commit 2782475c4f9700d57bfa56ec58f169203140c744 Author: claunia Date: Fri Oct 9 00:08:02 2009 +0000 Just configured from Wine's GIT svn path=/; revision=1 diff --git a/.git/HEAD b/.git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/.git/config b/.git/config new file mode 100644 index 0000000..d4a6d82 --- /dev/null +++ b/.git/config @@ -0,0 +1,12 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = http://source.winehq.org/git/appdb.git/ +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/.git/description b/.git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/.git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/.git/hooks/applypatch-msg.sample b/.git/hooks/applypatch-msg.sample new file mode 100755 index 0000000..8b2a2fe --- /dev/null +++ b/.git/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +test -x "$GIT_DIR/hooks/commit-msg" && + exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} +: diff --git a/.git/hooks/commit-msg.sample b/.git/hooks/commit-msg.sample new file mode 100755 index 0000000..6ef1d29 --- /dev/null +++ b/.git/hooks/commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by git-commit with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/.git/hooks/post-commit.sample b/.git/hooks/post-commit.sample new file mode 100755 index 0000000..2266821 --- /dev/null +++ b/.git/hooks/post-commit.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script that is called after a successful +# commit is made. +# +# To enable this hook, rename this file to "post-commit". + +: Nothing diff --git a/.git/hooks/post-receive.sample b/.git/hooks/post-receive.sample new file mode 100755 index 0000000..18d2e0f --- /dev/null +++ b/.git/hooks/post-receive.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script for the "post-receive" event. +# +# The "post-receive" script is run after receive-pack has accepted a pack +# and the repository has been updated. It is passed arguments in through +# stdin in the form +# +# For example: +# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master +# +# see contrib/hooks/ for an sample, or uncomment the next line and +# rename the file to "post-receive". + +#. /usr/share/doc/git-core/contrib/hooks/post-receive-email diff --git a/.git/hooks/post-update.sample b/.git/hooks/post-update.sample new file mode 100755 index 0000000..5323b56 --- /dev/null +++ b/.git/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git-update-server-info diff --git a/.git/hooks/pre-applypatch.sample b/.git/hooks/pre-applypatch.sample new file mode 100755 index 0000000..b1f187c --- /dev/null +++ b/.git/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} +: diff --git a/.git/hooks/pre-commit.sample b/.git/hooks/pre-commit.sample new file mode 100755 index 0000000..b11ad6a --- /dev/null +++ b/.git/hooks/pre-commit.sample @@ -0,0 +1,43 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by git-commit with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +# If you want to allow non-ascii filenames set this variable to true. +allownonascii=$(git config hooks.allownonascii) + +# Cross platform projects tend to avoid non-ascii filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + test "$(git diff --cached --name-only --diff-filter=A -z | + LC_ALL=C tr -d '[ -~]\0')" +then + echo "Error: Attempt to add a non-ascii filename." + echo + echo "This can cause problems if you want to work together" + echo "with people on other platforms than you." + echo + echo "To be portable it is adviseable to rename the file ..." + echo + echo "If you know what you are doing you can disable this" + echo "check using:" + echo + echo " git config hooks.allownonascii true" + echo + exit 1 +fi + +if git-rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +exec git diff-index --check --cached $against -- diff --git a/.git/hooks/pre-rebase.sample b/.git/hooks/pre-rebase.sample new file mode 100755 index 0000000..be1b06e --- /dev/null +++ b/.git/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git-rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git-rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git-rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git-rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up-to-date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"` + perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +exit 0 + +################################################################ + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git-rev-list ^master ^topic next + git-rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git-rev-list master..topic + + if this is empty, it is fully merged to "master". diff --git a/.git/hooks/prepare-commit-msg.sample b/.git/hooks/prepare-commit-msg.sample new file mode 100755 index 0000000..3652424 --- /dev/null +++ b/.git/hooks/prepare-commit-msg.sample @@ -0,0 +1,36 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by git-commit with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first comments out the +# "Conflicts:" part of a merge commit. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +case "$2,$3" in + merge,) + perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; + +# ,|template,) +# perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$1" ;; + + *) ;; +esac + +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff --git a/.git/hooks/update.sample b/.git/hooks/update.sample new file mode 100755 index 0000000..fd63b2d --- /dev/null +++ b/.git/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to blocks unannotated tags from entering. +# Called by git-receive-pack with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --bool hooks.allowunannotated) +allowdeletebranch=$(git config --bool hooks.allowdeletebranch) +denycreatebranch=$(git config --bool hooks.denycreatebranch) +allowdeletetag=$(git config --bool hooks.allowdeletetag) +allowmodifytag=$(git config --bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero="0000000000000000000000000000000000000000" +if [ "$newrev" = "$zero" ]; then + newrev_type=delete +else + newrev_type=$(git-cat-file -t $newrev) +fi + +case "$refname","$newrev_type" in + refs/tags/*,commit) + # un-annotated tag + short_refname=${refname##refs/tags/} + if [ "$allowunannotated" != "true" ]; then + echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/.git/index b/.git/index new file mode 100644 index 0000000..2a722cd Binary files /dev/null and b/.git/index differ diff --git a/.git/info/exclude b/.git/info/exclude new file mode 100644 index 0000000..2c87b72 --- /dev/null +++ b/.git/info/exclude @@ -0,0 +1,6 @@ +# git-ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/.git/logs/HEAD b/.git/logs/HEAD new file mode 100644 index 0000000..25e7587 --- /dev/null +++ b/.git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 5a9e078df620ab1f29ace3f9f6f78ced726c762b Natalia Portillo 1254963405 +0100 clone: from http://source.winehq.org/git/appdb.git/ diff --git a/.git/logs/refs/heads/master b/.git/logs/refs/heads/master new file mode 100644 index 0000000..25e7587 --- /dev/null +++ b/.git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 5a9e078df620ab1f29ace3f9f6f78ced726c762b Natalia Portillo 1254963405 +0100 clone: from http://source.winehq.org/git/appdb.git/ diff --git a/.git/logs/refs/remotes/origin/HEAD b/.git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..25e7587 --- /dev/null +++ b/.git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 5a9e078df620ab1f29ace3f9f6f78ced726c762b Natalia Portillo 1254963405 +0100 clone: from http://source.winehq.org/git/appdb.git/ diff --git a/.git/objects/00/01b42f6656882195cf50659811428b9265e4aa b/.git/objects/00/01b42f6656882195cf50659811428b9265e4aa new file mode 100644 index 0000000..3e3b75b Binary files /dev/null and b/.git/objects/00/01b42f6656882195cf50659811428b9265e4aa differ diff --git a/.git/objects/00/054db8e74f7bbae254a86e8e2ae2b8356f5496 b/.git/objects/00/054db8e74f7bbae254a86e8e2ae2b8356f5496 new file mode 100644 index 0000000..1317ee0 Binary files /dev/null and b/.git/objects/00/054db8e74f7bbae254a86e8e2ae2b8356f5496 differ diff --git a/.git/objects/00/139640e82a15073aac580ed3bc433a59048d72 b/.git/objects/00/139640e82a15073aac580ed3bc433a59048d72 new file mode 100644 index 0000000..462c559 Binary files /dev/null and b/.git/objects/00/139640e82a15073aac580ed3bc433a59048d72 differ diff --git a/.git/objects/00/48da7134eed3d342b4c05ab75753a467668664 b/.git/objects/00/48da7134eed3d342b4c05ab75753a467668664 new file mode 100644 index 0000000..be02146 Binary files /dev/null and b/.git/objects/00/48da7134eed3d342b4c05ab75753a467668664 differ diff --git a/.git/objects/00/7296a118638ebcd8788729ab270864511c8f20 b/.git/objects/00/7296a118638ebcd8788729ab270864511c8f20 new file mode 100644 index 0000000..f590cb6 Binary files /dev/null and b/.git/objects/00/7296a118638ebcd8788729ab270864511c8f20 differ diff --git a/.git/objects/00/81e4ca812638250ac50653a617fed4ef480313 b/.git/objects/00/81e4ca812638250ac50653a617fed4ef480313 new file mode 100644 index 0000000..47308cf Binary files /dev/null and b/.git/objects/00/81e4ca812638250ac50653a617fed4ef480313 differ diff --git a/.git/objects/00/83a67fa562a7b608d290b85ff7d5f4906e3ad9 b/.git/objects/00/83a67fa562a7b608d290b85ff7d5f4906e3ad9 new file mode 100644 index 0000000..a808d54 Binary files /dev/null and b/.git/objects/00/83a67fa562a7b608d290b85ff7d5f4906e3ad9 differ diff --git a/.git/objects/00/f9a20596bf14a5b72b697016a999fbaced0318 b/.git/objects/00/f9a20596bf14a5b72b697016a999fbaced0318 new file mode 100644 index 0000000..a581021 --- /dev/null +++ b/.git/objects/00/f9a20596bf14a5b72b697016a999fbaced0318 @@ -0,0 +1,2 @@ +xAN09sGBדpL3^9Fqc[n+sWx+7a3e'[daCw"A„Ĩiӄ蜥Q;k.r/JA +EW:vIp.Ivx*kd% npn{]s8E.\_)".k@Ԧ倸=Gj \ No newline at end of file diff --git a/.git/objects/01/26067319b91e45c0c7b2b564bb2531351587e7 b/.git/objects/01/26067319b91e45c0c7b2b564bb2531351587e7 new file mode 100644 index 0000000..14c2031 Binary files /dev/null and b/.git/objects/01/26067319b91e45c0c7b2b564bb2531351587e7 differ diff --git a/.git/objects/01/2c845238e57ac1ea2708515d656eab1061dc9a b/.git/objects/01/2c845238e57ac1ea2708515d656eab1061dc9a new file mode 100644 index 0000000..4c22dd3 Binary files /dev/null and b/.git/objects/01/2c845238e57ac1ea2708515d656eab1061dc9a differ diff --git a/.git/objects/01/36e4a92bdefe7943f9fa9f8eb8d45d691a40d5 b/.git/objects/01/36e4a92bdefe7943f9fa9f8eb8d45d691a40d5 new file mode 100644 index 0000000..663e7b3 --- /dev/null +++ b/.git/objects/01/36e4a92bdefe7943f9fa9f8eb8d45d691a40d5 @@ -0,0 +1,2 @@ +xKJ1Ego-/|Aıϋ!I[ˁsZß  3)h6ɹ+’fW? +m6GR*1ڰm}; AG ^_y=ANc>^_ aڬpANz] fciPф~((1gkn]u.q\n?qX{?. B\|BX>J 1mGt~ \ \ No newline at end of file diff --git a/.git/objects/01/7ed62ad51c2e32835c8ca4eb9333dccd12e14c b/.git/objects/01/7ed62ad51c2e32835c8ca4eb9333dccd12e14c new file mode 100644 index 0000000..58dc17d Binary files /dev/null and b/.git/objects/01/7ed62ad51c2e32835c8ca4eb9333dccd12e14c differ diff --git a/.git/objects/01/8304081d7ed0231ab34a1d7b048557944a21c1 b/.git/objects/01/8304081d7ed0231ab34a1d7b048557944a21c1 new file mode 100644 index 0000000..4167744 Binary files /dev/null and b/.git/objects/01/8304081d7ed0231ab34a1d7b048557944a21c1 differ diff --git a/.git/objects/01/bc58552afe3f7248fcde3d683a5275fdc56a69 b/.git/objects/01/bc58552afe3f7248fcde3d683a5275fdc56a69 new file mode 100644 index 0000000..95bddb5 Binary files /dev/null and b/.git/objects/01/bc58552afe3f7248fcde3d683a5275fdc56a69 differ diff --git a/.git/objects/01/dc82bc53dd792d08219709a49f5ba1995c22a0 b/.git/objects/01/dc82bc53dd792d08219709a49f5ba1995c22a0 new file mode 100644 index 0000000..01e64c1 Binary files /dev/null and b/.git/objects/01/dc82bc53dd792d08219709a49f5ba1995c22a0 differ diff --git a/.git/objects/01/e9607cd59e04678ea50766744a84e9416d8385 b/.git/objects/01/e9607cd59e04678ea50766744a84e9416d8385 new file mode 100644 index 0000000..f96e970 Binary files /dev/null and b/.git/objects/01/e9607cd59e04678ea50766744a84e9416d8385 differ diff --git a/.git/objects/02/2459cde23e1306822485d0f4386ba6ecb3a8d9 b/.git/objects/02/2459cde23e1306822485d0f4386ba6ecb3a8d9 new file mode 100644 index 0000000..ecc997a Binary files /dev/null and b/.git/objects/02/2459cde23e1306822485d0f4386ba6ecb3a8d9 differ diff --git a/.git/objects/02/2a100d94d498b5d0b144c614edbe7f1739933f b/.git/objects/02/2a100d94d498b5d0b144c614edbe7f1739933f new file mode 100644 index 0000000..afd23b0 Binary files /dev/null and b/.git/objects/02/2a100d94d498b5d0b144c614edbe7f1739933f differ diff --git a/.git/objects/02/5cd92d632343cfd707a4648d3a61803cad22e4 b/.git/objects/02/5cd92d632343cfd707a4648d3a61803cad22e4 new file mode 100644 index 0000000..7d32017 Binary files /dev/null and b/.git/objects/02/5cd92d632343cfd707a4648d3a61803cad22e4 differ diff --git a/.git/objects/02/8d51d85dbc16a2f3f592ccf85ed9c58a79c817 b/.git/objects/02/8d51d85dbc16a2f3f592ccf85ed9c58a79c817 new file mode 100644 index 0000000..27763ec --- /dev/null +++ b/.git/objects/02/8d51d85dbc16a2f3f592ccf85ed9c58a79c817 @@ -0,0 +1,3 @@ +x=N@ s +w[ 3B+()ALMf ?{3z.d{zp*3ML "a.DPSBF33d8L;p@}>,Me +/K3]7.S opO>gD')׻,~uq6­qtzU9}J㧲]87x[ 2.3:qmMh \ No newline at end of file diff --git a/.git/objects/02/8edb6c8806bc9aa38f45ad14d4857881cf9979 b/.git/objects/02/8edb6c8806bc9aa38f45ad14d4857881cf9979 new file mode 100644 index 0000000..cd74859 Binary files /dev/null and b/.git/objects/02/8edb6c8806bc9aa38f45ad14d4857881cf9979 differ diff --git a/.git/objects/02/94f01c3f1bed540dd7030969ebde83b879611b b/.git/objects/02/94f01c3f1bed540dd7030969ebde83b879611b new file mode 100644 index 0000000..fdd2d9f --- /dev/null +++ b/.git/objects/02/94f01c3f1bed540dd7030969ebde83b879611b @@ -0,0 +1,2 @@ +xAN09s_ p㉳ +3| xVuI>#HF,wȂ#'17^P< b#"Q|ok/sl|1wgq퓲Qɡ1f6Zv9&vW菨t½:v+|pB=_bK \ No newline at end of file diff --git a/.git/objects/02/f40e5bd4da88e96b01f9aa71050ebfb40be431 b/.git/objects/02/f40e5bd4da88e96b01f9aa71050ebfb40be431 new file mode 100644 index 0000000..ec37bd3 Binary files /dev/null and b/.git/objects/02/f40e5bd4da88e96b01f9aa71050ebfb40be431 differ diff --git a/.git/objects/02/f54da8cad08c3ec1f0dcf0128a46af68af9b61 b/.git/objects/02/f54da8cad08c3ec1f0dcf0128a46af68af9b61 new file mode 100644 index 0000000..7a8e7de Binary files /dev/null and b/.git/objects/02/f54da8cad08c3ec1f0dcf0128a46af68af9b61 differ diff --git a/.git/objects/03/39fa60c2a467e49649e5bbc563eec81e6f9a39 b/.git/objects/03/39fa60c2a467e49649e5bbc563eec81e6f9a39 new file mode 100644 index 0000000..0ae9fca --- /dev/null +++ b/.git/objects/03/39fa60c2a467e49649e5bbc563eec81e6f9a39 @@ -0,0 +1,2 @@ +x9N1}4"!D.@\y̌#C\_MtZ:(nz#nVHBIZ'd+6*E'<;D W (9F>#}bIyxj6x>Qkzz!^iKpw?^Z!%ZLؗZ/K"([mۼl~mA(٨'#\@(& +g?X^{ \ No newline at end of file diff --git a/.git/objects/03/73d15ce396a988819668b767341109e3fc2b6d b/.git/objects/03/73d15ce396a988819668b767341109e3fc2b6d new file mode 100644 index 0000000..b77e578 Binary files /dev/null and b/.git/objects/03/73d15ce396a988819668b767341109e3fc2b6d differ diff --git a/.git/objects/03/7c0a63656e654bebc12fdadd4fca454a2c4cf8 b/.git/objects/03/7c0a63656e654bebc12fdadd4fca454a2c4cf8 new file mode 100644 index 0000000..7a17acf Binary files /dev/null and b/.git/objects/03/7c0a63656e654bebc12fdadd4fca454a2c4cf8 differ diff --git a/.git/objects/03/b56f240562b2451d358eef2c22c93764255c71 b/.git/objects/03/b56f240562b2451d358eef2c22c93764255c71 new file mode 100644 index 0000000..272c873 Binary files /dev/null and b/.git/objects/03/b56f240562b2451d358eef2c22c93764255c71 differ diff --git a/.git/objects/03/b59209793072ec14aeddb7c6c6bdb3cbb669b4 b/.git/objects/03/b59209793072ec14aeddb7c6c6bdb3cbb669b4 new file mode 100644 index 0000000..44c3f8e Binary files /dev/null and b/.git/objects/03/b59209793072ec14aeddb7c6c6bdb3cbb669b4 differ diff --git a/.git/objects/03/b614fd1003642a1c6d4e3b3391a123d4d2dd8f b/.git/objects/03/b614fd1003642a1c6d4e3b3391a123d4d2dd8f new file mode 100644 index 0000000..71c9ef5 Binary files /dev/null and b/.git/objects/03/b614fd1003642a1c6d4e3b3391a123d4d2dd8f differ diff --git a/.git/objects/03/bd92dd3529601e7fad7def2300767159a0ed23 b/.git/objects/03/bd92dd3529601e7fad7def2300767159a0ed23 new file mode 100644 index 0000000..8837a0e Binary files /dev/null and b/.git/objects/03/bd92dd3529601e7fad7def2300767159a0ed23 differ diff --git a/.git/objects/03/fa3f1c7f1c5f3a80d2e3b53894f52a8b37955a b/.git/objects/03/fa3f1c7f1c5f3a80d2e3b53894f52a8b37955a new file mode 100644 index 0000000..af97fbd Binary files /dev/null and b/.git/objects/03/fa3f1c7f1c5f3a80d2e3b53894f52a8b37955a differ diff --git a/.git/objects/04/057ee34b027abd5479645f4d7e90e83083ddee b/.git/objects/04/057ee34b027abd5479645f4d7e90e83083ddee new file mode 100644 index 0000000..627521d --- /dev/null +++ b/.git/objects/04/057ee34b027abd5479645f4d7e90e83083ddee @@ -0,0 +1,2 @@ +x-Mj0 F)/aJfNĐqHfb5}zB˲\VD0a,PjtƩ +8EArF. |t8ML_>Qwʹ&J^e8:9g3 K g\r:tuڱ+]愔 ehG~BW \ No newline at end of file diff --git a/.git/objects/04/060f0964d7be10e46ae7034c7f96a7b33fa922 b/.git/objects/04/060f0964d7be10e46ae7034c7f96a7b33fa922 new file mode 100644 index 0000000..da59539 Binary files /dev/null and b/.git/objects/04/060f0964d7be10e46ae7034c7f96a7b33fa922 differ diff --git a/.git/objects/04/19168192970f4fc4427399682e6f571660ebe5 b/.git/objects/04/19168192970f4fc4427399682e6f571660ebe5 new file mode 100644 index 0000000..b5c7b71 Binary files /dev/null and b/.git/objects/04/19168192970f4fc4427399682e6f571660ebe5 differ diff --git a/.git/objects/04/1d0d2bc32a50968ff0c034daad036d5bd73d5a b/.git/objects/04/1d0d2bc32a50968ff0c034daad036d5bd73d5a new file mode 100644 index 0000000..0b2c3c6 --- /dev/null +++ b/.git/objects/04/1d0d2bc32a50968ff0c034daad036d5bd73d5a @@ -0,0 +1 @@ +x=j0D{W=Ԭ,ɶ @n@oze+F)mybƺ{ݱ tnĖ-S1S0vA0vl48ۣ1ք+Y2r<>η2%$jTsL:e 9 $OgJ=՟kyuxFsվ1L"~Yk"r}۪oдS \ No newline at end of file diff --git a/.git/objects/04/2dfaac387e52a91568cf0f61da71023a41eb12 b/.git/objects/04/2dfaac387e52a91568cf0f61da71023a41eb12 new file mode 100644 index 0000000..7416190 Binary files /dev/null and b/.git/objects/04/2dfaac387e52a91568cf0f61da71023a41eb12 differ diff --git a/.git/objects/04/73f7bfc3f31eb3a58ab6fadbeae31af6988c62 b/.git/objects/04/73f7bfc3f31eb3a58ab6fadbeae31af6988c62 new file mode 100644 index 0000000..4dd167c --- /dev/null +++ b/.git/objects/04/73f7bfc3f31eb3a58ab6fadbeae31af6988c62 @@ -0,0 +1 @@ +x=N0s鑐8Vhi(i8$3DJ<,s1L 鍲sӆA[P9>1FE|`T@aɶ#R! Ay]h)Z^&qy2Txt<>Cmgz{ J+Զ.?ch|$H>"H{^6(7, HZpyg_l \ No newline at end of file diff --git a/.git/objects/04/7c4c0ed325a883c3f05fd56b9d6dc77629fbee b/.git/objects/04/7c4c0ed325a883c3f05fd56b9d6dc77629fbee new file mode 100644 index 0000000..7de2ac3 Binary files /dev/null and b/.git/objects/04/7c4c0ed325a883c3f05fd56b9d6dc77629fbee differ diff --git a/.git/objects/04/94354f0e8e6b494480a3cb98f408aae2a4747d b/.git/objects/04/94354f0e8e6b494480a3cb98f408aae2a4747d new file mode 100644 index 0000000..6614aa5 Binary files /dev/null and b/.git/objects/04/94354f0e8e6b494480a3cb98f408aae2a4747d differ diff --git a/.git/objects/04/a2178d15ed7c1b415e79ae53d69f8d1858a66a b/.git/objects/04/a2178d15ed7c1b415e79ae53d69f8d1858a66a new file mode 100644 index 0000000..50bc1dd Binary files /dev/null and b/.git/objects/04/a2178d15ed7c1b415e79ae53d69f8d1858a66a differ diff --git a/.git/objects/04/affed54b1a3b482e161389badf1ec910df3711 b/.git/objects/04/affed54b1a3b482e161389badf1ec910df3711 new file mode 100644 index 0000000..fc53896 Binary files /dev/null and b/.git/objects/04/affed54b1a3b482e161389badf1ec910df3711 differ diff --git a/.git/objects/04/ba7d3b4cef121bad4d74f9f0dc92cd4abefb6e b/.git/objects/04/ba7d3b4cef121bad4d74f9f0dc92cd4abefb6e new file mode 100644 index 0000000..e85449d Binary files /dev/null and b/.git/objects/04/ba7d3b4cef121bad4d74f9f0dc92cd4abefb6e differ diff --git a/.git/objects/04/dbeae441778c5f48b6eea36cc16fb0e7c6ca09 b/.git/objects/04/dbeae441778c5f48b6eea36cc16fb0e7c6ca09 new file mode 100644 index 0000000..4ace1a5 Binary files /dev/null and b/.git/objects/04/dbeae441778c5f48b6eea36cc16fb0e7c6ca09 differ diff --git a/.git/objects/05/070e6a3a92b375ad5d3a60b4daa0b893f19c10 b/.git/objects/05/070e6a3a92b375ad5d3a60b4daa0b893f19c10 new file mode 100644 index 0000000..9955631 --- /dev/null +++ b/.git/objects/05/070e6a3a92b375ad5d3a60b4daa0b893f19c10 @@ -0,0 +1,2 @@ +x;N0E3v2B n`sbǑ? 'hhnqѱ)PA]D +ƍ$"i9iNkHvv̴UBk5 (s{<^jE%ex^r(pIy l'\[{ɵG`lbp?a-?]&@k؅*$A^pÙ\^^@Xq\д]__ R4Gj} v: \ No newline at end of file diff --git a/.git/objects/05/30664a8cf1d129efa73e28b7461661937008da b/.git/objects/05/30664a8cf1d129efa73e28b7461661937008da new file mode 100644 index 0000000..36176f4 Binary files /dev/null and b/.git/objects/05/30664a8cf1d129efa73e28b7461661937008da differ diff --git a/.git/objects/05/35a9e4513c8f71564b8f95d359e0b3c0eed2cc b/.git/objects/05/35a9e4513c8f71564b8f95d359e0b3c0eed2cc new file mode 100644 index 0000000..ca30827 Binary files /dev/null and b/.git/objects/05/35a9e4513c8f71564b8f95d359e0b3c0eed2cc differ diff --git a/.git/objects/05/5a53077f121e5886bd2ebfdd5ba3f380320392 b/.git/objects/05/5a53077f121e5886bd2ebfdd5ba3f380320392 new file mode 100644 index 0000000..c75713e Binary files /dev/null and b/.git/objects/05/5a53077f121e5886bd2ebfdd5ba3f380320392 differ diff --git a/.git/objects/05/62985244e90a1a6881af0179b32218fb8399c0 b/.git/objects/05/62985244e90a1a6881af0179b32218fb8399c0 new file mode 100644 index 0000000..4190ef1 Binary files /dev/null and b/.git/objects/05/62985244e90a1a6881af0179b32218fb8399c0 differ diff --git a/.git/objects/05/8eba4b4ff88e10c54db21d2306eb0d34fbcbed b/.git/objects/05/8eba4b4ff88e10c54db21d2306eb0d34fbcbed new file mode 100644 index 0000000..236e878 --- /dev/null +++ b/.git/objects/05/8eba4b4ff88e10c54db21d2306eb0d34fbcbed @@ -0,0 +1,4 @@ +x%NMN vSZk2ѭn<GKB:7s$m$"v&Ą(:4H ]' +$":$NH703q><U3N2\tUoeZs +WJ#5KyYӬ\nz=}K=J5޼ub!8z}! +V] \ No newline at end of file diff --git a/.git/objects/05/b1d5cca11feed93c2a315c416190cec1f07418 b/.git/objects/05/b1d5cca11feed93c2a315c416190cec1f07418 new file mode 100644 index 0000000..47c2502 Binary files /dev/null and b/.git/objects/05/b1d5cca11feed93c2a315c416190cec1f07418 differ diff --git a/.git/objects/05/edd8a4c5678ce3e8563b447de9c10ac8f66a12 b/.git/objects/05/edd8a4c5678ce3e8563b447de9c10ac8f66a12 new file mode 100644 index 0000000..41b6bbf Binary files /dev/null and b/.git/objects/05/edd8a4c5678ce3e8563b447de9c10ac8f66a12 differ diff --git a/.git/objects/05/efcd1ebbe5cc1e07d482faf69fb6ce36460fa9 b/.git/objects/05/efcd1ebbe5cc1e07d482faf69fb6ce36460fa9 new file mode 100644 index 0000000..94f96d8 Binary files /dev/null and b/.git/objects/05/efcd1ebbe5cc1e07d482faf69fb6ce36460fa9 differ diff --git a/.git/objects/05/fd02298a6c485adee842c4a33de485035f02e4 b/.git/objects/05/fd02298a6c485adee842c4a33de485035f02e4 new file mode 100644 index 0000000..09062b7 Binary files /dev/null and b/.git/objects/05/fd02298a6c485adee842c4a33de485035f02e4 differ diff --git a/.git/objects/05/ff1aba0506289d4f4e23324fbacb479a32e4a0 b/.git/objects/05/ff1aba0506289d4f4e23324fbacb479a32e4a0 new file mode 100644 index 0000000..9808439 Binary files /dev/null and b/.git/objects/05/ff1aba0506289d4f4e23324fbacb479a32e4a0 differ diff --git a/.git/objects/06/05c81994df22d1b78db47451f301c6393d582b b/.git/objects/06/05c81994df22d1b78db47451f301c6393d582b new file mode 100644 index 0000000..8bb2386 Binary files /dev/null and b/.git/objects/06/05c81994df22d1b78db47451f301c6393d582b differ diff --git a/.git/objects/06/33c007da00952d7874a95ac5d6e8554bf5a888 b/.git/objects/06/33c007da00952d7874a95ac5d6e8554bf5a888 new file mode 100644 index 0000000..90e22d9 Binary files /dev/null and b/.git/objects/06/33c007da00952d7874a95ac5d6e8554bf5a888 differ diff --git a/.git/objects/06/4d8909796de0225a3c6a5f3ca7ee11064c82c3 b/.git/objects/06/4d8909796de0225a3c6a5f3ca7ee11064c82c3 new file mode 100644 index 0000000..15bb2f8 Binary files /dev/null and b/.git/objects/06/4d8909796de0225a3c6a5f3ca7ee11064c82c3 differ diff --git a/.git/objects/06/533d8dc9a0012fd2be132a3ea173586466bb97 b/.git/objects/06/533d8dc9a0012fd2be132a3ea173586466bb97 new file mode 100644 index 0000000..0b60bc3 Binary files /dev/null and b/.git/objects/06/533d8dc9a0012fd2be132a3ea173586466bb97 differ diff --git a/.git/objects/06/6e5610db897ede5ac2fdeaa02e3d734dee3c57 b/.git/objects/06/6e5610db897ede5ac2fdeaa02e3d734dee3c57 new file mode 100644 index 0000000..a8e010b Binary files /dev/null and b/.git/objects/06/6e5610db897ede5ac2fdeaa02e3d734dee3c57 differ diff --git a/.git/objects/06/72604b8d7e03e6b838f78a99afbfa2b64b50c8 b/.git/objects/06/72604b8d7e03e6b838f78a99afbfa2b64b50c8 new file mode 100644 index 0000000..622f4a6 Binary files /dev/null and b/.git/objects/06/72604b8d7e03e6b838f78a99afbfa2b64b50c8 differ diff --git a/.git/objects/06/757c64e53fdecaaefc5aed7863c8bb37c78763 b/.git/objects/06/757c64e53fdecaaefc5aed7863c8bb37c78763 new file mode 100644 index 0000000..b9358fe Binary files /dev/null and b/.git/objects/06/757c64e53fdecaaefc5aed7863c8bb37c78763 differ diff --git a/.git/objects/06/87e88543c4e7e4cd7416e92bea4e29d5159381 b/.git/objects/06/87e88543c4e7e4cd7416e92bea4e29d5159381 new file mode 100644 index 0000000..addd667 Binary files /dev/null and b/.git/objects/06/87e88543c4e7e4cd7416e92bea4e29d5159381 differ diff --git a/.git/objects/06/904156a3ff576ae52a8b9d18b8289b3b9f8445 b/.git/objects/06/904156a3ff576ae52a8b9d18b8289b3b9f8445 new file mode 100644 index 0000000..63f7d5a Binary files /dev/null and b/.git/objects/06/904156a3ff576ae52a8b9d18b8289b3b9f8445 differ diff --git a/.git/objects/06/dd5243a02fe2ac9ad444a4240c4fc0de561d41 b/.git/objects/06/dd5243a02fe2ac9ad444a4240c4fc0de561d41 new file mode 100644 index 0000000..3949a7a Binary files /dev/null and b/.git/objects/06/dd5243a02fe2ac9ad444a4240c4fc0de561d41 differ diff --git a/.git/objects/06/eadf0a293c0a322b3e6811f95c2b48476b9f46 b/.git/objects/06/eadf0a293c0a322b3e6811f95c2b48476b9f46 new file mode 100644 index 0000000..2763302 --- /dev/null +++ b/.git/objects/06/eadf0a293c0a322b3e6811f95c2b48476b9f46 @@ -0,0 +1 @@ +x=N0FsW bGBhi(i{DؑH7b|޶B|0z,ܠ!JАv**0FT(iAXmrh$Fvr:+)._?%4q,g> \ No newline at end of file diff --git a/.git/objects/06/ef247e954ccb9d895da6114b3c5e5e6afe6b71 b/.git/objects/06/ef247e954ccb9d895da6114b3c5e5e6afe6b71 new file mode 100644 index 0000000..f8291d8 Binary files /dev/null and b/.git/objects/06/ef247e954ccb9d895da6114b3c5e5e6afe6b71 differ diff --git a/.git/objects/06/f693859fbf3dba9e22a82e3811ec004be56076 b/.git/objects/06/f693859fbf3dba9e22a82e3811ec004be56076 new file mode 100644 index 0000000..560bd29 --- /dev/null +++ b/.git/objects/06/f693859fbf3dba9e22a82e3811ec004be56076 @@ -0,0 +1,2 @@ +x%N0ۥ@D1:CBOgo.bp=/hfѸR@uS23HD> +7ɎFzMŒls̱ki{:z";XfyV v)_=gx]\ZqyXfk%MtNڹm`Pn]Ӝ ^R>S Hұq#PW)g*to)0;[( ڭPX \ No newline at end of file diff --git a/.git/objects/07/0df9daca87fd782b4b78285621f33929aa131a b/.git/objects/07/0df9daca87fd782b4b78285621f33929aa131a new file mode 100644 index 0000000..a5f8922 --- /dev/null +++ b/.git/objects/07/0df9daca87fd782b4b78285621f33929aa131a @@ -0,0 +1,3 @@ +x-An E)f_5*U&'!a47uף2ϩAoS@" KFim-zڅ+#I!0ad#/V.HAuxmTx +ʄ3jv9T}Ce~)UE/DG|Ě8z ;au.i= /BxWܙ0+cZ*QdZR* +x!`?8ue \ No newline at end of file diff --git a/.git/objects/07/46379e124221d477bd6ba90f0090c26b99d2db b/.git/objects/07/46379e124221d477bd6ba90f0090c26b99d2db new file mode 100644 index 0000000..f1275bd Binary files /dev/null and b/.git/objects/07/46379e124221d477bd6ba90f0090c26b99d2db differ diff --git a/.git/objects/07/609e1723f1ad9aa561b2bdfa45d4eb9d6300bb b/.git/objects/07/609e1723f1ad9aa561b2bdfa45d4eb9d6300bb new file mode 100644 index 0000000..3b92932 Binary files /dev/null and b/.git/objects/07/609e1723f1ad9aa561b2bdfa45d4eb9d6300bb differ diff --git a/.git/objects/07/76bdeeb94fadb500a6ee66ad14774ca0f3543b b/.git/objects/07/76bdeeb94fadb500a6ee66ad14774ca0f3543b new file mode 100644 index 0000000..04f0aea Binary files /dev/null and b/.git/objects/07/76bdeeb94fadb500a6ee66ad14774ca0f3543b differ diff --git a/.git/objects/07/7ecab9f9044a593af0a70266149e5557442c33 b/.git/objects/07/7ecab9f9044a593af0a70266149e5557442c33 new file mode 100644 index 0000000..a4d3dba --- /dev/null +++ b/.git/objects/07/7ecab9f9044a593af0a70266149e5557442c33 @@ -0,0 +1 @@ +xMN0Y@cObB !qc)Sסs1|Oy]c^0M{숄;1)%H']oF5mT8)A:v"cJ [#: (M\# ~J /uErSN'gJhPBtMmܵbok{i}[ڰ*:7טN@rz<mj \ No newline at end of file diff --git a/.git/objects/07/8f52775a3c0e841cb5d1d9e3bb2bc3b2cf3c6c b/.git/objects/07/8f52775a3c0e841cb5d1d9e3bb2bc3b2cf3c6c new file mode 100644 index 0000000..0137a8e Binary files /dev/null and b/.git/objects/07/8f52775a3c0e841cb5d1d9e3bb2bc3b2cf3c6c differ diff --git a/.git/objects/07/a8d90af5b669d6863e90abd38b1e924a8a564c b/.git/objects/07/a8d90af5b669d6863e90abd38b1e924a8a564c new file mode 100644 index 0000000..3ba1e7a Binary files /dev/null and b/.git/objects/07/a8d90af5b669d6863e90abd38b1e924a8a564c differ diff --git a/.git/objects/07/b957bd67e5092960845662c658524b8ecc3dc4 b/.git/objects/07/b957bd67e5092960845662c658524b8ecc3dc4 new file mode 100644 index 0000000..5718db3 Binary files /dev/null and b/.git/objects/07/b957bd67e5092960845662c658524b8ecc3dc4 differ diff --git a/.git/objects/07/c42bd4031ab8b329b76ef297666dd1e914585d b/.git/objects/07/c42bd4031ab8b329b76ef297666dd1e914585d new file mode 100644 index 0000000..6079a6e Binary files /dev/null and b/.git/objects/07/c42bd4031ab8b329b76ef297666dd1e914585d differ diff --git a/.git/objects/07/dd1faadd2c4062147f4aafe3167cd6926ee4b0 b/.git/objects/07/dd1faadd2c4062147f4aafe3167cd6926ee4b0 new file mode 100644 index 0000000..4f6c27f Binary files /dev/null and b/.git/objects/07/dd1faadd2c4062147f4aafe3167cd6926ee4b0 differ diff --git a/.git/objects/08/03c10b088bf47671962dd33d4c4b571cfbe3de b/.git/objects/08/03c10b088bf47671962dd33d4c4b571cfbe3de new file mode 100644 index 0000000..4179534 Binary files /dev/null and b/.git/objects/08/03c10b088bf47671962dd33d4c4b571cfbe3de differ diff --git a/.git/objects/08/22b3c797187a62be98bab74f38d1a18770aed3 b/.git/objects/08/22b3c797187a62be98bab74f38d1a18770aed3 new file mode 100644 index 0000000..f69681a Binary files /dev/null and b/.git/objects/08/22b3c797187a62be98bab74f38d1a18770aed3 differ diff --git a/.git/objects/08/40a1e85cd4e7db317fa4b59654de0aa933f868 b/.git/objects/08/40a1e85cd4e7db317fa4b59654de0aa933f868 new file mode 100644 index 0000000..d074bd7 Binary files /dev/null and b/.git/objects/08/40a1e85cd4e7db317fa4b59654de0aa933f868 differ diff --git a/.git/objects/08/73a7940000a3810c3b929af592b57a53f12c5d b/.git/objects/08/73a7940000a3810c3b929af592b57a53f12c5d new file mode 100644 index 0000000..f67cfee Binary files /dev/null and b/.git/objects/08/73a7940000a3810c3b929af592b57a53f12c5d differ diff --git a/.git/objects/08/8746cb8a797eb54d850a776de88a3271908db1 b/.git/objects/08/8746cb8a797eb54d850a776de88a3271908db1 new file mode 100644 index 0000000..b33c331 Binary files /dev/null and b/.git/objects/08/8746cb8a797eb54d850a776de88a3271908db1 differ diff --git a/.git/objects/08/92d5a3ad2389269dd43484dacbac983258ef08 b/.git/objects/08/92d5a3ad2389269dd43484dacbac983258ef08 new file mode 100644 index 0000000..80037ff Binary files /dev/null and b/.git/objects/08/92d5a3ad2389269dd43484dacbac983258ef08 differ diff --git a/.git/objects/08/c347370d879b41e1bdf9d41c08752fc07cb797 b/.git/objects/08/c347370d879b41e1bdf9d41c08752fc07cb797 new file mode 100644 index 0000000..f2556b3 Binary files /dev/null and b/.git/objects/08/c347370d879b41e1bdf9d41c08752fc07cb797 differ diff --git a/.git/objects/08/cb9d21900a0f6968d96c0b151b1a56994ca50b b/.git/objects/08/cb9d21900a0f6968d96c0b151b1a56994ca50b new file mode 100644 index 0000000..c8c3724 Binary files /dev/null and b/.git/objects/08/cb9d21900a0f6968d96c0b151b1a56994ca50b differ diff --git a/.git/objects/08/e9a6930f6024d66f5de9e9d5887517cf12f8ff b/.git/objects/08/e9a6930f6024d66f5de9e9d5887517cf12f8ff new file mode 100644 index 0000000..16719c0 Binary files /dev/null and b/.git/objects/08/e9a6930f6024d66f5de9e9d5887517cf12f8ff differ diff --git a/.git/objects/09/158393459bddc40a2054773d4ff58624625858 b/.git/objects/09/158393459bddc40a2054773d4ff58624625858 new file mode 100644 index 0000000..552e801 Binary files /dev/null and b/.git/objects/09/158393459bddc40a2054773d4ff58624625858 differ diff --git a/.git/objects/09/466f59a1d26a8178607ee92442f058a59729e5 b/.git/objects/09/466f59a1d26a8178607ee92442f058a59729e5 new file mode 100644 index 0000000..9c33449 --- /dev/null +++ b/.git/objects/09/466f59a1d26a8178607ee92442f058a59729e5 @@ -0,0 +1 @@ +x[j0EUbf,a(,b4lA$Etm]Ε2`6zJ@Q7A&ӪĔK@rlQ=6mv6ZBb1rĠ7n.5>~Q ZzK8D%#SW~r(mٹm@WT \ No newline at end of file diff --git a/.git/objects/09/4a78fef8165d8abdda611bd5101add9ed02b52 b/.git/objects/09/4a78fef8165d8abdda611bd5101add9ed02b52 new file mode 100644 index 0000000..2b0df61 Binary files /dev/null and b/.git/objects/09/4a78fef8165d8abdda611bd5101add9ed02b52 differ diff --git a/.git/objects/09/6ae65cf20f21891e659b28f51aef25dadd9c05 b/.git/objects/09/6ae65cf20f21891e659b28f51aef25dadd9c05 new file mode 100644 index 0000000..5a9369f Binary files /dev/null and b/.git/objects/09/6ae65cf20f21891e659b28f51aef25dadd9c05 differ diff --git a/.git/objects/09/802d946080803da37b9258c7bf2327888d2d69 b/.git/objects/09/802d946080803da37b9258c7bf2327888d2d69 new file mode 100644 index 0000000..bc3d68d --- /dev/null +++ b/.git/objects/09/802d946080803da37b9258c7bf2327888d2d69 @@ -0,0 +1,2 @@ +x]iPg!ZV`J N `M݅lݸ! bKA+48UGAWTJZKmnd_?<4<@B?d Q_Biw'AW {;T4(E%u9ޛ*c/ɅfhJ> ŇGIup,XGW5g>AWڜ[谈8ymK䜸`6NCE.pf NLt(Nf?gr'R?vVǐmoic˃#مWO>\]|z:0I{΀O.U>'-S50DCxbYu٥GJIη`bSE>jKՃ~1oJn, ;v'. +ɹ);7]zkG,Z*) M/~K6 G4{7-RRt,۞i}+?4X5OᰰUvA*Bq7l;C{=&$6կ_+ݴF"j@ (ѨAE⚝df ~U}Ll[j8"psݫJ^\e(&PLo~oSuZz0("a&(N]Θ$:X|jױ~Nd(R-sCzu}¡;ZζTLӂ^ڋ%Yr5Y\.i7=> L %-a,Fzfy#pV(E}]2PJ@1#x>}5!^hp"w-!&G+9KFfXsՌ?Yv.(|͘,P߮[P<:?]R\uX \ No newline at end of file diff --git a/.git/objects/09/9c008a9330005c98d5794d2aeb5827de76fa8a b/.git/objects/09/9c008a9330005c98d5794d2aeb5827de76fa8a new file mode 100644 index 0000000..be9b9fe Binary files /dev/null and b/.git/objects/09/9c008a9330005c98d5794d2aeb5827de76fa8a differ diff --git a/.git/objects/09/c2ab3d9bc1fb3a1a4f2ca4192a22aeb7f92c4b b/.git/objects/09/c2ab3d9bc1fb3a1a4f2ca4192a22aeb7f92c4b new file mode 100644 index 0000000..3c04fb7 Binary files /dev/null and b/.git/objects/09/c2ab3d9bc1fb3a1a4f2ca4192a22aeb7f92c4b differ diff --git a/.git/objects/09/d96b79bd714283760acd8a2d74819c486cd3ba b/.git/objects/09/d96b79bd714283760acd8a2d74819c486cd3ba new file mode 100644 index 0000000..6aa2ae1 --- /dev/null +++ b/.git/objects/09/d96b79bd714283760acd8a2d74819c486cd3ba @@ -0,0 +1 @@ +x5N0D9+^8QZ!q _ĉl?H6=?c {P331{FHMZVu,6Vf̩t"aY v*%P>hVcCKN(4нpCR>03Cͻ?/ MB ~elrXpc6݊o 31TtWv \ No newline at end of file diff --git a/.git/objects/09/fa909d667ddd77e98dbc7ac13bf938a8e5d0b9 b/.git/objects/09/fa909d667ddd77e98dbc7ac13bf938a8e5d0b9 new file mode 100644 index 0000000..a631c2a Binary files /dev/null and b/.git/objects/09/fa909d667ddd77e98dbc7ac13bf938a8e5d0b9 differ diff --git a/.git/objects/0a/01271f34400881b1749b63ac56ebc7c7650694 b/.git/objects/0a/01271f34400881b1749b63ac56ebc7c7650694 new file mode 100644 index 0000000..57129a2 Binary files /dev/null and b/.git/objects/0a/01271f34400881b1749b63ac56ebc7c7650694 differ diff --git a/.git/objects/0a/305197fd2f4ee0e7cf35525f8f9ab9c232edc2 b/.git/objects/0a/305197fd2f4ee0e7cf35525f8f9ab9c232edc2 new file mode 100644 index 0000000..dad1135 --- /dev/null +++ b/.git/objects/0a/305197fd2f4ee0e7cf35525f8f9ab9c232edc2 @@ -0,0 +1,4 @@ +x%KN0YGT~$P+ְ{XJvTz3\ v>PhJb6N JI*i;!zcZ+14fhvJ +HZ-y e~[ε86t%&EqoJ>S ,Jhqq{ +5v +n.mI>{L3O\i=}'v5;y3x 7 SBN~>0>`C.^7 \ No newline at end of file diff --git a/.git/objects/0a/42c3e36ce3f0234e31fd0d5783e9d0fa0706cc b/.git/objects/0a/42c3e36ce3f0234e31fd0d5783e9d0fa0706cc new file mode 100644 index 0000000..60a346e Binary files /dev/null and b/.git/objects/0a/42c3e36ce3f0234e31fd0d5783e9d0fa0706cc differ diff --git a/.git/objects/0a/62d41cad06203da97a5a5b07d859f748a4df45 b/.git/objects/0a/62d41cad06203da97a5a5b07d859f748a4df45 new file mode 100644 index 0000000..49d86cc --- /dev/null +++ b/.git/objects/0a/62d41cad06203da97a5a5b07d859f748a4df45 @@ -0,0 +1,2 @@ +x;N1D}AHȿi{BlDFyff\ m7;+MBC'39;Ĩ9DMm +:Wєbr/RR@,8ES]˖ۉ.gp@c}ׁBo^rX6L pj N[aYwrQa \ No newline at end of file diff --git a/.git/objects/0a/8552911805763618fc89396b53c55e60690e75 b/.git/objects/0a/8552911805763618fc89396b53c55e60690e75 new file mode 100644 index 0000000..1047972 Binary files /dev/null and b/.git/objects/0a/8552911805763618fc89396b53c55e60690e75 differ diff --git a/.git/objects/0a/9665b24f1a650edd36eadb3bc765d60ea65d07 b/.git/objects/0a/9665b24f1a650edd36eadb3bc765d60ea65d07 new file mode 100644 index 0000000..048350e Binary files /dev/null and b/.git/objects/0a/9665b24f1a650edd36eadb3bc765d60ea65d07 differ diff --git a/.git/objects/0a/acf10858ebe0bc6adfa3c4620145c70dd054b5 b/.git/objects/0a/acf10858ebe0bc6adfa3c4620145c70dd054b5 new file mode 100644 index 0000000..82a7f6a Binary files /dev/null and b/.git/objects/0a/acf10858ebe0bc6adfa3c4620145c70dd054b5 differ diff --git a/.git/objects/0a/bd7d09e4588a8e77b26dbe2e05ca8ee75c4fcd b/.git/objects/0a/bd7d09e4588a8e77b26dbe2e05ca8ee75c4fcd new file mode 100644 index 0000000..5b89667 Binary files /dev/null and b/.git/objects/0a/bd7d09e4588a8e77b26dbe2e05ca8ee75c4fcd differ diff --git a/.git/objects/0a/c0604e2831f04a1af80ddb7a274c35479d7611 b/.git/objects/0a/c0604e2831f04a1af80ddb7a274c35479d7611 new file mode 100644 index 0000000..5abc88b Binary files /dev/null and b/.git/objects/0a/c0604e2831f04a1af80ddb7a274c35479d7611 differ diff --git a/.git/objects/0a/e61134c35cdb3c4678898cdaaa23b9a91c9042 b/.git/objects/0a/e61134c35cdb3c4678898cdaaa23b9a91c9042 new file mode 100644 index 0000000..aa4262c Binary files /dev/null and b/.git/objects/0a/e61134c35cdb3c4678898cdaaa23b9a91c9042 differ diff --git a/.git/objects/0a/fa3f7660ec70581c4af5b56ba23508701345fa b/.git/objects/0a/fa3f7660ec70581c4af5b56ba23508701345fa new file mode 100644 index 0000000..0c854c3 Binary files /dev/null and b/.git/objects/0a/fa3f7660ec70581c4af5b56ba23508701345fa differ diff --git a/.git/objects/0b/064b399cb1678226fb957bedac879cb61e4aa6 b/.git/objects/0b/064b399cb1678226fb957bedac879cb61e4aa6 new file mode 100644 index 0000000..e7039f5 Binary files /dev/null and b/.git/objects/0b/064b399cb1678226fb957bedac879cb61e4aa6 differ diff --git a/.git/objects/0b/2a13d011da957d407b46e1a76ef949eb02dbdd b/.git/objects/0b/2a13d011da957d407b46e1a76ef949eb02dbdd new file mode 100644 index 0000000..3c7de2e Binary files /dev/null and b/.git/objects/0b/2a13d011da957d407b46e1a76ef949eb02dbdd differ diff --git a/.git/objects/0b/2ed83380867a39c05797841ff4c8a9053e1e6d b/.git/objects/0b/2ed83380867a39c05797841ff4c8a9053e1e6d new file mode 100644 index 0000000..ea9bce5 Binary files /dev/null and b/.git/objects/0b/2ed83380867a39c05797841ff4c8a9053e1e6d differ diff --git a/.git/objects/0b/4e06e4952f48af2be02db72df5d0880275a2fa b/.git/objects/0b/4e06e4952f48af2be02db72df5d0880275a2fa new file mode 100644 index 0000000..033cfa7 Binary files /dev/null and b/.git/objects/0b/4e06e4952f48af2be02db72df5d0880275a2fa differ diff --git a/.git/objects/0b/63165cb84d0446cf32402745cd0adb60f2b19d b/.git/objects/0b/63165cb84d0446cf32402745cd0adb60f2b19d new file mode 100644 index 0000000..5317007 Binary files /dev/null and b/.git/objects/0b/63165cb84d0446cf32402745cd0adb60f2b19d differ diff --git a/.git/objects/0b/a44bb3f60c27ec0ac7c251a46fcd176a889f20 b/.git/objects/0b/a44bb3f60c27ec0ac7c251a46fcd176a889f20 new file mode 100644 index 0000000..75454d6 Binary files /dev/null and b/.git/objects/0b/a44bb3f60c27ec0ac7c251a46fcd176a889f20 differ diff --git a/.git/objects/0b/bc81341a7ccc1c58c1c59795437268981a7ac4 b/.git/objects/0b/bc81341a7ccc1c58c1c59795437268981a7ac4 new file mode 100644 index 0000000..9edda1f Binary files /dev/null and b/.git/objects/0b/bc81341a7ccc1c58c1c59795437268981a7ac4 differ diff --git a/.git/objects/0c/1a3eac03f8529f86c6141b3341abf82e95a74e b/.git/objects/0c/1a3eac03f8529f86c6141b3341abf82e95a74e new file mode 100644 index 0000000..746955c Binary files /dev/null and b/.git/objects/0c/1a3eac03f8529f86c6141b3341abf82e95a74e differ diff --git a/.git/objects/0c/20adbe31ab4ac7485abdc82252f30d24d46354 b/.git/objects/0c/20adbe31ab4ac7485abdc82252f30d24d46354 new file mode 100644 index 0000000..c951d2c Binary files /dev/null and b/.git/objects/0c/20adbe31ab4ac7485abdc82252f30d24d46354 differ diff --git a/.git/objects/0c/45496cc0ccd85d79b182011d7ca55c45f93267 b/.git/objects/0c/45496cc0ccd85d79b182011d7ca55c45f93267 new file mode 100644 index 0000000..6ce9748 Binary files /dev/null and b/.git/objects/0c/45496cc0ccd85d79b182011d7ca55c45f93267 differ diff --git a/.git/objects/0c/47bd87a3ba556c794fb8e39926ae91f67b7aad b/.git/objects/0c/47bd87a3ba556c794fb8e39926ae91f67b7aad new file mode 100644 index 0000000..7a7925c Binary files /dev/null and b/.git/objects/0c/47bd87a3ba556c794fb8e39926ae91f67b7aad differ diff --git a/.git/objects/0c/5030cea18242d504de9391db3fd100ae5f7c24 b/.git/objects/0c/5030cea18242d504de9391db3fd100ae5f7c24 new file mode 100644 index 0000000..8a2c1a5 --- /dev/null +++ b/.git/objects/0c/5030cea18242d504de9391db3fd100ae5f7c24 @@ -0,0 +1,2 @@ +xMN!]sڛ1nux9Ʌk[j'RW9gcl0KrWJ ]pϏxiLa=2V~ +Q5 )D,.O j[xDXm˝1M4P_ą}9}Ӊ?n +K2^i`Sˌpu]_%X> \ No newline at end of file diff --git a/.git/objects/0e/b70ebd808c014a3ec0337f1b9596bb7b28fca0 b/.git/objects/0e/b70ebd808c014a3ec0337f1b9596bb7b28fca0 new file mode 100644 index 0000000..61ff96e Binary files /dev/null and b/.git/objects/0e/b70ebd808c014a3ec0337f1b9596bb7b28fca0 differ diff --git a/.git/objects/0e/e3db55d731cb3009fcc6a021d8679cbe2da487 b/.git/objects/0e/e3db55d731cb3009fcc6a021d8679cbe2da487 new file mode 100644 index 0000000..82870c8 Binary files /dev/null and b/.git/objects/0e/e3db55d731cb3009fcc6a021d8679cbe2da487 differ diff --git a/.git/objects/0e/e712539585e9f47e04bc4164fa818c32d29e57 b/.git/objects/0e/e712539585e9f47e04bc4164fa818c32d29e57 new file mode 100644 index 0000000..61ae583 Binary files /dev/null and b/.git/objects/0e/e712539585e9f47e04bc4164fa818c32d29e57 differ diff --git a/.git/objects/0e/f6aa6e13b0984d3ae76ce69d74f2b7bd5b0139 b/.git/objects/0e/f6aa6e13b0984d3ae76ce69d74f2b7bd5b0139 new file mode 100644 index 0000000..a4c3eef Binary files /dev/null and b/.git/objects/0e/f6aa6e13b0984d3ae76ce69d74f2b7bd5b0139 differ diff --git a/.git/objects/0f/1a552c2e24cdc1384ae9ffb3a93c9e4846695d b/.git/objects/0f/1a552c2e24cdc1384ae9ffb3a93c9e4846695d new file mode 100644 index 0000000..749a64b Binary files /dev/null and b/.git/objects/0f/1a552c2e24cdc1384ae9ffb3a93c9e4846695d differ diff --git a/.git/objects/0f/21daba18e1b704883310256d515aa81c8586c0 b/.git/objects/0f/21daba18e1b704883310256d515aa81c8586c0 new file mode 100644 index 0000000..86a87d0 --- /dev/null +++ b/.git/objects/0f/21daba18e1b704883310256d515aa81c8586c0 @@ -0,0 +1,2 @@ +x5n0 E;+5ۡZHtyA]8i')hGkiAӴeA7aMm4=j Nyڭa}Lǝw6YN뙿)y.]>ӽrŽxԮc{=hj³2J5[۩ +)Mph-uJwv ex^˦3GOL8KP'J|`LBgkmeɱMp۟8u98u>(xdջWJBWPEXc+b#%R*/i\ \ No newline at end of file diff --git a/.git/objects/0f/82fb839c1311a274f07a266564ac2ce570cf82 b/.git/objects/0f/82fb839c1311a274f07a266564ac2ce570cf82 new file mode 100644 index 0000000..6d51583 --- /dev/null +++ b/.git/objects/0f/82fb839c1311a274f07a266564ac2ce570cf82 @@ -0,0 +1,2 @@ +xAN0CY!$mH!`'o6#s1rve;龯Z& X80gۈY +r8b M19N7(6 [;X͡fwкp͊W0s^R L`)0`&is>|C9ZΡP &XB\Wx) +/c \ No newline at end of file diff --git a/.git/objects/0f/e5512f08392647b183d25332f6f5581dbc43ea b/.git/objects/0f/e5512f08392647b183d25332f6f5581dbc43ea new file mode 100644 index 0000000..9da7d64 --- /dev/null +++ b/.git/objects/0f/e5512f08392647b183d25332f6f5581dbc43ea @@ -0,0 +1 @@ +xMJ1])j? 7gxJNIf9U(rwAtAk̚Io)x4&lwȰ|b:@JvF,2(VVQ\:vnp7֕u*uxę>y7HeWVJ'X&cW_gH8hVY/Da0 toQQn \ No newline at end of file diff --git a/.git/objects/10/194de2a5c50bfeeb99da25df3bfd68e0989ad4 b/.git/objects/10/194de2a5c50bfeeb99da25df3bfd68e0989ad4 new file mode 100644 index 0000000..7053866 Binary files /dev/null and b/.git/objects/10/194de2a5c50bfeeb99da25df3bfd68e0989ad4 differ diff --git a/.git/objects/10/2508117cd662767d8a4160056e6e28b5112ac7 b/.git/objects/10/2508117cd662767d8a4160056e6e28b5112ac7 new file mode 100644 index 0000000..2cd0339 Binary files /dev/null and b/.git/objects/10/2508117cd662767d8a4160056e6e28b5112ac7 differ diff --git a/.git/objects/10/6c38c7537b6f5b03abf18f0f6bb98166d29eb3 b/.git/objects/10/6c38c7537b6f5b03abf18f0f6bb98166d29eb3 new file mode 100644 index 0000000..d2eabf6 Binary files /dev/null and b/.git/objects/10/6c38c7537b6f5b03abf18f0f6bb98166d29eb3 differ diff --git a/.git/objects/10/7493c4bba0b459acfba153f72787f441e9d20e b/.git/objects/10/7493c4bba0b459acfba153f72787f441e9d20e new file mode 100644 index 0000000..72b6a9a Binary files /dev/null and b/.git/objects/10/7493c4bba0b459acfba153f72787f441e9d20e differ diff --git a/.git/objects/10/9dcdffe138019d707bded595f28d1e5d8e880e b/.git/objects/10/9dcdffe138019d707bded595f28d1e5d8e880e new file mode 100644 index 0000000..0832092 Binary files /dev/null and b/.git/objects/10/9dcdffe138019d707bded595f28d1e5d8e880e differ diff --git a/.git/objects/10/ccbcc01debdc4769333654300d8d19a9c2ed1b b/.git/objects/10/ccbcc01debdc4769333654300d8d19a9c2ed1b new file mode 100644 index 0000000..6bea6ca Binary files /dev/null and b/.git/objects/10/ccbcc01debdc4769333654300d8d19a9c2ed1b differ diff --git a/.git/objects/11/087ded48121f0c734a1b5ec9ad6f7e564ea976 b/.git/objects/11/087ded48121f0c734a1b5ec9ad6f7e564ea976 new file mode 100644 index 0000000..bcbd2fd Binary files /dev/null and b/.git/objects/11/087ded48121f0c734a1b5ec9ad6f7e564ea976 differ diff --git a/.git/objects/11/145abc1e90eda95a888db50598b2d9cb68566f b/.git/objects/11/145abc1e90eda95a888db50598b2d9cb68566f new file mode 100644 index 0000000..faefbbc Binary files /dev/null and b/.git/objects/11/145abc1e90eda95a888db50598b2d9cb68566f differ diff --git a/.git/objects/11/19fa6964b88c3685cd114ab1fd77670958b796 b/.git/objects/11/19fa6964b88c3685cd114ab1fd77670958b796 new file mode 100644 index 0000000..ea2266f Binary files /dev/null and b/.git/objects/11/19fa6964b88c3685cd114ab1fd77670958b796 differ diff --git a/.git/objects/11/2a8749812fa508a837feb926f007f743ffdee3 b/.git/objects/11/2a8749812fa508a837feb926f007f743ffdee3 new file mode 100644 index 0000000..c8dee33 Binary files /dev/null and b/.git/objects/11/2a8749812fa508a837feb926f007f743ffdee3 differ diff --git a/.git/objects/11/69bf5ddb39155476db18c2e04ee722b65fecea b/.git/objects/11/69bf5ddb39155476db18c2e04ee722b65fecea new file mode 100644 index 0000000..ddcd109 Binary files /dev/null and b/.git/objects/11/69bf5ddb39155476db18c2e04ee722b65fecea differ diff --git a/.git/objects/11/7633f6bf77337fff1b4b5741dea220adf37cfd b/.git/objects/11/7633f6bf77337fff1b4b5741dea220adf37cfd new file mode 100644 index 0000000..5b0b450 Binary files /dev/null and b/.git/objects/11/7633f6bf77337fff1b4b5741dea220adf37cfd differ diff --git a/.git/objects/11/898f667705d62754335752b2d9bdabc7a05cc8 b/.git/objects/11/898f667705d62754335752b2d9bdabc7a05cc8 new file mode 100644 index 0000000..0597695 Binary files /dev/null and b/.git/objects/11/898f667705d62754335752b2d9bdabc7a05cc8 differ diff --git a/.git/objects/11/9efd28d575599521cd99d37bf4a6e1de73bb36 b/.git/objects/11/9efd28d575599521cd99d37bf4a6e1de73bb36 new file mode 100644 index 0000000..33e4415 Binary files /dev/null and b/.git/objects/11/9efd28d575599521cd99d37bf4a6e1de73bb36 differ diff --git a/.git/objects/11/ab75405f0e20f0f02968d854fda3727b818857 b/.git/objects/11/ab75405f0e20f0f02968d854fda3727b818857 new file mode 100644 index 0000000..a87d8f7 Binary files /dev/null and b/.git/objects/11/ab75405f0e20f0f02968d854fda3727b818857 differ diff --git a/.git/objects/11/cede2d32e3d18dccf8f4017d7c089164f91df2 b/.git/objects/11/cede2d32e3d18dccf8f4017d7c089164f91df2 new file mode 100644 index 0000000..e1112a0 Binary files /dev/null and b/.git/objects/11/cede2d32e3d18dccf8f4017d7c089164f91df2 differ diff --git a/.git/objects/11/f1e23af470d6011e8d5cad20c88f09f8af8d4d b/.git/objects/11/f1e23af470d6011e8d5cad20c88f09f8af8d4d new file mode 100644 index 0000000..068ce3c Binary files /dev/null and b/.git/objects/11/f1e23af470d6011e8d5cad20c88f09f8af8d4d differ diff --git a/.git/objects/12/1069c2b56d13ed269670b0032fbf32bdbac8f5 b/.git/objects/12/1069c2b56d13ed269670b0032fbf32bdbac8f5 new file mode 100644 index 0000000..02b3b7b Binary files /dev/null and b/.git/objects/12/1069c2b56d13ed269670b0032fbf32bdbac8f5 differ diff --git a/.git/objects/12/150f2e3f995b43e22322d8b4bcecab664f17f5 b/.git/objects/12/150f2e3f995b43e22322d8b4bcecab664f17f5 new file mode 100644 index 0000000..f7a6075 Binary files /dev/null and b/.git/objects/12/150f2e3f995b43e22322d8b4bcecab664f17f5 differ diff --git a/.git/objects/12/3bb816a60489a1f839d5fae8627e039b44c693 b/.git/objects/12/3bb816a60489a1f839d5fae8627e039b44c693 new file mode 100644 index 0000000..c6b6b39 Binary files /dev/null and b/.git/objects/12/3bb816a60489a1f839d5fae8627e039b44c693 differ diff --git a/.git/objects/13/2431e9a277fdd806f1a6c83dd4f20888be1198 b/.git/objects/13/2431e9a277fdd806f1a6c83dd4f20888be1198 new file mode 100644 index 0000000..b5a6043 Binary files /dev/null and b/.git/objects/13/2431e9a277fdd806f1a6c83dd4f20888be1198 differ diff --git a/.git/objects/13/3c64114ecac86f02dfb299e0d526b5990eb762 b/.git/objects/13/3c64114ecac86f02dfb299e0d526b5990eb762 new file mode 100644 index 0000000..e48944c Binary files /dev/null and b/.git/objects/13/3c64114ecac86f02dfb299e0d526b5990eb762 differ diff --git a/.git/objects/13/7580cb4af7cfa86fc671191a528f0e8bc2ec2e b/.git/objects/13/7580cb4af7cfa86fc671191a528f0e8bc2ec2e new file mode 100644 index 0000000..732f242 Binary files /dev/null and b/.git/objects/13/7580cb4af7cfa86fc671191a528f0e8bc2ec2e differ diff --git a/.git/objects/13/aeefe5dc233d44562880b1b51e8cfdc2d4e240 b/.git/objects/13/aeefe5dc233d44562880b1b51e8cfdc2d4e240 new file mode 100644 index 0000000..8b6da97 Binary files /dev/null and b/.git/objects/13/aeefe5dc233d44562880b1b51e8cfdc2d4e240 differ diff --git a/.git/objects/13/b1390497b5f4131473dccbcc943a089c5a8e0c b/.git/objects/13/b1390497b5f4131473dccbcc943a089c5a8e0c new file mode 100644 index 0000000..a908375 Binary files /dev/null and b/.git/objects/13/b1390497b5f4131473dccbcc943a089c5a8e0c differ diff --git a/.git/objects/13/b140474f48eb12f98028d511832ab6c40737c0 b/.git/objects/13/b140474f48eb12f98028d511832ab6c40737c0 new file mode 100644 index 0000000..0b3e1f0 Binary files /dev/null and b/.git/objects/13/b140474f48eb12f98028d511832ab6c40737c0 differ diff --git a/.git/objects/13/d769ab4bbcf966bbcb28acd5b9ee66eb945f06 b/.git/objects/13/d769ab4bbcf966bbcb28acd5b9ee66eb945f06 new file mode 100644 index 0000000..5a8cdea Binary files /dev/null and b/.git/objects/13/d769ab4bbcf966bbcb28acd5b9ee66eb945f06 differ diff --git a/.git/objects/13/f5929fcca3d7e98528f8a4ab3c3eee16543030 b/.git/objects/13/f5929fcca3d7e98528f8a4ab3c3eee16543030 new file mode 100644 index 0000000..3824db2 Binary files /dev/null and b/.git/objects/13/f5929fcca3d7e98528f8a4ab3c3eee16543030 differ diff --git a/.git/objects/13/fe229774c52ad5df50b415b3ba6f86206e5fe1 b/.git/objects/13/fe229774c52ad5df50b415b3ba6f86206e5fe1 new file mode 100644 index 0000000..93b8df5 --- /dev/null +++ b/.git/objects/13/fe229774c52ad5df50b415b3ba6f86206e5fe1 @@ -0,0 +1 @@ +xJ0a}9I6 "x|2LwIST}o凟sJC+"`Wa5N['VlºTS*kьFdXM[D|{7x-HȆWd;:-xP-+mG:,Jkg {ĎMwT+|Q b>HGa!88Keezz~jY \ No newline at end of file diff --git a/.git/objects/14/23f1c1ae8e55673d13199c8e8e5995591e4f0b b/.git/objects/14/23f1c1ae8e55673d13199c8e8e5995591e4f0b new file mode 100644 index 0000000..76a354c Binary files /dev/null and b/.git/objects/14/23f1c1ae8e55673d13199c8e8e5995591e4f0b differ diff --git a/.git/objects/14/7045fbed12b400e6c276c076cf236f24ed41f9 b/.git/objects/14/7045fbed12b400e6c276c076cf236f24ed41f9 new file mode 100644 index 0000000..d008979 Binary files /dev/null and b/.git/objects/14/7045fbed12b400e6c276c076cf236f24ed41f9 differ diff --git a/.git/objects/14/8a8f662899a10036ee45c71e5936e05bba1f80 b/.git/objects/14/8a8f662899a10036ee45c71e5936e05bba1f80 new file mode 100644 index 0000000..1cfed83 Binary files /dev/null and b/.git/objects/14/8a8f662899a10036ee45c71e5936e05bba1f80 differ diff --git a/.git/objects/14/920b699fa8dd092b2b9855e29ec0a353d31423 b/.git/objects/14/920b699fa8dd092b2b9855e29ec0a353d31423 new file mode 100644 index 0000000..195c7d6 Binary files /dev/null and b/.git/objects/14/920b699fa8dd092b2b9855e29ec0a353d31423 differ diff --git a/.git/objects/14/ac1e5c8f044f7c0d15d9e0ee06e0cdf69eed6c b/.git/objects/14/ac1e5c8f044f7c0d15d9e0ee06e0cdf69eed6c new file mode 100644 index 0000000..df71a96 Binary files /dev/null and b/.git/objects/14/ac1e5c8f044f7c0d15d9e0ee06e0cdf69eed6c differ diff --git a/.git/objects/14/bba93d37366ac0eea1b0cf675933558389d13b b/.git/objects/14/bba93d37366ac0eea1b0cf675933558389d13b new file mode 100644 index 0000000..c544ca4 --- /dev/null +++ b/.git/objects/14/bba93d37366ac0eea1b0cf675933558389d13b @@ -0,0 +1,2 @@ +xn D{W콪6*U9Z#`V??Vj5o5cӺ +V5grI{ER)6jR"W9m)VP#yɝAZYRnHo=3Q: / }ct=شPߟ {3$yxmZ`9(-ruΡ[Wp}9㲯zr\2 <1M_pҚ\j" 8/l_ \ No newline at end of file diff --git a/.git/objects/14/e1767f9e0e9ed73415231535eb2b6644638451 b/.git/objects/14/e1767f9e0e9ed73415231535eb2b6644638451 new file mode 100644 index 0000000..1ca5de3 Binary files /dev/null and b/.git/objects/14/e1767f9e0e9ed73415231535eb2b6644638451 differ diff --git a/.git/objects/15/10d1d010d98778ca7cdeb955c02949ba99c6c0 b/.git/objects/15/10d1d010d98778ca7cdeb955c02949ba99c6c0 new file mode 100644 index 0000000..1205c32 Binary files /dev/null and b/.git/objects/15/10d1d010d98778ca7cdeb955c02949ba99c6c0 differ diff --git a/.git/objects/15/2fbc43093cb71e7ad81763e8122428528bd2c4 b/.git/objects/15/2fbc43093cb71e7ad81763e8122428528bd2c4 new file mode 100644 index 0000000..03fa88f Binary files /dev/null and b/.git/objects/15/2fbc43093cb71e7ad81763e8122428528bd2c4 differ diff --git a/.git/objects/15/588241a8bd2a1c7926e3f6cf3bcedd8f47ced7 b/.git/objects/15/588241a8bd2a1c7926e3f6cf3bcedd8f47ced7 new file mode 100644 index 0000000..22ac524 Binary files /dev/null and b/.git/objects/15/588241a8bd2a1c7926e3f6cf3bcedd8f47ced7 differ diff --git a/.git/objects/15/58d669decc171c141511b7f73ff1cfb9a07502 b/.git/objects/15/58d669decc171c141511b7f73ff1cfb9a07502 new file mode 100644 index 0000000..9700612 Binary files /dev/null and b/.git/objects/15/58d669decc171c141511b7f73ff1cfb9a07502 differ diff --git a/.git/objects/15/5bfbc53c5b72f786b53e7c6e00dcedc9e04a40 b/.git/objects/15/5bfbc53c5b72f786b53e7c6e00dcedc9e04a40 new file mode 100644 index 0000000..5b07afa Binary files /dev/null and b/.git/objects/15/5bfbc53c5b72f786b53e7c6e00dcedc9e04a40 differ diff --git a/.git/objects/15/5f631a4be7e042d643f064877a3473c80987cd b/.git/objects/15/5f631a4be7e042d643f064877a3473c80987cd new file mode 100644 index 0000000..c3c94e6 --- /dev/null +++ b/.git/objects/15/5f631a4be7e042d643f064877a3473c80987cd @@ -0,0 +1 @@ +x5J0])^,oJpwzѤ$)Rުf>f(A޵vya|TRFrhV{Όxw!7[A Z(,'νǙD֏t5xq||d/\!#p9g;es*JqO-n2 LxQqX:bhL5l j?cKJYQ \ No newline at end of file diff --git a/.git/objects/15/623563c55ca02b38e45f75510e786aa38ea23d b/.git/objects/15/623563c55ca02b38e45f75510e786aa38ea23d new file mode 100644 index 0000000..fd03e84 Binary files /dev/null and b/.git/objects/15/623563c55ca02b38e45f75510e786aa38ea23d differ diff --git a/.git/objects/15/7c9c251e237f9543ac0d7c4147776793c3ccd5 b/.git/objects/15/7c9c251e237f9543ac0d7c4147776793c3ccd5 new file mode 100644 index 0000000..99af341 Binary files /dev/null and b/.git/objects/15/7c9c251e237f9543ac0d7c4147776793c3ccd5 differ diff --git a/.git/objects/15/a1e239597a5799e7305b08dd44e45158036c46 b/.git/objects/15/a1e239597a5799e7305b08dd44e45158036c46 new file mode 100644 index 0000000..4f48323 Binary files /dev/null and b/.git/objects/15/a1e239597a5799e7305b08dd44e45158036c46 differ diff --git a/.git/objects/15/bf66085f25525e5b1af7696f8778c4c06c62b6 b/.git/objects/15/bf66085f25525e5b1af7696f8778c4c06c62b6 new file mode 100644 index 0000000..52eda3c Binary files /dev/null and b/.git/objects/15/bf66085f25525e5b1af7696f8778c4c06c62b6 differ diff --git a/.git/objects/15/c4247ffe6df5c0737cca41701b0a6c45b7dd02 b/.git/objects/15/c4247ffe6df5c0737cca41701b0a6c45b7dd02 new file mode 100644 index 0000000..598fd87 Binary files /dev/null and b/.git/objects/15/c4247ffe6df5c0737cca41701b0a6c45b7dd02 differ diff --git a/.git/objects/15/d5564775c57ffb7144c6e4bbb29b837921aa5f b/.git/objects/15/d5564775c57ffb7144c6e4bbb29b837921aa5f new file mode 100644 index 0000000..a909915 Binary files /dev/null and b/.git/objects/15/d5564775c57ffb7144c6e4bbb29b837921aa5f differ diff --git a/.git/objects/16/07086420141463178e1cd1f779c1e61e7ed722 b/.git/objects/16/07086420141463178e1cd1f779c1e61e7ed722 new file mode 100644 index 0000000..7b9e0c0 Binary files /dev/null and b/.git/objects/16/07086420141463178e1cd1f779c1e61e7ed722 differ diff --git a/.git/objects/16/11bc03c9716983afa8582033977914fb56eb22 b/.git/objects/16/11bc03c9716983afa8582033977914fb56eb22 new file mode 100644 index 0000000..de828a4 Binary files /dev/null and b/.git/objects/16/11bc03c9716983afa8582033977914fb56eb22 differ diff --git a/.git/objects/16/11bfdde82261aaf58a0bc0ddacaeaedafadb2f b/.git/objects/16/11bfdde82261aaf58a0bc0ddacaeaedafadb2f new file mode 100644 index 0000000..9ff8cde Binary files /dev/null and b/.git/objects/16/11bfdde82261aaf58a0bc0ddacaeaedafadb2f differ diff --git a/.git/objects/16/145f716f771a822f41c2e64943b4680a275ef2 b/.git/objects/16/145f716f771a822f41c2e64943b4680a275ef2 new file mode 100644 index 0000000..9f4966c Binary files /dev/null and b/.git/objects/16/145f716f771a822f41c2e64943b4680a275ef2 differ diff --git a/.git/objects/16/22c97bf0074001af47f7a9495b42ee5c0bce87 b/.git/objects/16/22c97bf0074001af47f7a9495b42ee5c0bce87 new file mode 100644 index 0000000..e5fb6a8 Binary files /dev/null and b/.git/objects/16/22c97bf0074001af47f7a9495b42ee5c0bce87 differ diff --git a/.git/objects/16/24688790472f4470d95875ca14905cfddf4a4c b/.git/objects/16/24688790472f4470d95875ca14905cfddf4a4c new file mode 100644 index 0000000..f7a5108 Binary files /dev/null and b/.git/objects/16/24688790472f4470d95875ca14905cfddf4a4c differ diff --git a/.git/objects/16/3a9a0874f6793fb001e4cea1fd7d3e3cf5c422 b/.git/objects/16/3a9a0874f6793fb001e4cea1fd7d3e3cf5c422 new file mode 100644 index 0000000..e207b1d Binary files /dev/null and b/.git/objects/16/3a9a0874f6793fb001e4cea1fd7d3e3cf5c422 differ diff --git a/.git/objects/16/6d6fdf418de9b4ce79d5463e15887ae726c885 b/.git/objects/16/6d6fdf418de9b4ce79d5463e15887ae726c885 new file mode 100644 index 0000000..45ee46c --- /dev/null +++ b/.git/objects/16/6d6fdf418de9b4ce79d5463e15887ae726c885 @@ -0,0 +1 @@ +x-N09)XlǎBEnp͏ؑ͸bXa|a] w92 NKeVIi%Ym 'gs2m # rн@lZBȔᅑm{B煮EmX+zJpDSo pa`*߲;) Cɮ˾֟\qD#+8\8RK:CF:)%Jb' \ No newline at end of file diff --git a/.git/objects/16/949bb71cb93e53bb918631b2686bf5518a2048 b/.git/objects/16/949bb71cb93e53bb918631b2686bf5518a2048 new file mode 100644 index 0000000..53009ed --- /dev/null +++ b/.git/objects/16/949bb71cb93e53bb918631b2686bf5518a2048 @@ -0,0 +1,4 @@ +x%j0DW}2JXQ+ݜ3p-Z%儙 1B0.˜LZꙛht[9OI‰R'J4tk}^ a^[xJ߹2k.#%8..4oKu-SJ!< ϛŸV֘FZaʡy+[d \ No newline at end of file diff --git a/.git/objects/16/fc41ba454bfcba199b831c30d7044a4279403a b/.git/objects/16/fc41ba454bfcba199b831c30d7044a4279403a new file mode 100644 index 0000000..d3c165a Binary files /dev/null and b/.git/objects/16/fc41ba454bfcba199b831c30d7044a4279403a differ diff --git a/.git/objects/17/2746535963e33b02b2c228d9a91645eb9ab2da b/.git/objects/17/2746535963e33b02b2c228d9a91645eb9ab2da new file mode 100644 index 0000000..eabb7ff Binary files /dev/null and b/.git/objects/17/2746535963e33b02b2c228d9a91645eb9ab2da differ diff --git a/.git/objects/17/2a7d43d52e10cf8b01038790fc05cc5cf06c74 b/.git/objects/17/2a7d43d52e10cf8b01038790fc05cc5cf06c74 new file mode 100644 index 0000000..cded878 Binary files /dev/null and b/.git/objects/17/2a7d43d52e10cf8b01038790fc05cc5cf06c74 differ diff --git a/.git/objects/17/525a2fd547216b8a78fd27f52d11bfdbba7f11 b/.git/objects/17/525a2fd547216b8a78fd27f52d11bfdbba7f11 new file mode 100644 index 0000000..6e83c9b Binary files /dev/null and b/.git/objects/17/525a2fd547216b8a78fd27f52d11bfdbba7f11 differ diff --git a/.git/objects/17/53ff9757830afea1b7e78d48811cd0d0fdfc32 b/.git/objects/17/53ff9757830afea1b7e78d48811cd0d0fdfc32 new file mode 100644 index 0000000..4e50097 Binary files /dev/null and b/.git/objects/17/53ff9757830afea1b7e78d48811cd0d0fdfc32 differ diff --git a/.git/objects/17/6377f025bea951836ac6a2e6d4d6f2bf6d8524 b/.git/objects/17/6377f025bea951836ac6a2e6d4d6f2bf6d8524 new file mode 100644 index 0000000..788a6eb Binary files /dev/null and b/.git/objects/17/6377f025bea951836ac6a2e6d4d6f2bf6d8524 differ diff --git a/.git/objects/18/0283d453106db2abbd4745d5b0013c345bceb7 b/.git/objects/18/0283d453106db2abbd4745d5b0013c345bceb7 new file mode 100644 index 0000000..fa3ee7f Binary files /dev/null and b/.git/objects/18/0283d453106db2abbd4745d5b0013c345bceb7 differ diff --git a/.git/objects/18/169da0e9aa9d4e853e601b2ad6449635d0f4aa b/.git/objects/18/169da0e9aa9d4e853e601b2ad6449635d0f4aa new file mode 100644 index 0000000..a8fee18 Binary files /dev/null and b/.git/objects/18/169da0e9aa9d4e853e601b2ad6449635d0f4aa differ diff --git a/.git/objects/18/2b3736955af76f40f797fc792cf791e957d921 b/.git/objects/18/2b3736955af76f40f797fc792cf791e957d921 new file mode 100644 index 0000000..5e714a7 Binary files /dev/null and b/.git/objects/18/2b3736955af76f40f797fc792cf791e957d921 differ diff --git a/.git/objects/18/331772b046d94ea37d00337d4f84195ab1153a b/.git/objects/18/331772b046d94ea37d00337d4f84195ab1153a new file mode 100644 index 0000000..932462b Binary files /dev/null and b/.git/objects/18/331772b046d94ea37d00337d4f84195ab1153a differ diff --git a/.git/objects/18/3d020149c194aa93961f3afd2f1b1c0a768a30 b/.git/objects/18/3d020149c194aa93961f3afd2f1b1c0a768a30 new file mode 100644 index 0000000..ab24d10 Binary files /dev/null and b/.git/objects/18/3d020149c194aa93961f3afd2f1b1c0a768a30 differ diff --git a/.git/objects/18/4239b3466e206829a20ea06743962fd3bf7c3e b/.git/objects/18/4239b3466e206829a20ea06743962fd3bf7c3e new file mode 100644 index 0000000..28e05ff Binary files /dev/null and b/.git/objects/18/4239b3466e206829a20ea06743962fd3bf7c3e differ diff --git a/.git/objects/18/51f913f5a19ab6272fc1f143ed410e48b48306 b/.git/objects/18/51f913f5a19ab6272fc1f143ed410e48b48306 new file mode 100644 index 0000000..fa64c8c Binary files /dev/null and b/.git/objects/18/51f913f5a19ab6272fc1f143ed410e48b48306 differ diff --git a/.git/objects/18/a3b97694127009a7b164b8104005536ce811e1 b/.git/objects/18/a3b97694127009a7b164b8104005536ce811e1 new file mode 100644 index 0000000..3513e63 --- /dev/null +++ b/.git/objects/18/a3b97694127009a7b164b8104005536ce811e1 @@ -0,0 +1,3 @@ +x5MN0YGT8vlXNړ)TSs1,$vO RP ^F:H4サEo$ҡ +N!} +q v 9jQ Vw~3x^Hޖod[z3ͭ£8 tY£Btmke3Cgy]($twFq" +穱"ܸ.y_\Y \ No newline at end of file diff --git a/.git/objects/18/a4e2bc8f62637aa1a5e051c0567e5880df062e b/.git/objects/18/a4e2bc8f62637aa1a5e051c0567e5880df062e new file mode 100644 index 0000000..b590e5b Binary files /dev/null and b/.git/objects/18/a4e2bc8f62637aa1a5e051c0567e5880df062e differ diff --git a/.git/objects/18/b7784af8ed8c791fa9ab7b7bc556cc03475726 b/.git/objects/18/b7784af8ed8c791fa9ab7b7bc556cc03475726 new file mode 100644 index 0000000..5120591 Binary files /dev/null and b/.git/objects/18/b7784af8ed8c791fa9ab7b7bc556cc03475726 differ diff --git a/.git/objects/18/cf062dde87b9a2daef51958535260beb810100 b/.git/objects/18/cf062dde87b9a2daef51958535260beb810100 new file mode 100644 index 0000000..4fa2881 Binary files /dev/null and b/.git/objects/18/cf062dde87b9a2daef51958535260beb810100 differ diff --git a/.git/objects/18/d5d9290cc296ceb3b6620ab312653c90a0a592 b/.git/objects/18/d5d9290cc296ceb3b6620ab312653c90a0a592 new file mode 100644 index 0000000..210b1fc Binary files /dev/null and b/.git/objects/18/d5d9290cc296ceb3b6620ab312653c90a0a592 differ diff --git a/.git/objects/19/06225fc419f72aed56cf5c8b59799b031e8562 b/.git/objects/19/06225fc419f72aed56cf5c8b59799b031e8562 new file mode 100644 index 0000000..5328ee3 Binary files /dev/null and b/.git/objects/19/06225fc419f72aed56cf5c8b59799b031e8562 differ diff --git a/.git/objects/19/0d19e8b35d9809a654346e02107179900d4a69 b/.git/objects/19/0d19e8b35d9809a654346e02107179900d4a69 new file mode 100644 index 0000000..3b79be0 Binary files /dev/null and b/.git/objects/19/0d19e8b35d9809a654346e02107179900d4a69 differ diff --git a/.git/objects/19/3c3b8e00b2e80f8edd790f1a43730d46ce6279 b/.git/objects/19/3c3b8e00b2e80f8edd790f1a43730d46ce6279 new file mode 100644 index 0000000..a270536 Binary files /dev/null and b/.git/objects/19/3c3b8e00b2e80f8edd790f1a43730d46ce6279 differ diff --git a/.git/objects/19/3f428cb30e89787b6365e16b3b84b8df6e29a6 b/.git/objects/19/3f428cb30e89787b6365e16b3b84b8df6e29a6 new file mode 100644 index 0000000..a570c69 Binary files /dev/null and b/.git/objects/19/3f428cb30e89787b6365e16b3b84b8df6e29a6 differ diff --git a/.git/objects/19/52a038c8d67787a17297d73e039dfadc538196 b/.git/objects/19/52a038c8d67787a17297d73e039dfadc538196 new file mode 100644 index 0000000..47f11ed Binary files /dev/null and b/.git/objects/19/52a038c8d67787a17297d73e039dfadc538196 differ diff --git a/.git/objects/19/6129e5eafb2c1c2017ccd1dd4680385eb8051e b/.git/objects/19/6129e5eafb2c1c2017ccd1dd4680385eb8051e new file mode 100644 index 0000000..77f1554 Binary files /dev/null and b/.git/objects/19/6129e5eafb2c1c2017ccd1dd4680385eb8051e differ diff --git a/.git/objects/19/619a81ffa0233a97038a880753b0e8165eab87 b/.git/objects/19/619a81ffa0233a97038a880753b0e8165eab87 new file mode 100644 index 0000000..f34aa83 Binary files /dev/null and b/.git/objects/19/619a81ffa0233a97038a880753b0e8165eab87 differ diff --git a/.git/objects/19/9bdeb15bcb8c9025ff11a43acd0779ef1ca361 b/.git/objects/19/9bdeb15bcb8c9025ff11a43acd0779ef1ca361 new file mode 100644 index 0000000..fae274e Binary files /dev/null and b/.git/objects/19/9bdeb15bcb8c9025ff11a43acd0779ef1ca361 differ diff --git a/.git/objects/19/c34f5f2e0d89822d8f65415e41c904a17c14a5 b/.git/objects/19/c34f5f2e0d89822d8f65415e41c904a17c14a5 new file mode 100644 index 0000000..25f6a51 --- /dev/null +++ b/.git/objects/19/c34f5f2e0d89822d8f65415e41c904a17c14a5 @@ -0,0 +1 @@ +xMJ0gwŁ3\Ar{G Ri"+`l5Iw+^*(%Bo#)GHxKísWޱ%O w9=5 PcoQ +!6^%^-.pp7qs{|ͻuq9A C\B. k B5un_xh >vv@oޡ) bwsg; \ No newline at end of file diff --git a/.git/objects/1a/5275131138e11d3cfcad694114fe84fe3ad2d0 b/.git/objects/1a/5275131138e11d3cfcad694114fe84fe3ad2d0 new file mode 100644 index 0000000..a21e279 Binary files /dev/null and b/.git/objects/1a/5275131138e11d3cfcad694114fe84fe3ad2d0 differ diff --git a/.git/objects/1a/910e39c7764cb166cae2e39f4686be364963a3 b/.git/objects/1a/910e39c7764cb166cae2e39f4686be364963a3 new file mode 100644 index 0000000..fab9cd8 Binary files /dev/null and b/.git/objects/1a/910e39c7764cb166cae2e39f4686be364963a3 differ diff --git a/.git/objects/1a/91a5cdf2f629e195445e03512a2422a82b8a3b b/.git/objects/1a/91a5cdf2f629e195445e03512a2422a82b8a3b new file mode 100644 index 0000000..0673637 Binary files /dev/null and b/.git/objects/1a/91a5cdf2f629e195445e03512a2422a82b8a3b differ diff --git a/.git/objects/1a/ad74640355627a1d6724e4ec0c8cafb1b83b06 b/.git/objects/1a/ad74640355627a1d6724e4ec0c8cafb1b83b06 new file mode 100644 index 0000000..0647702 Binary files /dev/null and b/.git/objects/1a/ad74640355627a1d6724e4ec0c8cafb1b83b06 differ diff --git a/.git/objects/1a/b8145d021e4387d9acaecf6dc54c973df16de6 b/.git/objects/1a/b8145d021e4387d9acaecf6dc54c973df16de6 new file mode 100644 index 0000000..36ee9d4 Binary files /dev/null and b/.git/objects/1a/b8145d021e4387d9acaecf6dc54c973df16de6 differ diff --git a/.git/objects/1a/c0ce795a13155a08e68ed7531f9b9c65653217 b/.git/objects/1a/c0ce795a13155a08e68ed7531f9b9c65653217 new file mode 100644 index 0000000..2077691 Binary files /dev/null and b/.git/objects/1a/c0ce795a13155a08e68ed7531f9b9c65653217 differ diff --git a/.git/objects/1a/eda87a1363ca63ab617688ff0a220650c502d2 b/.git/objects/1a/eda87a1363ca63ab617688ff0a220650c502d2 new file mode 100644 index 0000000..9e75fee Binary files /dev/null and b/.git/objects/1a/eda87a1363ca63ab617688ff0a220650c502d2 differ diff --git a/.git/objects/1b/2737adfeb91cc890878006d3b254d2bbd5764f b/.git/objects/1b/2737adfeb91cc890878006d3b254d2bbd5764f new file mode 100644 index 0000000..55d51b4 Binary files /dev/null and b/.git/objects/1b/2737adfeb91cc890878006d3b254d2bbd5764f differ diff --git a/.git/objects/1b/4042e2acd1f78786693ef5c14bb565077425d4 b/.git/objects/1b/4042e2acd1f78786693ef5c14bb565077425d4 new file mode 100644 index 0000000..c18d403 Binary files /dev/null and b/.git/objects/1b/4042e2acd1f78786693ef5c14bb565077425d4 differ diff --git a/.git/objects/1b/8fb4c92eb0c800661934018a974f72480b5c2e b/.git/objects/1b/8fb4c92eb0c800661934018a974f72480b5c2e new file mode 100644 index 0000000..6f351d5 Binary files /dev/null and b/.git/objects/1b/8fb4c92eb0c800661934018a974f72480b5c2e differ diff --git a/.git/objects/1b/b296f864b9b3da202aa03bf25e38af3f16043d b/.git/objects/1b/b296f864b9b3da202aa03bf25e38af3f16043d new file mode 100644 index 0000000..4ec1052 Binary files /dev/null and b/.git/objects/1b/b296f864b9b3da202aa03bf25e38af3f16043d differ diff --git a/.git/objects/1b/f066f48a8cf6a23a9f92f52bb24dd41d5e8f07 b/.git/objects/1b/f066f48a8cf6a23a9f92f52bb24dd41d5e8f07 new file mode 100644 index 0000000..8f06b67 Binary files /dev/null and b/.git/objects/1b/f066f48a8cf6a23a9f92f52bb24dd41d5e8f07 differ diff --git a/.git/objects/1b/fc96e084d09af01ca7e5e4af5753fe902debc3 b/.git/objects/1b/fc96e084d09af01ca7e5e4af5753fe902debc3 new file mode 100644 index 0000000..4fe4245 Binary files /dev/null and b/.git/objects/1b/fc96e084d09af01ca7e5e4af5753fe902debc3 differ diff --git a/.git/objects/1c/781d24e1a14ec7c2e5813705695f42b130849e b/.git/objects/1c/781d24e1a14ec7c2e5813705695f42b130849e new file mode 100644 index 0000000..e98a869 Binary files /dev/null and b/.git/objects/1c/781d24e1a14ec7c2e5813705695f42b130849e differ diff --git a/.git/objects/1c/78d4a61018be4b68ba9e55fb4dd954ef2705ef b/.git/objects/1c/78d4a61018be4b68ba9e55fb4dd954ef2705ef new file mode 100644 index 0000000..b5679e2 Binary files /dev/null and b/.git/objects/1c/78d4a61018be4b68ba9e55fb4dd954ef2705ef differ diff --git a/.git/objects/1c/8fb655a343e016f2dbc84b2738292752501e44 b/.git/objects/1c/8fb655a343e016f2dbc84b2738292752501e44 new file mode 100644 index 0000000..fca8c92 Binary files /dev/null and b/.git/objects/1c/8fb655a343e016f2dbc84b2738292752501e44 differ diff --git a/.git/objects/1c/aeaa4ec93d36acb10978f0c86010352783be99 b/.git/objects/1c/aeaa4ec93d36acb10978f0c86010352783be99 new file mode 100644 index 0000000..e0a0767 Binary files /dev/null and b/.git/objects/1c/aeaa4ec93d36acb10978f0c86010352783be99 differ diff --git a/.git/objects/1c/bf1c2f87ef9fe206a5e4b8f530ac6fb56f99a0 b/.git/objects/1c/bf1c2f87ef9fe206a5e4b8f530ac6fb56f99a0 new file mode 100644 index 0000000..989e198 Binary files /dev/null and b/.git/objects/1c/bf1c2f87ef9fe206a5e4b8f530ac6fb56f99a0 differ diff --git a/.git/objects/1d/14db270e1f75386cee48371df26356edf5a06c b/.git/objects/1d/14db270e1f75386cee48371df26356edf5a06c new file mode 100644 index 0000000..5fb0796 Binary files /dev/null and b/.git/objects/1d/14db270e1f75386cee48371df26356edf5a06c differ diff --git a/.git/objects/1d/1fac67d3b0e017052b00a8333e843ba13c03b6 b/.git/objects/1d/1fac67d3b0e017052b00a8333e843ba13c03b6 new file mode 100644 index 0000000..acd07e2 Binary files /dev/null and b/.git/objects/1d/1fac67d3b0e017052b00a8333e843ba13c03b6 differ diff --git a/.git/objects/1d/2fa14cedc7d854e561ac68e8432d1156bd6cb7 b/.git/objects/1d/2fa14cedc7d854e561ac68e8432d1156bd6cb7 new file mode 100644 index 0000000..8058adc Binary files /dev/null and b/.git/objects/1d/2fa14cedc7d854e561ac68e8432d1156bd6cb7 differ diff --git a/.git/objects/1d/3085b325f193d51ea1ff5d4b0171870df5678d b/.git/objects/1d/3085b325f193d51ea1ff5d4b0171870df5678d new file mode 100644 index 0000000..495d084 Binary files /dev/null and b/.git/objects/1d/3085b325f193d51ea1ff5d4b0171870df5678d differ diff --git a/.git/objects/1d/3811f7937feb9db376489c2c2b4ad4dfbfd741 b/.git/objects/1d/3811f7937feb9db376489c2c2b4ad4dfbfd741 new file mode 100644 index 0000000..796d807 Binary files /dev/null and b/.git/objects/1d/3811f7937feb9db376489c2c2b4ad4dfbfd741 differ diff --git a/.git/objects/1d/7473274fce5384b82039dfb42d0a60abf71279 b/.git/objects/1d/7473274fce5384b82039dfb42d0a60abf71279 new file mode 100644 index 0000000..644338a Binary files /dev/null and b/.git/objects/1d/7473274fce5384b82039dfb42d0a60abf71279 differ diff --git a/.git/objects/1d/8f06d969ff43a5e40a19862c1f0679fae90cc8 b/.git/objects/1d/8f06d969ff43a5e40a19862c1f0679fae90cc8 new file mode 100644 index 0000000..2106001 Binary files /dev/null and b/.git/objects/1d/8f06d969ff43a5e40a19862c1f0679fae90cc8 differ diff --git a/.git/objects/1d/e14734d08e582fa4cedd1396490ec00a93cde3 b/.git/objects/1d/e14734d08e582fa4cedd1396490ec00a93cde3 new file mode 100644 index 0000000..261b11e Binary files /dev/null and b/.git/objects/1d/e14734d08e582fa4cedd1396490ec00a93cde3 differ diff --git a/.git/objects/1d/e67492c9bfa69338d6cff582de7b28fc3e9351 b/.git/objects/1d/e67492c9bfa69338d6cff582de7b28fc3e9351 new file mode 100644 index 0000000..c825fdc Binary files /dev/null and b/.git/objects/1d/e67492c9bfa69338d6cff582de7b28fc3e9351 differ diff --git a/.git/objects/1d/fb1a24c607620339bf0587f65234aa6766858a b/.git/objects/1d/fb1a24c607620339bf0587f65234aa6766858a new file mode 100644 index 0000000..7081613 Binary files /dev/null and b/.git/objects/1d/fb1a24c607620339bf0587f65234aa6766858a differ diff --git a/.git/objects/1e/17ef04c36134d94005ab268ca663600b6bfceb b/.git/objects/1e/17ef04c36134d94005ab268ca663600b6bfceb new file mode 100644 index 0000000..f3610a0 Binary files /dev/null and b/.git/objects/1e/17ef04c36134d94005ab268ca663600b6bfceb differ diff --git a/.git/objects/1e/1b4a1ecea231ae8a065c5584c9c5bdba84aa74 b/.git/objects/1e/1b4a1ecea231ae8a065c5584c9c5bdba84aa74 new file mode 100644 index 0000000..be566c7 --- /dev/null +++ b/.git/objects/1e/1b4a1ecea231ae8a065c5584c9c5bdba84aa74 @@ -0,0 +1 @@ +x5Mj0)޾ϊk7=ز6YX@`>f?OS f"8H`DŽwDs>h,)UpuX:e$*ŴW' 4gx)P|DxO_vjw+3pnLiL0 r,1tm`ڟ%{J޼ uc:Cjl\v\py\U \ No newline at end of file diff --git a/.git/objects/1e/1f1c971be556864f1a30e5c246db337699e366 b/.git/objects/1e/1f1c971be556864f1a30e5c246db337699e366 new file mode 100644 index 0000000..b158a04 Binary files /dev/null and b/.git/objects/1e/1f1c971be556864f1a30e5c246db337699e366 differ diff --git a/.git/objects/1e/277c3da40fe9aa50e4407fda770609233fd220 b/.git/objects/1e/277c3da40fe9aa50e4407fda770609233fd220 new file mode 100644 index 0000000..78fa4e2 Binary files /dev/null and b/.git/objects/1e/277c3da40fe9aa50e4407fda770609233fd220 differ diff --git a/.git/objects/1e/4608516d59ba773a06143984f3c6707cd2f452 b/.git/objects/1e/4608516d59ba773a06143984f3c6707cd2f452 new file mode 100644 index 0000000..07f022d Binary files /dev/null and b/.git/objects/1e/4608516d59ba773a06143984f3c6707cd2f452 differ diff --git a/.git/objects/1e/5631a1b0320a0c4c65a17e4d2917445d058ec2 b/.git/objects/1e/5631a1b0320a0c4c65a17e4d2917445d058ec2 new file mode 100644 index 0000000..4aaad5a Binary files /dev/null and b/.git/objects/1e/5631a1b0320a0c4c65a17e4d2917445d058ec2 differ diff --git a/.git/objects/1e/71cea6779fc5c8f2aa65438ad9292b850de829 b/.git/objects/1e/71cea6779fc5c8f2aa65438ad9292b850de829 new file mode 100644 index 0000000..cb96f67 Binary files /dev/null and b/.git/objects/1e/71cea6779fc5c8f2aa65438ad9292b850de829 differ diff --git a/.git/objects/1e/8799a7235db49db0bbe9c59574452b0b3efa3e b/.git/objects/1e/8799a7235db49db0bbe9c59574452b0b3efa3e new file mode 100644 index 0000000..35532a2 Binary files /dev/null and b/.git/objects/1e/8799a7235db49db0bbe9c59574452b0b3efa3e differ diff --git a/.git/objects/1e/b598b9722120d9f6fca52bdb322e8fad6555c0 b/.git/objects/1e/b598b9722120d9f6fca52bdb322e8fad6555c0 new file mode 100644 index 0000000..25ae20c Binary files /dev/null and b/.git/objects/1e/b598b9722120d9f6fca52bdb322e8fad6555c0 differ diff --git a/.git/objects/1e/c83644b77504275b4797a735ffa44d168c2cdc b/.git/objects/1e/c83644b77504275b4797a735ffa44d168c2cdc new file mode 100644 index 0000000..e0aa5c3 Binary files /dev/null and b/.git/objects/1e/c83644b77504275b4797a735ffa44d168c2cdc differ diff --git a/.git/objects/1e/cff469de663841d63528bbc246b1331021f902 b/.git/objects/1e/cff469de663841d63528bbc246b1331021f902 new file mode 100644 index 0000000..3e34e27 Binary files /dev/null and b/.git/objects/1e/cff469de663841d63528bbc246b1331021f902 differ diff --git a/.git/objects/1e/de8534edd191430c865484c2dcea0dadcea6ce b/.git/objects/1e/de8534edd191430c865484c2dcea0dadcea6ce new file mode 100644 index 0000000..eda4bc7 Binary files /dev/null and b/.git/objects/1e/de8534edd191430c865484c2dcea0dadcea6ce differ diff --git a/.git/objects/1f/081f4be1e15f9a62d0fd7ae9e89c3e63cae5ee b/.git/objects/1f/081f4be1e15f9a62d0fd7ae9e89c3e63cae5ee new file mode 100644 index 0000000..8775337 --- /dev/null +++ b/.git/objects/1f/081f4be1e15f9a62d0fd7ae9e89c3e63cae5ee @@ -0,0 +1,2 @@ +x%AK0=W"IFY z_^^m ̻̠aa|\%CgUN0RNz=jIH;aD3&QՎ+##Ml#7#_,>qxtg+'j,F\y͡Y~*m9O tn^xأA6GbX@3 SP% \ No newline at end of file diff --git a/.git/objects/24/9db36976f5e70feb3994de9c0fe651b7e3c6ec b/.git/objects/24/9db36976f5e70feb3994de9c0fe651b7e3c6ec new file mode 100644 index 0000000..14847de Binary files /dev/null and b/.git/objects/24/9db36976f5e70feb3994de9c0fe651b7e3c6ec differ diff --git a/.git/objects/24/9dc69b7ff28d63e7cc32fbdeaabae3a199156e b/.git/objects/24/9dc69b7ff28d63e7cc32fbdeaabae3a199156e new file mode 100644 index 0000000..d9926e2 Binary files /dev/null and b/.git/objects/24/9dc69b7ff28d63e7cc32fbdeaabae3a199156e differ diff --git a/.git/objects/24/eccd5b0e4c21cca5d8b497e688d5c059176d67 b/.git/objects/24/eccd5b0e4c21cca5d8b497e688d5c059176d67 new file mode 100644 index 0000000..8e50498 Binary files /dev/null and b/.git/objects/24/eccd5b0e4c21cca5d8b497e688d5c059176d67 differ diff --git a/.git/objects/25/0296e23774ddd1da7afc92f3eaa094bfafaea7 b/.git/objects/25/0296e23774ddd1da7afc92f3eaa094bfafaea7 new file mode 100644 index 0000000..a23e1ea Binary files /dev/null and b/.git/objects/25/0296e23774ddd1da7afc92f3eaa094bfafaea7 differ diff --git a/.git/objects/25/03d2ba21fea3203f1e206d374650ae62ec7953 b/.git/objects/25/03d2ba21fea3203f1e206d374650ae62ec7953 new file mode 100644 index 0000000..3d04f2b Binary files /dev/null and b/.git/objects/25/03d2ba21fea3203f1e206d374650ae62ec7953 differ diff --git a/.git/objects/25/2dafe43df0a61efa2d130b503a7a54071e1c7d b/.git/objects/25/2dafe43df0a61efa2d130b503a7a54071e1c7d new file mode 100644 index 0000000..ee1270d --- /dev/null +++ b/.git/objects/25/2dafe43df0a61efa2d130b503a7a54071e1c7d @@ -0,0 +1,2 @@ +xAn E)fSUUzv 0Įl0uߋU_OOu+O0 ҈WVvb@qAkݨp4mEFtCd?rxҎP /B .?%sxjR)c%*=IH!68&2ʈ?bA\^2 +ߖ*?*S3o\6.ks'h?km \ No newline at end of file diff --git a/.git/objects/25/508894d2ca5ab047afef7318e44a273730d82e b/.git/objects/25/508894d2ca5ab047afef7318e44a273730d82e new file mode 100644 index 0000000..bcc7626 Binary files /dev/null and b/.git/objects/25/508894d2ca5ab047afef7318e44a273730d82e differ diff --git a/.git/objects/25/526cf910c0726e960a4bc1b8d9892d6a415af4 b/.git/objects/25/526cf910c0726e960a4bc1b8d9892d6a415af4 new file mode 100644 index 0000000..e74326c Binary files /dev/null and b/.git/objects/25/526cf910c0726e960a4bc1b8d9892d6a415af4 differ diff --git a/.git/objects/25/66e735c9363cd3c3d18b197659c38c798e0c51 b/.git/objects/25/66e735c9363cd3c3d18b197659c38c798e0c51 new file mode 100644 index 0000000..a134c9f Binary files /dev/null and b/.git/objects/25/66e735c9363cd3c3d18b197659c38c798e0c51 differ diff --git a/.git/objects/25/6afa1a2ad7e40449252df7a0fef72f9c8d1a08 b/.git/objects/25/6afa1a2ad7e40449252df7a0fef72f9c8d1a08 new file mode 100644 index 0000000..9bf1b6e Binary files /dev/null and b/.git/objects/25/6afa1a2ad7e40449252df7a0fef72f9c8d1a08 differ diff --git a/.git/objects/25/77246b7ee2788f9e534d32647839a89e62b3d6 b/.git/objects/25/77246b7ee2788f9e534d32647839a89e62b3d6 new file mode 100644 index 0000000..04a73ed Binary files /dev/null and b/.git/objects/25/77246b7ee2788f9e534d32647839a89e62b3d6 differ diff --git a/.git/objects/25/818378d9cca73f03fc32eae6edce88fae4097f b/.git/objects/25/818378d9cca73f03fc32eae6edce88fae4097f new file mode 100644 index 0000000..710b35f Binary files /dev/null and b/.git/objects/25/818378d9cca73f03fc32eae6edce88fae4097f differ diff --git a/.git/objects/25/a17cc0326aaef01bbc2c76fe41f57228d93501 b/.git/objects/25/a17cc0326aaef01bbc2c76fe41f57228d93501 new file mode 100644 index 0000000..1ec87c8 Binary files /dev/null and b/.git/objects/25/a17cc0326aaef01bbc2c76fe41f57228d93501 differ diff --git a/.git/objects/25/f4af9eb9fed0cd220e67db39f48dee118782fc b/.git/objects/25/f4af9eb9fed0cd220e67db39f48dee118782fc new file mode 100644 index 0000000..19be155 Binary files /dev/null and b/.git/objects/25/f4af9eb9fed0cd220e67db39f48dee118782fc differ diff --git a/.git/objects/26/14800518032ed5bd3c2b0fa2310bbb8ac0d199 b/.git/objects/26/14800518032ed5bd3c2b0fa2310bbb8ac0d199 new file mode 100644 index 0000000..1543a16 Binary files /dev/null and b/.git/objects/26/14800518032ed5bd3c2b0fa2310bbb8ac0d199 differ diff --git a/.git/objects/26/28ca796ae2745d841c45d750a5257b1db4b35b b/.git/objects/26/28ca796ae2745d841c45d750a5257b1db4b35b new file mode 100644 index 0000000..659c58e Binary files /dev/null and b/.git/objects/26/28ca796ae2745d841c45d750a5257b1db4b35b differ diff --git a/.git/objects/26/33cfe72804919b7d34a567ac82c2a055f15706 b/.git/objects/26/33cfe72804919b7d34a567ac82c2a055f15706 new file mode 100644 index 0000000..e9cc971 --- /dev/null +++ b/.git/objects/26/33cfe72804919b7d34a567ac82c2a055f15706 @@ -0,0 +1,2 @@ +x%Kj0D)z2H}arZrVƲY&GdvU +%@h*磶+ulZ}@s6166  I+xr{hsJ1;s+pnSƴBgJ &*̥d0j~ UV{^Y[ՓDyJyɾ:oEKO \ No newline at end of file diff --git a/.git/objects/26/854c6b3b7fb0b85c712b2ba4c1334d8cdc16ce b/.git/objects/26/854c6b3b7fb0b85c712b2ba4c1334d8cdc16ce new file mode 100644 index 0000000..1a6ee73 Binary files /dev/null and b/.git/objects/26/854c6b3b7fb0b85c712b2ba4c1334d8cdc16ce differ diff --git a/.git/objects/26/c2081cd2994e16888e7c2d9d82e5e275b17b30 b/.git/objects/26/c2081cd2994e16888e7c2d9d82e5e275b17b30 new file mode 100644 index 0000000..bd55173 Binary files /dev/null and b/.git/objects/26/c2081cd2994e16888e7c2d9d82e5e275b17b30 differ diff --git a/.git/objects/26/e1a7fd7c998d0b63eee0bfc04ca89a51f33c8f b/.git/objects/26/e1a7fd7c998d0b63eee0bfc04ca89a51f33c8f new file mode 100644 index 0000000..454e8c0 Binary files /dev/null and b/.git/objects/26/e1a7fd7c998d0b63eee0bfc04ca89a51f33c8f differ diff --git a/.git/objects/27/0adc149fbee54a49c22cc01c583ce2b705c0a3 b/.git/objects/27/0adc149fbee54a49c22cc01c583ce2b705c0a3 new file mode 100644 index 0000000..2ead4f0 Binary files /dev/null and b/.git/objects/27/0adc149fbee54a49c22cc01c583ce2b705c0a3 differ diff --git a/.git/objects/27/0b65b0f8d4ebd39f67dab9e4458f994cc8b371 b/.git/objects/27/0b65b0f8d4ebd39f67dab9e4458f994cc8b371 new file mode 100644 index 0000000..8f8afb4 --- /dev/null +++ b/.git/objects/27/0b65b0f8d4ebd39f67dab9e4458f994cc8b371 @@ -0,0 +1,4 @@ +x]N!}}5O'ށf#`։x*WUwV~M + +d/1U O J5-#hދFUrVϴEkYA^{T\iw=+QěAOuڎg_+4mL\pЮ@TG>>'W +S/jW \ No newline at end of file diff --git a/.git/objects/27/0c1f9227dc82700b3d3cb31a22f1d032bb4487 b/.git/objects/27/0c1f9227dc82700b3d3cb31a22f1d032bb4487 new file mode 100644 index 0000000..ae13668 Binary files /dev/null and b/.git/objects/27/0c1f9227dc82700b3d3cb31a22f1d032bb4487 differ diff --git a/.git/objects/27/1ccbae1226e1821f113471b9389174529230a9 b/.git/objects/27/1ccbae1226e1821f113471b9389174529230a9 new file mode 100644 index 0000000..de3aa03 Binary files /dev/null and b/.git/objects/27/1ccbae1226e1821f113471b9389174529230a9 differ diff --git a/.git/objects/27/2b685927c6605492e9e1ac33de06fc973aee27 b/.git/objects/27/2b685927c6605492e9e1ac33de06fc973aee27 new file mode 100644 index 0000000..f9f64a4 Binary files /dev/null and b/.git/objects/27/2b685927c6605492e9e1ac33de06fc973aee27 differ diff --git a/.git/objects/27/3f0efbc7f4ddbe0d389314d2b787a4ccbabb4e b/.git/objects/27/3f0efbc7f4ddbe0d389314d2b787a4ccbabb4e new file mode 100644 index 0000000..5dd903c Binary files /dev/null and b/.git/objects/27/3f0efbc7f4ddbe0d389314d2b787a4ccbabb4e differ diff --git a/.git/objects/27/4f256a63d80d4c122a6811f49602386788f3e9 b/.git/objects/27/4f256a63d80d4c122a6811f49602386788f3e9 new file mode 100644 index 0000000..b74003a --- /dev/null +++ b/.git/objects/27/4f256a63d80d4c122a6811f49602386788f3e9 @@ -0,0 +1,2 @@ +x-N0 9)|GLN4!pk&i؛qŰKcfx6&AHvk{'PT-kI +]glѷfβohs.%^ VN]p$̳HDn;#(5b#WᮒQCXoflky[zI/^o C?8#E:휚`+C LRS[ \ No newline at end of file diff --git a/.git/objects/28/27e0654e43ebec2b1f3fa2e972f0f6795a92b8 b/.git/objects/28/27e0654e43ebec2b1f3fa2e972f0f6795a92b8 new file mode 100644 index 0000000..e7f1a27 Binary files /dev/null and b/.git/objects/28/27e0654e43ebec2b1f3fa2e972f0f6795a92b8 differ diff --git a/.git/objects/28/5d960a9f8350d66cb94158e6823400636897e6 b/.git/objects/28/5d960a9f8350d66cb94158e6823400636897e6 new file mode 100644 index 0000000..eb53f05 Binary files /dev/null and b/.git/objects/28/5d960a9f8350d66cb94158e6823400636897e6 differ diff --git a/.git/objects/28/61620c39d8d49e6e276e7b25717fdc86963386 b/.git/objects/28/61620c39d8d49e6e276e7b25717fdc86963386 new file mode 100644 index 0000000..ecb2498 Binary files /dev/null and b/.git/objects/28/61620c39d8d49e6e276e7b25717fdc86963386 differ diff --git a/.git/objects/28/750e5605660b50fddaae066b536324bf6b36bd b/.git/objects/28/750e5605660b50fddaae066b536324bf6b36bd new file mode 100644 index 0000000..c88a49d Binary files /dev/null and b/.git/objects/28/750e5605660b50fddaae066b536324bf6b36bd differ diff --git a/.git/objects/28/9867fc1afa1784219f79d5d206d9be2c4e2988 b/.git/objects/28/9867fc1afa1784219f79d5d206d9be2c4e2988 new file mode 100644 index 0000000..5e08c5b Binary files /dev/null and b/.git/objects/28/9867fc1afa1784219f79d5d206d9be2c4e2988 differ diff --git a/.git/objects/28/aeeb75ee114fd31f361e8f000cbb21c1ff04a8 b/.git/objects/28/aeeb75ee114fd31f361e8f000cbb21c1ff04a8 new file mode 100644 index 0000000..70535fe Binary files /dev/null and b/.git/objects/28/aeeb75ee114fd31f361e8f000cbb21c1ff04a8 differ diff --git a/.git/objects/28/e6f0f202bfc69892ed001223537222a1703966 b/.git/objects/28/e6f0f202bfc69892ed001223537222a1703966 new file mode 100644 index 0000000..3712194 Binary files /dev/null and b/.git/objects/28/e6f0f202bfc69892ed001223537222a1703966 differ diff --git a/.git/objects/29/047ae0f3ccb08ff7ca222e0d0d1ca70144e5ca b/.git/objects/29/047ae0f3ccb08ff7ca222e0d0d1ca70144e5ca new file mode 100644 index 0000000..5c6bba3 Binary files /dev/null and b/.git/objects/29/047ae0f3ccb08ff7ca222e0d0d1ca70144e5ca differ diff --git a/.git/objects/29/42e779904955a991ea1e291a9e0a21591049a3 b/.git/objects/29/42e779904955a991ea1e291a9e0a21591049a3 new file mode 100644 index 0000000..16a0e55 Binary files /dev/null and b/.git/objects/29/42e779904955a991ea1e291a9e0a21591049a3 differ diff --git a/.git/objects/29/5ff345ba456dc0a7b92fe4aad9752e13521fcc b/.git/objects/29/5ff345ba456dc0a7b92fe4aad9752e13521fcc new file mode 100644 index 0000000..78312ec Binary files /dev/null and b/.git/objects/29/5ff345ba456dc0a7b92fe4aad9752e13521fcc differ diff --git a/.git/objects/29/88519d4e8d82b7f6dad48100860133ea0509b7 b/.git/objects/29/88519d4e8d82b7f6dad48100860133ea0509b7 new file mode 100644 index 0000000..af9e29a Binary files /dev/null and b/.git/objects/29/88519d4e8d82b7f6dad48100860133ea0509b7 differ diff --git a/.git/objects/29/89bdb1600505a066ef07159bb8e9da274b4a2d b/.git/objects/29/89bdb1600505a066ef07159bb8e9da274b4a2d new file mode 100644 index 0000000..22a27d4 --- /dev/null +++ b/.git/objects/29/89bdb1600505a066ef07159bb8e9da274b4a2d @@ -0,0 +1,4 @@ +x-MN0FYGDVjņeRlfb1hI! +bj&AH25q's(q.1K4Ҡbm$JV\ rDžFD+k(VFK^I+ +ExΑ +*7)<i%pc]6<-xm +E21Oc \ No newline at end of file diff --git a/.git/objects/2a/afe57f91a82e876341991387c80023a43db478 b/.git/objects/2a/afe57f91a82e876341991387c80023a43db478 new file mode 100644 index 0000000..d975ede Binary files /dev/null and b/.git/objects/2a/afe57f91a82e876341991387c80023a43db478 differ diff --git a/.git/objects/2a/b2a30adab8cd07f5c73aeaaa1f9e9cad2f6314 b/.git/objects/2a/b2a30adab8cd07f5c73aeaaa1f9e9cad2f6314 new file mode 100644 index 0000000..643747a Binary files /dev/null and b/.git/objects/2a/b2a30adab8cd07f5c73aeaaa1f9e9cad2f6314 differ diff --git a/.git/objects/2a/b4c83b7a9ce6d4c187f761068b357551812b10 b/.git/objects/2a/b4c83b7a9ce6d4c187f761068b357551812b10 new file mode 100644 index 0000000..9e3cf45 Binary files /dev/null and b/.git/objects/2a/b4c83b7a9ce6d4c187f761068b357551812b10 differ diff --git a/.git/objects/2a/cbd5f86b418f36c3858f168ec5d90769bf9b9a b/.git/objects/2a/cbd5f86b418f36c3858f168ec5d90769bf9b9a new file mode 100644 index 0000000..8b904ed Binary files /dev/null and b/.git/objects/2a/cbd5f86b418f36c3858f168ec5d90769bf9b9a differ diff --git a/.git/objects/2a/e001a20b022b0a1c6f341a10b2f76eac956235 b/.git/objects/2a/e001a20b022b0a1c6f341a10b2f76eac956235 new file mode 100644 index 0000000..4d74979 Binary files /dev/null and b/.git/objects/2a/e001a20b022b0a1c6f341a10b2f76eac956235 differ diff --git a/.git/objects/2a/fd981cda8f0aeac9eb899c80389c38c73ef753 b/.git/objects/2a/fd981cda8f0aeac9eb899c80389c38c73ef753 new file mode 100644 index 0000000..6770c99 Binary files /dev/null and b/.git/objects/2a/fd981cda8f0aeac9eb899c80389c38c73ef753 differ diff --git a/.git/objects/2b/0c137cd89cc02fae0b3a68605fd64350877a41 b/.git/objects/2b/0c137cd89cc02fae0b3a68605fd64350877a41 new file mode 100644 index 0000000..b40bf29 Binary files /dev/null and b/.git/objects/2b/0c137cd89cc02fae0b3a68605fd64350877a41 differ diff --git a/.git/objects/2b/23921e27bd6ea00e1a0085b39542e79ea0ca3d b/.git/objects/2b/23921e27bd6ea00e1a0085b39542e79ea0ca3d new file mode 100644 index 0000000..7419e7e Binary files /dev/null and b/.git/objects/2b/23921e27bd6ea00e1a0085b39542e79ea0ca3d differ diff --git a/.git/objects/2b/3a47970e0be34664ba812e8f372aef58f74f25 b/.git/objects/2b/3a47970e0be34664ba812e8f372aef58f74f25 new file mode 100644 index 0000000..944f196 Binary files /dev/null and b/.git/objects/2b/3a47970e0be34664ba812e8f372aef58f74f25 differ diff --git a/.git/objects/2b/43d42c76113f679a7c628798eb3a3a9c052311 b/.git/objects/2b/43d42c76113f679a7c628798eb3a3a9c052311 new file mode 100644 index 0000000..7206b07 Binary files /dev/null and b/.git/objects/2b/43d42c76113f679a7c628798eb3a3a9c052311 differ diff --git a/.git/objects/2b/92c0a858a4db4b259033d058db96df52f6203b b/.git/objects/2b/92c0a858a4db4b259033d058db96df52f6203b new file mode 100644 index 0000000..4fc6630 --- /dev/null +++ b/.git/objects/2b/92c0a858a4db4b259033d058db96df52f6203b @@ -0,0 +1,2 @@ +x-j {S-EM +K)V ҧob `%{=Xb~Q /xg\iW2Fi(@=, >ljJ*%4r&d|C7?MK̑dS| cMu3^6<ӊⅮxo5X_ML.L]Xgs:d*?X6:Ж%dzTzEX!Mhm&{ZK œ(g= \ No newline at end of file diff --git a/.git/objects/2b/a60860eac801c39c8ae794fda8ad32caa000b6 b/.git/objects/2b/a60860eac801c39c8ae794fda8ad32caa000b6 new file mode 100644 index 0000000..8255db4 Binary files /dev/null and b/.git/objects/2b/a60860eac801c39c8ae794fda8ad32caa000b6 differ diff --git a/.git/objects/2b/b92f73c32687094521d6b97c332a7fe48fe0ce b/.git/objects/2b/b92f73c32687094521d6b97c332a7fe48fe0ce new file mode 100644 index 0000000..1639d6b Binary files /dev/null and b/.git/objects/2b/b92f73c32687094521d6b97c332a7fe48fe0ce differ diff --git a/.git/objects/2b/d1f2a3c7c076803dd2224b93a8df9632f4e4f3 b/.git/objects/2b/d1f2a3c7c076803dd2224b93a8df9632f4e4f3 new file mode 100644 index 0000000..7b54c89 Binary files /dev/null and b/.git/objects/2b/d1f2a3c7c076803dd2224b93a8df9632f4e4f3 differ diff --git a/.git/objects/2b/d552c9e0cdd1aa52221ee59e0ef02b60ba173a b/.git/objects/2b/d552c9e0cdd1aa52221ee59e0ef02b60ba173a new file mode 100644 index 0000000..4ad1a8c --- /dev/null +++ b/.git/objects/2b/d552c9e0cdd1aa52221ee59e0ef02b60ba173a @@ -0,0 +1,2 @@ +x=N0`jb{$ر44`m_"%v)f\ vfiBtW"'-78bsuE9rRP@6K=p(4U5x>0U78toV+)>Xyb[CEC:gm \ No newline at end of file diff --git a/.git/objects/2c/552356022e8eadde3837515d2fead97851e81a b/.git/objects/2c/552356022e8eadde3837515d2fead97851e81a new file mode 100644 index 0000000..9aaaa22 Binary files /dev/null and b/.git/objects/2c/552356022e8eadde3837515d2fead97851e81a differ diff --git a/.git/objects/2c/68ffda5cfad0c1798221a6c1a3bc2861264f7f b/.git/objects/2c/68ffda5cfad0c1798221a6c1a3bc2861264f7f new file mode 100644 index 0000000..e3ec00d Binary files /dev/null and b/.git/objects/2c/68ffda5cfad0c1798221a6c1a3bc2861264f7f differ diff --git a/.git/objects/2c/848ea825b2d82f63a9fa0ec993e7c4dde3bbf0 b/.git/objects/2c/848ea825b2d82f63a9fa0ec993e7c4dde3bbf0 new file mode 100644 index 0000000..ba3d450 --- /dev/null +++ b/.git/objects/2c/848ea825b2d82f63a9fa0ec993e7c4dde3bbf0 @@ -0,0 +1,7 @@ +xUkPWHIFt@REѱƤ(P,&1 G +h[@K|?p!VDCTb~9{=ң¥Fa*У\6?կi}"'vJ)QSzv W/Ejf(Hs7\UE3(\Vno?~%b:3k%r}L|VnI?81p4~2$ݬrYxv́ad[_u \ No newline at end of file diff --git a/.git/objects/2c/84adb72615f44dcf534424b75ad0478a948156 b/.git/objects/2c/84adb72615f44dcf534424b75ad0478a948156 new file mode 100644 index 0000000..394cabb Binary files /dev/null and b/.git/objects/2c/84adb72615f44dcf534424b75ad0478a948156 differ diff --git a/.git/objects/2c/b80b60049e1d31e1a89fdc43f6923a873cc739 b/.git/objects/2c/b80b60049e1d31e1a89fdc43f6923a873cc739 new file mode 100644 index 0000000..ec8884f Binary files /dev/null and b/.git/objects/2c/b80b60049e1d31e1a89fdc43f6923a873cc739 differ diff --git a/.git/objects/2c/d395932002dd1db3c00b9c13311b50c1009df7 b/.git/objects/2c/d395932002dd1db3c00b9c13311b50c1009df7 new file mode 100644 index 0000000..3e38682 Binary files /dev/null and b/.git/objects/2c/d395932002dd1db3c00b9c13311b50c1009df7 differ diff --git a/.git/objects/2c/f370cf38cbc72ab98cc039f111c293adb343ed b/.git/objects/2c/f370cf38cbc72ab98cc039f111c293adb343ed new file mode 100644 index 0000000..a9cdef7 Binary files /dev/null and b/.git/objects/2c/f370cf38cbc72ab98cc039f111c293adb343ed differ diff --git a/.git/objects/2c/fc2dfe6f2b662d823293a5e6a5dadf69c884c5 b/.git/objects/2c/fc2dfe6f2b662d823293a5e6a5dadf69c884c5 new file mode 100644 index 0000000..fabd09f Binary files /dev/null and b/.git/objects/2c/fc2dfe6f2b662d823293a5e6a5dadf69c884c5 differ diff --git a/.git/objects/2d/14f09b1e604c6417dc355c70c40e9bf9dce537 b/.git/objects/2d/14f09b1e604c6417dc355c70c40e9bf9dce537 new file mode 100644 index 0000000..8145fad Binary files /dev/null and b/.git/objects/2d/14f09b1e604c6417dc355c70c40e9bf9dce537 differ diff --git a/.git/objects/2d/412d2a2bf58445d6533b734a4ebda46fe7d8fe b/.git/objects/2d/412d2a2bf58445d6533b734a4ebda46fe7d8fe new file mode 100644 index 0000000..5ce8724 Binary files /dev/null and b/.git/objects/2d/412d2a2bf58445d6533b734a4ebda46fe7d8fe differ diff --git a/.git/objects/2d/5db255b28079c17791fe1e6fc4b323bddc1130 b/.git/objects/2d/5db255b28079c17791fe1e6fc4b323bddc1130 new file mode 100644 index 0000000..2b574c2 Binary files /dev/null and b/.git/objects/2d/5db255b28079c17791fe1e6fc4b323bddc1130 differ diff --git a/.git/objects/2d/7a93b05c876d0459ccce91a9c529c1d08c01c2 b/.git/objects/2d/7a93b05c876d0459ccce91a9c529c1d08c01c2 new file mode 100644 index 0000000..5a3d95f Binary files /dev/null and b/.git/objects/2d/7a93b05c876d0459ccce91a9c529c1d08c01c2 differ diff --git a/.git/objects/2d/a891e3d1fe702eab3353765f12def1ddf2a428 b/.git/objects/2d/a891e3d1fe702eab3353765f12def1ddf2a428 new file mode 100644 index 0000000..be67a0f Binary files /dev/null and b/.git/objects/2d/a891e3d1fe702eab3353765f12def1ddf2a428 differ diff --git a/.git/objects/2d/bfdf2d8f7e2b2d24a96eab2999e926d597ae48 b/.git/objects/2d/bfdf2d8f7e2b2d24a96eab2999e926d597ae48 new file mode 100644 index 0000000..146b16e Binary files /dev/null and b/.git/objects/2d/bfdf2d8f7e2b2d24a96eab2999e926d597ae48 differ diff --git a/.git/objects/2d/f8d405827ae3eb0b0328708190f1e7dc414dcc b/.git/objects/2d/f8d405827ae3eb0b0328708190f1e7dc414dcc new file mode 100644 index 0000000..f49f691 Binary files /dev/null and b/.git/objects/2d/f8d405827ae3eb0b0328708190f1e7dc414dcc differ diff --git a/.git/objects/2e/26c9c9ca6324a88f562271d8d6827f364b3696 b/.git/objects/2e/26c9c9ca6324a88f562271d8d6827f364b3696 new file mode 100644 index 0000000..a19cdb7 Binary files /dev/null and b/.git/objects/2e/26c9c9ca6324a88f562271d8d6827f364b3696 differ diff --git a/.git/objects/2e/5291d37cacba94eee3b50793b221a4d47accd8 b/.git/objects/2e/5291d37cacba94eee3b50793b221a4d47accd8 new file mode 100644 index 0000000..257bc1c Binary files /dev/null and b/.git/objects/2e/5291d37cacba94eee3b50793b221a4d47accd8 differ diff --git a/.git/objects/2e/81a3cec6f54caf74a072ac000480a2a10aac9f b/.git/objects/2e/81a3cec6f54caf74a072ac000480a2a10aac9f new file mode 100644 index 0000000..45a64ee --- /dev/null +++ b/.git/objects/2e/81a3cec6f54caf74a072ac000480a2a10aac9f @@ -0,0 +1,2 @@ +xUN0ۥ@'QCHǽ=/hֆu3H=*dR;92TϹrFՆ|Z-te+f36* +<O }wuak"o?S9O4Kp za}.}`*jٝK/!dqe[a*%ඥc@?29='4_CPS_b \ No newline at end of file diff --git a/.git/objects/2e/bf56af435ce1b81f1f5c96a71ca43c872f846c b/.git/objects/2e/bf56af435ce1b81f1f5c96a71ca43c872f846c new file mode 100644 index 0000000..2dfc726 Binary files /dev/null and b/.git/objects/2e/bf56af435ce1b81f1f5c96a71ca43c872f846c differ diff --git a/.git/objects/2e/d1a0f68922eeaeaec166abb373fe3804318e7a b/.git/objects/2e/d1a0f68922eeaeaec166abb373fe3804318e7a new file mode 100644 index 0000000..1fe91d0 Binary files /dev/null and b/.git/objects/2e/d1a0f68922eeaeaec166abb373fe3804318e7a differ diff --git a/.git/objects/2e/f6406308c1b9b0f6885429cbf06f30225e98a4 b/.git/objects/2e/f6406308c1b9b0f6885429cbf06f30225e98a4 new file mode 100644 index 0000000..af58bbf Binary files /dev/null and b/.git/objects/2e/f6406308c1b9b0f6885429cbf06f30225e98a4 differ diff --git a/.git/objects/2f/146bed39adeaade0c8b7484372094ff38df9d9 b/.git/objects/2f/146bed39adeaade0c8b7484372094ff38df9d9 new file mode 100644 index 0000000..12a64c7 --- /dev/null +++ b/.git/objects/2f/146bed39adeaade0c8b7484372094ff38df9d9 @@ -0,0 +1,4 @@ +xRn@쯘ZUW .@ZAʁ 8p@'zg'D&Q8ղd}^xٻ[lrg4F- +C$v +%K*#?')/K0[ U-)kIWGǹ7\kx+~xuN]{(Uǰ c'[v$N@ +F3b4,}gZGp6|1/ Lğs`P3DnpgZ@T_$4=Dt֐K^Ûb<+TU!=4fibxj'd8^S%&YR6C1t[cdt_a:ȓ]ﶶQwm#h`g 5+Hǽ'L,5{g>bC_fZ=ebbx1v& hAS \ No newline at end of file diff --git a/.git/objects/2f/1f11f91cafb4709159610978df9b53be7a3070 b/.git/objects/2f/1f11f91cafb4709159610978df9b53be7a3070 new file mode 100644 index 0000000..cf23cb6 Binary files /dev/null and b/.git/objects/2f/1f11f91cafb4709159610978df9b53be7a3070 differ diff --git a/.git/objects/2f/2aa82eb860bd08e97db48c155fc31484c01bd3 b/.git/objects/2f/2aa82eb860bd08e97db48c155fc31484c01bd3 new file mode 100644 index 0000000..b7472ba Binary files /dev/null and b/.git/objects/2f/2aa82eb860bd08e97db48c155fc31484c01bd3 differ diff --git a/.git/objects/2f/3657f19600f7020d3a4485747605ebbad9c62d b/.git/objects/2f/3657f19600f7020d3a4485747605ebbad9c62d new file mode 100644 index 0000000..efeb27e Binary files /dev/null and b/.git/objects/2f/3657f19600f7020d3a4485747605ebbad9c62d differ diff --git a/.git/objects/2f/542f5f0cbac3922f4b2723a9f9f418a773ee48 b/.git/objects/2f/542f5f0cbac3922f4b2723a9f9f418a773ee48 new file mode 100644 index 0000000..50ea33f Binary files /dev/null and b/.git/objects/2f/542f5f0cbac3922f4b2723a9f9f418a773ee48 differ diff --git a/.git/objects/2f/8b80efb7e70140fcbeeac0b19f6c1808c24a05 b/.git/objects/2f/8b80efb7e70140fcbeeac0b19f6c1808c24a05 new file mode 100644 index 0000000..05c9012 Binary files /dev/null and b/.git/objects/2f/8b80efb7e70140fcbeeac0b19f6c1808c24a05 differ diff --git a/.git/objects/2f/abed0a19b53d002ca2adbe3bc887877360f82c b/.git/objects/2f/abed0a19b53d002ca2adbe3bc887877360f82c new file mode 100644 index 0000000..9faa51f Binary files /dev/null and b/.git/objects/2f/abed0a19b53d002ca2adbe3bc887877360f82c differ diff --git a/.git/objects/2f/e40e353f246aa8323ed4aa4ceec4d265937d5f b/.git/objects/2f/e40e353f246aa8323ed4aa4ceec4d265937d5f new file mode 100644 index 0000000..630ec9d Binary files /dev/null and b/.git/objects/2f/e40e353f246aa8323ed4aa4ceec4d265937d5f differ diff --git a/.git/objects/2f/f964ceb897038542c08cd40c46c9795d355d72 b/.git/objects/2f/f964ceb897038542c08cd40c46c9795d355d72 new file mode 100644 index 0000000..ebff254 Binary files /dev/null and b/.git/objects/2f/f964ceb897038542c08cd40c46c9795d355d72 differ diff --git a/.git/objects/30/0eb02d409d713866dcf987485823d75a278049 b/.git/objects/30/0eb02d409d713866dcf987485823d75a278049 new file mode 100644 index 0000000..3f8108f Binary files /dev/null and b/.git/objects/30/0eb02d409d713866dcf987485823d75a278049 differ diff --git a/.git/objects/30/1ad3cd1abe2ad1014e6d1f647964f065717f76 b/.git/objects/30/1ad3cd1abe2ad1014e6d1f647964f065717f76 new file mode 100644 index 0000000..1be56ae --- /dev/null +++ b/.git/objects/30/1ad3cd1abe2ad1014e6d1f647964f065717f76 @@ -0,0 +1,2 @@ +xMN0FYGBv + SgDJ1 {.}zz(Ԫ`->%vF4cHdE8 W (hM0 zɆOW"bOؠlSpY(X~f}}kLRJ~IJj;Vjw/pYr@m7r]zGzZm~d \ No newline at end of file diff --git a/.git/objects/30/4b7e9f0056033d9006bffa74ee85184bc74cd7 b/.git/objects/30/4b7e9f0056033d9006bffa74ee85184bc74cd7 new file mode 100644 index 0000000..7d71309 --- /dev/null +++ b/.git/objects/30/4b7e9f0056033d9006bffa74ee85184bc74cd7 @@ -0,0 +1 @@ +xMJ@]Si OPS]&]Cf}dYfk;-`mיq##>]|8/Sܰp 6&t:.zۮM')zȏ |$WWS2pšSHQ~ YWуqZӶMVo"6ʣ$+l+Ög 7.^.#Ra0~yՇxo \ No newline at end of file diff --git a/.git/objects/30/5f682353e41db2665c9be9081d2ad1e5c75ef9 b/.git/objects/30/5f682353e41db2665c9be9081d2ad1e5c75ef9 new file mode 100644 index 0000000..1f3770e Binary files /dev/null and b/.git/objects/30/5f682353e41db2665c9be9081d2ad1e5c75ef9 differ diff --git a/.git/objects/30/69294936229011adbe64de5a52afe5f6c9ed0a b/.git/objects/30/69294936229011adbe64de5a52afe5f6c9ed0a new file mode 100644 index 0000000..7babd13 Binary files /dev/null and b/.git/objects/30/69294936229011adbe64de5a52afe5f6c9ed0a differ diff --git a/.git/objects/30/6ae7d497b3316a52decbd6b8e0e3211bd54666 b/.git/objects/30/6ae7d497b3316a52decbd6b8e0e3211bd54666 new file mode 100644 index 0000000..7bcf73e Binary files /dev/null and b/.git/objects/30/6ae7d497b3316a52decbd6b8e0e3211bd54666 differ diff --git a/.git/objects/30/9320482d3f835e2eb24adf02c77eefb673560d b/.git/objects/30/9320482d3f835e2eb24adf02c77eefb673560d new file mode 100644 index 0000000..d946dc4 Binary files /dev/null and b/.git/objects/30/9320482d3f835e2eb24adf02c77eefb673560d differ diff --git a/.git/objects/30/9953507d962b33da3a00cd01518cf397e2ca67 b/.git/objects/30/9953507d962b33da3a00cd01518cf397e2ca67 new file mode 100644 index 0000000..a3b3661 Binary files /dev/null and b/.git/objects/30/9953507d962b33da3a00cd01518cf397e2ca67 differ diff --git a/.git/objects/30/ad2f3cfe7ad7b94ef5e47ef6cd1cf7a787f399 b/.git/objects/30/ad2f3cfe7ad7b94ef5e47ef6cd1cf7a787f399 new file mode 100644 index 0000000..f1e2887 Binary files /dev/null and b/.git/objects/30/ad2f3cfe7ad7b94ef5e47ef6cd1cf7a787f399 differ diff --git a/.git/objects/30/c5b93d6f8f2e024c39470138507519f8b5f8a1 b/.git/objects/30/c5b93d6f8f2e024c39470138507519f8b5f8a1 new file mode 100644 index 0000000..f097668 --- /dev/null +++ b/.git/objects/30/c5b93d6f8f2e024c39470138507519f8b5f8a1 @@ -0,0 +1,2 @@ +xOKj1ڧxO9ib۟@iv3tKG/gxW8jy`ߔ {PHSb \ No newline at end of file diff --git a/.git/objects/35/9987c53cdeca60ddfdc814e1cc9cb5f5f0409f b/.git/objects/35/9987c53cdeca60ddfdc814e1cc9cb5f5f0409f new file mode 100644 index 0000000..8cd6bf6 Binary files /dev/null and b/.git/objects/35/9987c53cdeca60ddfdc814e1cc9cb5f5f0409f differ diff --git a/.git/objects/35/a4894c423521aa2b34bce41d320c5a146fa637 b/.git/objects/35/a4894c423521aa2b34bce41d320c5a146fa637 new file mode 100644 index 0000000..0e1bfc7 Binary files /dev/null and b/.git/objects/35/a4894c423521aa2b34bce41d320c5a146fa637 differ diff --git a/.git/objects/35/df7b4f3017cf49fd4b3313d6cde4ba14b93d14 b/.git/objects/35/df7b4f3017cf49fd4b3313d6cde4ba14b93d14 new file mode 100644 index 0000000..bd53153 --- /dev/null +++ b/.git/objects/35/df7b4f3017cf49fd4b3313d6cde4ba14b93d14 @@ -0,0 +1 @@ +x-MN0 Y#I3Aa3'pgZI4Лbdl٦BO%UjV ^)+c'#hW͊bA=R;DQ=CՏ ˔2-Q٦"\s X2TO[GkSx^{!cMֿKyG7pO\pC{_w ͘}#uNpMx<D ЎǦu] +!J&IFXF1#3G¨cLUƹAfB&s=)j4sS@2/670|HeV)ަ-Y[A[k[wQ*Gl0D0CT8ɖ Ϫ^<ǒN+)%Nao~)s \ No newline at end of file diff --git a/.git/objects/36/782e44f04b3f4d073c222d762c0987ef12fab4 b/.git/objects/36/782e44f04b3f4d073c222d762c0987ef12fab4 new file mode 100644 index 0000000..1aa9e9b Binary files /dev/null and b/.git/objects/36/782e44f04b3f4d073c222d762c0987ef12fab4 differ diff --git a/.git/objects/36/c0da1c1579701d3b4c8f71acfd16a8a41b7d92 b/.git/objects/36/c0da1c1579701d3b4c8f71acfd16a8a41b7d92 new file mode 100644 index 0000000..057bec6 --- /dev/null +++ b/.git/objects/36/c0da1c1579701d3b4c8f71acfd16a8a41b7d92 @@ -0,0 +1 @@ +x%NKN0dSez$*TT>+pg1jqD{3\ #qq|i&'fBs熖AhMumXt镳Zl R]͔8ddTZ4䐙E746JiݩBي<gP9wLׅ|| 쩸V6|#8cc/uI[ަ +3%F& C׾wm9oK^ |g nGړ; ٻbXT AIm)T֭!̥x_t \ No newline at end of file diff --git a/.git/objects/36/e4f7e48a42ce988b957251ce07a45ad7f26137 b/.git/objects/36/e4f7e48a42ce988b957251ce07a45ad7f26137 new file mode 100644 index 0000000..399b826 Binary files /dev/null and b/.git/objects/36/e4f7e48a42ce988b957251ce07a45ad7f26137 differ diff --git a/.git/objects/37/15934c001b1f741f49d38ebe9d76691f3d29cf b/.git/objects/37/15934c001b1f741f49d38ebe9d76691f3d29cf new file mode 100644 index 0000000..ce0d453 Binary files /dev/null and b/.git/objects/37/15934c001b1f741f49d38ebe9d76691f3d29cf differ diff --git a/.git/objects/37/1a947146e041dbe043c6886e44965efb025786 b/.git/objects/37/1a947146e041dbe043c6886e44965efb025786 new file mode 100644 index 0000000..e037efa Binary files /dev/null and b/.git/objects/37/1a947146e041dbe043c6886e44965efb025786 differ diff --git a/.git/objects/37/23f34a1169620eb7ce4fc082d56585844655cc b/.git/objects/37/23f34a1169620eb7ce4fc082d56585844655cc new file mode 100644 index 0000000..cffb89a --- /dev/null +++ b/.git/objects/37/23f34a1169620eb7ce4fc082d56585844655cc @@ -0,0 +1,3 @@ +x%N0D]lDZtB u)?Ljbfh\@dfU-*OJס<)[ER:OΡRV+fd{4:ʐA28]gڞ | +2 c$1i>r x2tT1[=RM;% < +%D5cm)<ಇ5wVJkIα HpZ9|3l W}7\F \ No newline at end of file diff --git a/.git/objects/37/3adcc930148da0f1c252b22669f4604422b45c b/.git/objects/37/3adcc930148da0f1c252b22669f4604422b45c new file mode 100644 index 0000000..6a470d4 Binary files /dev/null and b/.git/objects/37/3adcc930148da0f1c252b22669f4604422b45c differ diff --git a/.git/objects/37/3bb1808d7246f773d87e39d61d8d0cfb2f6819 b/.git/objects/37/3bb1808d7246f773d87e39d61d8d0cfb2f6819 new file mode 100644 index 0000000..101148c Binary files /dev/null and b/.git/objects/37/3bb1808d7246f773d87e39d61d8d0cfb2f6819 differ diff --git a/.git/objects/37/94bb29b619e2d375e17ce587b69282e7f05617 b/.git/objects/37/94bb29b619e2d375e17ce587b69282e7f05617 new file mode 100644 index 0000000..e5a8088 Binary files /dev/null and b/.git/objects/37/94bb29b619e2d375e17ce587b69282e7f05617 differ diff --git a/.git/objects/37/d39b6d662b2f90959ff2498fbce956976906a0 b/.git/objects/37/d39b6d662b2f90959ff2498fbce956976906a0 new file mode 100644 index 0000000..c92d783 Binary files /dev/null and b/.git/objects/37/d39b6d662b2f90959ff2498fbce956976906a0 differ diff --git a/.git/objects/37/f3d792af5b91a3ecd013f1e0a2afdbd1b81061 b/.git/objects/37/f3d792af5b91a3ecd013f1e0a2afdbd1b81061 new file mode 100644 index 0000000..8c3d421 Binary files /dev/null and b/.git/objects/37/f3d792af5b91a3ecd013f1e0a2afdbd1b81061 differ diff --git a/.git/objects/38/159e3fb4f65149048023e24d76af8d25b401f5 b/.git/objects/38/159e3fb4f65149048023e24d76af8d25b401f5 new file mode 100644 index 0000000..4840522 Binary files /dev/null and b/.git/objects/38/159e3fb4f65149048023e24d76af8d25b401f5 differ diff --git a/.git/objects/38/553c73717980b697cc0f17853405bb717bcd51 b/.git/objects/38/553c73717980b697cc0f17853405bb717bcd51 new file mode 100644 index 0000000..7f14e0e Binary files /dev/null and b/.git/objects/38/553c73717980b697cc0f17853405bb717bcd51 differ diff --git a/.git/objects/38/61126761ecb202f653235dfbb40ea8b3c010f4 b/.git/objects/38/61126761ecb202f653235dfbb40ea8b3c010f4 new file mode 100644 index 0000000..32b838e Binary files /dev/null and b/.git/objects/38/61126761ecb202f653235dfbb40ea8b3c010f4 differ diff --git a/.git/objects/38/6fd74360b78c265df6ce8f86a5bc42c6e84112 b/.git/objects/38/6fd74360b78c265df6ce8f86a5bc42c6e84112 new file mode 100644 index 0000000..24af258 Binary files /dev/null and b/.git/objects/38/6fd74360b78c265df6ce8f86a5bc42c6e84112 differ diff --git a/.git/objects/38/907c94d889b54efc4b272426c9ed65dcb34e3c b/.git/objects/38/907c94d889b54efc4b272426c9ed65dcb34e3c new file mode 100644 index 0000000..4541ea3 Binary files /dev/null and b/.git/objects/38/907c94d889b54efc4b272426c9ed65dcb34e3c differ diff --git a/.git/objects/38/982d18ddff22eb4004ec53d198d68616a4ff99 b/.git/objects/38/982d18ddff22eb4004ec53d198d68616a4ff99 new file mode 100644 index 0000000..02d0c8e Binary files /dev/null and b/.git/objects/38/982d18ddff22eb4004ec53d198d68616a4ff99 differ diff --git a/.git/objects/38/d419e26653c6ee816b47e985f62ac27e512398 b/.git/objects/38/d419e26653c6ee816b47e985f62ac27e512398 new file mode 100644 index 0000000..acacde7 Binary files /dev/null and b/.git/objects/38/d419e26653c6ee816b47e985f62ac27e512398 differ diff --git a/.git/objects/38/ea4f043e749cf71a7a79ae8e3705a3a4eb602f b/.git/objects/38/ea4f043e749cf71a7a79ae8e3705a3a4eb602f new file mode 100644 index 0000000..61faef8 Binary files /dev/null and b/.git/objects/38/ea4f043e749cf71a7a79ae8e3705a3a4eb602f differ diff --git a/.git/objects/39/007c02ae94b68d7058ac1ea32b07ad7f817f27 b/.git/objects/39/007c02ae94b68d7058ac1ea32b07ad7f817f27 new file mode 100644 index 0000000..677c0ff Binary files /dev/null and b/.git/objects/39/007c02ae94b68d7058ac1ea32b07ad7f817f27 differ diff --git a/.git/objects/39/19c89f3d7e0f96492ca681897f71781de19987 b/.git/objects/39/19c89f3d7e0f96492ca681897f71781de19987 new file mode 100644 index 0000000..afe9f68 Binary files /dev/null and b/.git/objects/39/19c89f3d7e0f96492ca681897f71781de19987 differ diff --git a/.git/objects/39/1a3ad9b9a2be9a4255eec18f52f46ddadc107d b/.git/objects/39/1a3ad9b9a2be9a4255eec18f52f46ddadc107d new file mode 100644 index 0000000..083ca0f Binary files /dev/null and b/.git/objects/39/1a3ad9b9a2be9a4255eec18f52f46ddadc107d differ diff --git a/.git/objects/39/233922471a1ca18420e4c37f1d7555d72fdc01 b/.git/objects/39/233922471a1ca18420e4c37f1d7555d72fdc01 new file mode 100644 index 0000000..afb2849 --- /dev/null +++ b/.git/objects/39/233922471a1ca18420e4c37f1d7555d72fdc01 @@ -0,0 +1,3 @@ +x-NJ0uݯ;bIۤAFw niMJ̟ 8&n/ uW3 ]7uݬqBγ@A+{+tSP`do Dj(ꙅF)Ɏ,dž+_)XNM\9w +D=.1Z'qTZ<@lZ$- 8폜i=k-㿮iRC7 +>Ȝ=$dS؂/Z \ No newline at end of file diff --git a/.git/objects/39/2c35038214afd6a841ff4d187ddc0fde25d7f0 b/.git/objects/39/2c35038214afd6a841ff4d187ddc0fde25d7f0 new file mode 100644 index 0000000..3b30d21 Binary files /dev/null and b/.git/objects/39/2c35038214afd6a841ff4d187ddc0fde25d7f0 differ diff --git a/.git/objects/39/35b21787b278fec545ebd35621a426383c80d9 b/.git/objects/39/35b21787b278fec545ebd35621a426383c80d9 new file mode 100644 index 0000000..f1e7566 Binary files /dev/null and b/.git/objects/39/35b21787b278fec545ebd35621a426383c80d9 differ diff --git a/.git/objects/39/4a81cfb78d64b08180ad1fdcfc6b9cd82c0b56 b/.git/objects/39/4a81cfb78d64b08180ad1fdcfc6b9cd82c0b56 new file mode 100644 index 0000000..7a85e99 Binary files /dev/null and b/.git/objects/39/4a81cfb78d64b08180ad1fdcfc6b9cd82c0b56 differ diff --git a/.git/objects/39/6503c227eb64b9a4b7116382904f865797140b b/.git/objects/39/6503c227eb64b9a4b7116382904f865797140b new file mode 100644 index 0000000..c314ce7 Binary files /dev/null and b/.git/objects/39/6503c227eb64b9a4b7116382904f865797140b differ diff --git a/.git/objects/39/84a1e1f10f5f43bd8be23808c3826d3f398927 b/.git/objects/39/84a1e1f10f5f43bd8be23808c3826d3f398927 new file mode 100644 index 0000000..ea6598c Binary files /dev/null and b/.git/objects/39/84a1e1f10f5f43bd8be23808c3826d3f398927 differ diff --git a/.git/objects/39/97886df3ba50b2573332b16ca02d892ff04b43 b/.git/objects/39/97886df3ba50b2573332b16ca02d892ff04b43 new file mode 100644 index 0000000..f5785b1 Binary files /dev/null and b/.git/objects/39/97886df3ba50b2573332b16ca02d892ff04b43 differ diff --git a/.git/objects/39/a12a9b889f984213b0176dfb8fea95df06241d b/.git/objects/39/a12a9b889f984213b0176dfb8fea95df06241d new file mode 100644 index 0000000..8e791a3 Binary files /dev/null and b/.git/objects/39/a12a9b889f984213b0176dfb8fea95df06241d differ diff --git a/.git/objects/39/b5834560bc710d018f72e380bfaacb676397a9 b/.git/objects/39/b5834560bc710d018f72e380bfaacb676397a9 new file mode 100644 index 0000000..09013da Binary files /dev/null and b/.git/objects/39/b5834560bc710d018f72e380bfaacb676397a9 differ diff --git a/.git/objects/39/bb1ef377143ef83ae60e26af0dad4e9d57177d b/.git/objects/39/bb1ef377143ef83ae60e26af0dad4e9d57177d new file mode 100644 index 0000000..c9c38ee Binary files /dev/null and b/.git/objects/39/bb1ef377143ef83ae60e26af0dad4e9d57177d differ diff --git a/.git/objects/39/e2f1d59d1b6ad9e472516c01474a2e89c184e2 b/.git/objects/39/e2f1d59d1b6ad9e472516c01474a2e89c184e2 new file mode 100644 index 0000000..89918c3 Binary files /dev/null and b/.git/objects/39/e2f1d59d1b6ad9e472516c01474a2e89c184e2 differ diff --git a/.git/objects/39/e9999c267348f83852d87b0db90dfb091c93a4 b/.git/objects/39/e9999c267348f83852d87b0db90dfb091c93a4 new file mode 100644 index 0000000..0904842 Binary files /dev/null and b/.git/objects/39/e9999c267348f83852d87b0db90dfb091c93a4 differ diff --git a/.git/objects/39/f306c70848859dfeb834af5df5d3afc275c515 b/.git/objects/39/f306c70848859dfeb834af5df5d3afc275c515 new file mode 100644 index 0000000..a0b20b3 Binary files /dev/null and b/.git/objects/39/f306c70848859dfeb834af5df5d3afc275c515 differ diff --git a/.git/objects/3a/1f3da9e3c9b59f3869f3102c6a751c763388b2 b/.git/objects/3a/1f3da9e3c9b59f3869f3102c6a751c763388b2 new file mode 100644 index 0000000..fb0d6a3 Binary files /dev/null and b/.git/objects/3a/1f3da9e3c9b59f3869f3102c6a751c763388b2 differ diff --git a/.git/objects/3a/228f94198c57bb388293da5ea07e1b7505147e b/.git/objects/3a/228f94198c57bb388293da5ea07e1b7505147e new file mode 100644 index 0000000..a771fd5 --- /dev/null +++ b/.git/objects/3a/228f94198c57bb388293da5ea07e1b7505147e @@ -0,0 +1 @@ +x5Mj0)޾4< .B dReZ߬^030./Kxk+/cpB1#$Kww[(U)=-TB :ea9Ƒ:)x&Oޣ˳WJp.V8ٖ^DS`ǜib6-bm9| !k$sL# V;qu})1Ʋ\C \ No newline at end of file diff --git a/.git/objects/3a/25c6433385f6035a69ad8537fc3f79e170f47e b/.git/objects/3a/25c6433385f6035a69ad8537fc3f79e170f47e new file mode 100644 index 0000000..ea8af5a --- /dev/null +++ b/.git/objects/3a/25c6433385f6035a69ad8537fc3f79e170f47e @@ -0,0 +1,3 @@ +x-KN1DY)z1g>v †N؎lBnƞaصT0+j&-"㎬arɘSkQ㶻Lq0gf$-kVMZB VuoeVs/'G*p4M=ՅfIgsIc +/|VJ +xb޵-Hb"1ɬ[oWߓq%lhηxOXtÐeS,9\ \ No newline at end of file diff --git a/.git/objects/3a/3863ccd269ad1bd7c5131ec383d0af21a6b743 b/.git/objects/3a/3863ccd269ad1bd7c5131ec383d0af21a6b743 new file mode 100644 index 0000000..4c36264 --- /dev/null +++ b/.git/objects/3a/3863ccd269ad1bd7c5131ec383d0af21a6b743 @@ -0,0 +1 @@ +xj0DW}ҕdBItv]L Qd~la8ƗA& IM*$)*Aidrl5OA8E ъF׊dviR!R`NΗ(s ٺZp丹 >?^S5@Jժ91_N_OepF \ No newline at end of file diff --git a/.git/objects/3a/50457ea9631eacd3860f45edc8cbae2bded5d0 b/.git/objects/3a/50457ea9631eacd3860f45edc8cbae2bded5d0 new file mode 100644 index 0000000..b879d3d Binary files /dev/null and b/.git/objects/3a/50457ea9631eacd3860f45edc8cbae2bded5d0 differ diff --git a/.git/objects/3a/551d606b1113278d6e70c8549b25797d01bc31 b/.git/objects/3a/551d606b1113278d6e70c8549b25797d01bc31 new file mode 100644 index 0000000..c075ade --- /dev/null +++ b/.git/objects/3a/551d606b1113278d6e70c8549b25797d01bc31 @@ -0,0 +1,2 @@ +x5MN0Yoؖ*T6=XqZr3\PhfѸc }Fs`QZrVF98Z,X(U}g=z[AA:n:o3}aT3rbqy} -KxaK.nT֐ + #AH2[ \ No newline at end of file diff --git a/.git/objects/3a/6de0cb1167fb0f833cf720f080f39415b347c4 b/.git/objects/3a/6de0cb1167fb0f833cf720f080f39415b347c4 new file mode 100644 index 0000000..d26510b Binary files /dev/null and b/.git/objects/3a/6de0cb1167fb0f833cf720f080f39415b347c4 differ diff --git a/.git/objects/3a/6e9b6170f38c2917ccb5b063bfdad3477bd555 b/.git/objects/3a/6e9b6170f38c2917ccb5b063bfdad3477bd555 new file mode 100644 index 0000000..b414bf4 Binary files /dev/null and b/.git/objects/3a/6e9b6170f38c2917ccb5b063bfdad3477bd555 differ diff --git a/.git/objects/3a/81c51768e4f2fef846c8aaddf1cc67212dad0d b/.git/objects/3a/81c51768e4f2fef846c8aaddf1cc67212dad0d new file mode 100644 index 0000000..20fb7d6 Binary files /dev/null and b/.git/objects/3a/81c51768e4f2fef846c8aaddf1cc67212dad0d differ diff --git a/.git/objects/3a/a82cbfff25732507d6b4eec860d1902b63c560 b/.git/objects/3a/a82cbfff25732507d6b4eec860d1902b63c560 new file mode 100644 index 0000000..9db9b31 Binary files /dev/null and b/.git/objects/3a/a82cbfff25732507d6b4eec860d1902b63c560 differ diff --git a/.git/objects/3a/b41b6fca5277f0b428f529effdf63ff0a7e688 b/.git/objects/3a/b41b6fca5277f0b428f529effdf63ff0a7e688 new file mode 100644 index 0000000..20a6980 --- /dev/null +++ b/.git/objects/3a/b41b6fca5277f0b428f529effdf63ff0a7e688 @@ -0,0 +1,3 @@ +x5MN1 Y)GTL"Uu I<픙$7cH+XXޓeufPLAIqcHz$''zm&oUwLa +iU^V8+o㠔3d)B_ex}ZR(wT`f\—̏ Zg %Dos+z>>F;\< +/4iDz8A+Α41G¥8` \ No newline at end of file diff --git a/.git/objects/3a/d6e946ce03509621c2f53947a56038a5e66723 b/.git/objects/3a/d6e946ce03509621c2f53947a56038a5e66723 new file mode 100644 index 0000000..db2dfa3 Binary files /dev/null and b/.git/objects/3a/d6e946ce03509621c2f53947a56038a5e66723 differ diff --git a/.git/objects/3a/d7c4589079c7222fc6a0aabb386ae55bd31036 b/.git/objects/3a/d7c4589079c7222fc6a0aabb386ae55bd31036 new file mode 100644 index 0000000..a297ba4 --- /dev/null +++ b/.git/objects/3a/d7c4589079c7222fc6a0aabb386ae55bd31036 @@ -0,0 +1 @@ +x-KN1DY)zQX!q3c4GbϪKJ.&oZ!i8 o'cUoqXPjjƭej xjB FzfN +=qkpX(59z2+Rt0,(xb.>7@&g|TJp)*qo/-R'y[Np+˝5gw>b*|rg󺜶t n505 mTXCq*uZ9 \ No newline at end of file diff --git a/.git/objects/3a/f090c86816f93d3a14187ff65d6d6b2cfcd500 b/.git/objects/3a/f090c86816f93d3a14187ff65d6d6b2cfcd500 new file mode 100644 index 0000000..1f4951d Binary files /dev/null and b/.git/objects/3a/f090c86816f93d3a14187ff65d6d6b2cfcd500 differ diff --git a/.git/objects/3b/33206cdb5fffaad06c863d78dd5555517b9c3f b/.git/objects/3b/33206cdb5fffaad06c863d78dd5555517b9c3f new file mode 100644 index 0000000..cbcf1e2 Binary files /dev/null and b/.git/objects/3b/33206cdb5fffaad06c863d78dd5555517b9c3f differ diff --git a/.git/objects/3b/5ebdbada1a1613eb73a34af8c091e84dab5eca b/.git/objects/3b/5ebdbada1a1613eb73a34af8c091e84dab5eca new file mode 100644 index 0000000..bf27acf Binary files /dev/null and b/.git/objects/3b/5ebdbada1a1613eb73a34af8c091e84dab5eca differ diff --git a/.git/objects/3b/6453d6317eed12a3d2389a237f8a1943f8f14e b/.git/objects/3b/6453d6317eed12a3d2389a237f8a1943f8f14e new file mode 100644 index 0000000..194af07 Binary files /dev/null and b/.git/objects/3b/6453d6317eed12a3d2389a237f8a1943f8f14e differ diff --git a/.git/objects/3b/65ac5345065d7e845066909f0c2ae15a80fbf1 b/.git/objects/3b/65ac5345065d7e845066909f0c2ae15a80fbf1 new file mode 100644 index 0000000..812696e --- /dev/null +++ b/.git/objects/3b/65ac5345065d7e845066909f0c2ae15a80fbf1 @@ -0,0 +1,2 @@ +x%MK0E]WX6 2Fى w/KiJ&U_opv\8p6 +J&1-{7r3roI:ީN9R$dli-K-F+Wh7R1εDkW˜29] ~op")>AzXSۺP9 Rp-Šz.V(3{*a`e\D<p NW \ No newline at end of file diff --git a/.git/objects/3b/9bd2f1a475da0be44d030c3b7d3dc3a076ddf7 b/.git/objects/3b/9bd2f1a475da0be44d030c3b7d3dc3a076ddf7 new file mode 100644 index 0000000..dc3d9ff Binary files /dev/null and b/.git/objects/3b/9bd2f1a475da0be44d030c3b7d3dc3a076ddf7 differ diff --git a/.git/objects/3b/dcf308c3d2f26573377426cc4697f7f7b17658 b/.git/objects/3b/dcf308c3d2f26573377426cc4697f7f7b17658 new file mode 100644 index 0000000..0b74f02 Binary files /dev/null and b/.git/objects/3b/dcf308c3d2f26573377426cc4697f7f7b17658 differ diff --git a/.git/objects/3b/e1b94afab0cf40188add1d4a2251e969f32f08 b/.git/objects/3b/e1b94afab0cf40188add1d4a2251e969f32f08 new file mode 100644 index 0000000..19068e5 Binary files /dev/null and b/.git/objects/3b/e1b94afab0cf40188add1d4a2251e969f32f08 differ diff --git a/.git/objects/3c/186f7aebb0a37cce328dd50931ed7a05cb6a5b b/.git/objects/3c/186f7aebb0a37cce328dd50931ed7a05cb6a5b new file mode 100644 index 0000000..4acb647 Binary files /dev/null and b/.git/objects/3c/186f7aebb0a37cce328dd50931ed7a05cb6a5b differ diff --git a/.git/objects/3c/3e977f6100f74013657489e2bcc2b20ff20592 b/.git/objects/3c/3e977f6100f74013657489e2bcc2b20ff20592 new file mode 100644 index 0000000..78ce42a Binary files /dev/null and b/.git/objects/3c/3e977f6100f74013657489e2bcc2b20ff20592 differ diff --git a/.git/objects/3c/6e3582efaa766db844143ef607ca8ce4263c02 b/.git/objects/3c/6e3582efaa766db844143ef607ca8ce4263c02 new file mode 100644 index 0000000..14904e5 Binary files /dev/null and b/.git/objects/3c/6e3582efaa766db844143ef607ca8ce4263c02 differ diff --git a/.git/objects/3c/8b2acae02398b0232f45b8128fc05f8828c93d b/.git/objects/3c/8b2acae02398b0232f45b8128fc05f8828c93d new file mode 100644 index 0000000..fdfac8e Binary files /dev/null and b/.git/objects/3c/8b2acae02398b0232f45b8128fc05f8828c93d differ diff --git a/.git/objects/3c/8cd00c88413f8c997948b568c44e61797275da b/.git/objects/3c/8cd00c88413f8c997948b568c44e61797275da new file mode 100644 index 0000000..06bd14e Binary files /dev/null and b/.git/objects/3c/8cd00c88413f8c997948b568c44e61797275da differ diff --git a/.git/objects/3c/984550955b80c9ca90f7a5430f12e1f99e0579 b/.git/objects/3c/984550955b80c9ca90f7a5430f12e1f99e0579 new file mode 100644 index 0000000..b96d715 Binary files /dev/null and b/.git/objects/3c/984550955b80c9ca90f7a5430f12e1f99e0579 differ diff --git a/.git/objects/3c/cfd7dbbb556307966b65e1d6495cbd8c6e699b b/.git/objects/3c/cfd7dbbb556307966b65e1d6495cbd8c6e699b new file mode 100644 index 0000000..2288300 Binary files /dev/null and b/.git/objects/3c/cfd7dbbb556307966b65e1d6495cbd8c6e699b differ diff --git a/.git/objects/3c/f11577575204e10c85251551245c30711af915 b/.git/objects/3c/f11577575204e10c85251551245c30711af915 new file mode 100644 index 0000000..f6ea0c8 Binary files /dev/null and b/.git/objects/3c/f11577575204e10c85251551245c30711af915 differ diff --git a/.git/objects/3c/f7a256f1b67f249da968f02272c956863ae054 b/.git/objects/3c/f7a256f1b67f249da968f02272c956863ae054 new file mode 100644 index 0000000..68216aa Binary files /dev/null and b/.git/objects/3c/f7a256f1b67f249da968f02272c956863ae054 differ diff --git a/.git/objects/3d/0a36e5dcd622936bbf99f9747f0df6f58dd3cc b/.git/objects/3d/0a36e5dcd622936bbf99f9747f0df6f58dd3cc new file mode 100644 index 0000000..2c7ed11 Binary files /dev/null and b/.git/objects/3d/0a36e5dcd622936bbf99f9747f0df6f58dd3cc differ diff --git a/.git/objects/3d/590fe76cc76a8bf3cb0b375ce129bbfae32711 b/.git/objects/3d/590fe76cc76a8bf3cb0b375ce129bbfae32711 new file mode 100644 index 0000000..4e66885 Binary files /dev/null and b/.git/objects/3d/590fe76cc76a8bf3cb0b375ce129bbfae32711 differ diff --git a/.git/objects/3d/75b29129f25b62cf975a112697329456702d37 b/.git/objects/3d/75b29129f25b62cf975a112697329456702d37 new file mode 100644 index 0000000..0c7b1ce Binary files /dev/null and b/.git/objects/3d/75b29129f25b62cf975a112697329456702d37 differ diff --git a/.git/objects/3d/a51ba02c4b2423da1e0339580285ad9f3f5c0d b/.git/objects/3d/a51ba02c4b2423da1e0339580285ad9f3f5c0d new file mode 100644 index 0000000..1a0af5c --- /dev/null +++ b/.git/objects/3d/a51ba02c4b2423da1e0339580285ad9f3f5c0d @@ -0,0 +1,2 @@ +x-Mn )VQ5.+uT54s{ҟ=ٴm]DDh'|"3xF3QN^2z nLVKt(zK)4*tL\ ~%exZr(5 <d<E63Xgk%شPׯ \Z%yS2'v +As\!E\TT"*}K\H \ No newline at end of file diff --git a/.git/objects/3d/d833e1f8be9ca8b77a0c6046da080662156998 b/.git/objects/3d/d833e1f8be9ca8b77a0c6046da080662156998 new file mode 100644 index 0000000..9921511 Binary files /dev/null and b/.git/objects/3d/d833e1f8be9ca8b77a0c6046da080662156998 differ diff --git a/.git/objects/3d/d8c77810f823e7342e37d57339a551128c0dc6 b/.git/objects/3d/d8c77810f823e7342e37d57339a551128c0dc6 new file mode 100644 index 0000000..857bfb2 Binary files /dev/null and b/.git/objects/3d/d8c77810f823e7342e37d57339a551128c0dc6 differ diff --git a/.git/objects/3d/dc51409901bf70c98000accf9ec406db18c5b7 b/.git/objects/3d/dc51409901bf70c98000accf9ec406db18c5b7 new file mode 100644 index 0000000..5e73b50 Binary files /dev/null and b/.git/objects/3d/dc51409901bf70c98000accf9ec406db18c5b7 differ diff --git a/.git/objects/3d/f5e2280061e3d61355757eef3980c56269f15e b/.git/objects/3d/f5e2280061e3d61355757eef3980c56269f15e new file mode 100644 index 0000000..0061808 --- /dev/null +++ b/.git/objects/3d/f5e2280061e3d61355757eef3980c56269f15e @@ -0,0 +1,2 @@ +x1n Ԝb" 6 QeirՀ1bizG+3eͪ:g6DLƐa/T9wYvyAix%jfFeS[Ks;+|P=ghK~(7ĎlG?Ljn7qY|CI`d]سԪ-YsMJClCV$ԽZroA+L1'x6δgg^1'gFX#V=Sn1bҼ-՟mPB9*mS,g d-| !&q%:?>~5ŕSĶ{De \ No newline at end of file diff --git a/.git/objects/3e/5847780096c9c27569ad3ee2e3e89afd0a0463 b/.git/objects/3e/5847780096c9c27569ad3ee2e3e89afd0a0463 new file mode 100644 index 0000000..c831363 Binary files /dev/null and b/.git/objects/3e/5847780096c9c27569ad3ee2e3e89afd0a0463 differ diff --git a/.git/objects/3e/7ce62dde98e24d54e7a531c60c2fc90af7b1cf b/.git/objects/3e/7ce62dde98e24d54e7a531c60c2fc90af7b1cf new file mode 100644 index 0000000..1dc7f36 Binary files /dev/null and b/.git/objects/3e/7ce62dde98e24d54e7a531c60c2fc90af7b1cf differ diff --git a/.git/objects/3e/a3d4016accb7156c4c2babafece4aac42dff46 b/.git/objects/3e/a3d4016accb7156c4c2babafece4aac42dff46 new file mode 100644 index 0000000..8e95f7c Binary files /dev/null and b/.git/objects/3e/a3d4016accb7156c4c2babafece4aac42dff46 differ diff --git a/.git/objects/3e/d4204add3730768ca9035ea011bf4dec3e6d6b b/.git/objects/3e/d4204add3730768ca9035ea011bf4dec3e6d6b new file mode 100644 index 0000000..104cc85 Binary files /dev/null and b/.git/objects/3e/d4204add3730768ca9035ea011bf4dec3e6d6b differ diff --git a/.git/objects/3e/dd18c101707f8e705d27d05e3bf1a53b4f1f2b b/.git/objects/3e/dd18c101707f8e705d27d05e3bf1a53b4f1f2b new file mode 100644 index 0000000..a90a76d --- /dev/null +++ b/.git/objects/3e/dd18c101707f8e705d27d05e3bf1a53b4f1f2b @@ -0,0 +1,2 @@ +x-OKN0dS="_&U58sb)+z3\b7hƤ|$qW33B7Lqd'ÄΒS -3 +&e%KB +mHi)aDIK[]R畿u͛K?9rS]x-9KkRx)C{B4涻=/K^Su 7pگonAjx3m#g̵8ÚJ+v)8d7i`_ \ No newline at end of file diff --git a/.git/objects/3e/e8a892b1600c61db1316fb736f9f7fdfe740f1 b/.git/objects/3e/e8a892b1600c61db1316fb736f9f7fdfe740f1 new file mode 100644 index 0000000..3f5db6d Binary files /dev/null and b/.git/objects/3e/e8a892b1600c61db1316fb736f9f7fdfe740f1 differ diff --git a/.git/objects/3f/17cf52d3df2d6947a495e53934cd4f9ff65631 b/.git/objects/3f/17cf52d3df2d6947a495e53934cd4f9ff65631 new file mode 100644 index 0000000..8fbda9a Binary files /dev/null and b/.git/objects/3f/17cf52d3df2d6947a495e53934cd4f9ff65631 differ diff --git a/.git/objects/3f/662f13a941fcf4b3ef7f3523cf36b5baf6e8c9 b/.git/objects/3f/662f13a941fcf4b3ef7f3523cf36b5baf6e8c9 new file mode 100644 index 0000000..ca9c34e Binary files /dev/null and b/.git/objects/3f/662f13a941fcf4b3ef7f3523cf36b5baf6e8c9 differ diff --git a/.git/objects/3f/793b886a7dfc65a3f5c60df48db9323304ef66 b/.git/objects/3f/793b886a7dfc65a3f5c60df48db9323304ef66 new file mode 100644 index 0000000..b5ca675 Binary files /dev/null and b/.git/objects/3f/793b886a7dfc65a3f5c60df48db9323304ef66 differ diff --git a/.git/objects/3f/7eef95f220869aa3ec5213f6bdc36d1c59eb2c b/.git/objects/3f/7eef95f220869aa3ec5213f6bdc36d1c59eb2c new file mode 100644 index 0000000..8e7eec7 Binary files /dev/null and b/.git/objects/3f/7eef95f220869aa3ec5213f6bdc36d1c59eb2c differ diff --git a/.git/objects/3f/86b8eeee96069ff6c5d43254e6c4282f239180 b/.git/objects/3f/86b8eeee96069ff6c5d43254e6c4282f239180 new file mode 100644 index 0000000..0611af4 Binary files /dev/null and b/.git/objects/3f/86b8eeee96069ff6c5d43254e6c4282f239180 differ diff --git a/.git/objects/3f/950ea90274592f7b4c75ae26732178a5967fa8 b/.git/objects/3f/950ea90274592f7b4c75ae26732178a5967fa8 new file mode 100644 index 0000000..2c59fda Binary files /dev/null and b/.git/objects/3f/950ea90274592f7b4c75ae26732178a5967fa8 differ diff --git a/.git/objects/3f/9588cb9e9ce0a5b0edd2a4c63540038bd37bc9 b/.git/objects/3f/9588cb9e9ce0a5b0edd2a4c63540038bd37bc9 new file mode 100644 index 0000000..711b24d Binary files /dev/null and b/.git/objects/3f/9588cb9e9ce0a5b0edd2a4c63540038bd37bc9 differ diff --git a/.git/objects/3f/a60ee05857596980891144bdb1f331d7d96e12 b/.git/objects/3f/a60ee05857596980891144bdb1f331d7d96e12 new file mode 100644 index 0000000..045caf5 Binary files /dev/null and b/.git/objects/3f/a60ee05857596980891144bdb1f331d7d96e12 differ diff --git a/.git/objects/3f/a80ebdd6946f68f31dcad33f90f48b3f649fec b/.git/objects/3f/a80ebdd6946f68f31dcad33f90f48b3f649fec new file mode 100644 index 0000000..bf9bccd Binary files /dev/null and b/.git/objects/3f/a80ebdd6946f68f31dcad33f90f48b3f649fec differ diff --git a/.git/objects/3f/cb9ba00805a1f2128d9df93b9fb89ce2a5456a b/.git/objects/3f/cb9ba00805a1f2128d9df93b9fb89ce2a5456a new file mode 100644 index 0000000..faecf48 Binary files /dev/null and b/.git/objects/3f/cb9ba00805a1f2128d9df93b9fb89ce2a5456a differ diff --git a/.git/objects/3f/f6a57ea72861eea1178d8248e0db88e602e611 b/.git/objects/3f/f6a57ea72861eea1178d8248e0db88e602e611 new file mode 100644 index 0000000..2004811 Binary files /dev/null and b/.git/objects/3f/f6a57ea72861eea1178d8248e0db88e602e611 differ diff --git a/.git/objects/40/09d1c91e66ced793660154595e78a604f37965 b/.git/objects/40/09d1c91e66ced793660154595e78a604f37965 new file mode 100644 index 0000000..82b7bd7 Binary files /dev/null and b/.git/objects/40/09d1c91e66ced793660154595e78a604f37965 differ diff --git a/.git/objects/40/17bc6bc47f60863301ee3540760c9fc777da3f b/.git/objects/40/17bc6bc47f60863301ee3540760c9fc777da3f new file mode 100644 index 0000000..77cb5b5 Binary files /dev/null and b/.git/objects/40/17bc6bc47f60863301ee3540760c9fc777da3f differ diff --git a/.git/objects/40/38600e7f56fc3b3a74e6802ead9103bfeffd16 b/.git/objects/40/38600e7f56fc3b3a74e6802ead9103bfeffd16 new file mode 100644 index 0000000..76bc45a Binary files /dev/null and b/.git/objects/40/38600e7f56fc3b3a74e6802ead9103bfeffd16 differ diff --git a/.git/objects/40/4100f6dbcabc0e1a4efd1499c880ad86780aa0 b/.git/objects/40/4100f6dbcabc0e1a4efd1499c880ad86780aa0 new file mode 100644 index 0000000..98641c6 Binary files /dev/null and b/.git/objects/40/4100f6dbcabc0e1a4efd1499c880ad86780aa0 differ diff --git a/.git/objects/40/4e3a1d794a28b50f3b8314aa4b063653e2fba1 b/.git/objects/40/4e3a1d794a28b50f3b8314aa4b063653e2fba1 new file mode 100644 index 0000000..fe56f67 Binary files /dev/null and b/.git/objects/40/4e3a1d794a28b50f3b8314aa4b063653e2fba1 differ diff --git a/.git/objects/40/7c0796c8c850d339c3085d40a8440dd1a4b762 b/.git/objects/40/7c0796c8c850d339c3085d40a8440dd1a4b762 new file mode 100644 index 0000000..4e8446a Binary files /dev/null and b/.git/objects/40/7c0796c8c850d339c3085d40a8440dd1a4b762 differ diff --git a/.git/objects/40/8bcbe69c7335111b5a1e80568c619d52e5f0a6 b/.git/objects/40/8bcbe69c7335111b5a1e80568c619d52e5f0a6 new file mode 100644 index 0000000..4617c15 Binary files /dev/null and b/.git/objects/40/8bcbe69c7335111b5a1e80568c619d52e5f0a6 differ diff --git a/.git/objects/40/9467fdc3d7cfe7cf9e165a49dcf2b0a6a384fe b/.git/objects/40/9467fdc3d7cfe7cf9e165a49dcf2b0a6a384fe new file mode 100644 index 0000000..b618626 Binary files /dev/null and b/.git/objects/40/9467fdc3d7cfe7cf9e165a49dcf2b0a6a384fe differ diff --git a/.git/objects/41/01de3bb1e7863014ba1bbec5d43d48edddbe83 b/.git/objects/41/01de3bb1e7863014ba1bbec5d43d48edddbe83 new file mode 100644 index 0000000..42d6fca Binary files /dev/null and b/.git/objects/41/01de3bb1e7863014ba1bbec5d43d48edddbe83 differ diff --git a/.git/objects/41/12c0b4dce2d699700f5802f12a99f5325419db b/.git/objects/41/12c0b4dce2d699700f5802f12a99f5325419db new file mode 100644 index 0000000..95521e1 Binary files /dev/null and b/.git/objects/41/12c0b4dce2d699700f5802f12a99f5325419db differ diff --git a/.git/objects/41/186944a48cd23bc9ff56249c9954134f7bba17 b/.git/objects/41/186944a48cd23bc9ff56249c9954134f7bba17 new file mode 100644 index 0000000..5c14519 Binary files /dev/null and b/.git/objects/41/186944a48cd23bc9ff56249c9954134f7bba17 differ diff --git a/.git/objects/41/b3afb722bfd4e5c40547bb94be206d78eed253 b/.git/objects/41/b3afb722bfd4e5c40547bb94be206d78eed253 new file mode 100644 index 0000000..0f3d2e3 Binary files /dev/null and b/.git/objects/41/b3afb722bfd4e5c40547bb94be206d78eed253 differ diff --git a/.git/objects/41/b61ab4c8451589c33631880e70ba681b2262b7 b/.git/objects/41/b61ab4c8451589c33631880e70ba681b2262b7 new file mode 100644 index 0000000..2a379c1 Binary files /dev/null and b/.git/objects/41/b61ab4c8451589c33631880e70ba681b2262b7 differ diff --git a/.git/objects/41/c0aef600e04f84f359ab75be8436682f659a01 b/.git/objects/41/c0aef600e04f84f359ab75be8436682f659a01 new file mode 100644 index 0000000..8f533b5 Binary files /dev/null and b/.git/objects/41/c0aef600e04f84f359ab75be8436682f659a01 differ diff --git a/.git/objects/41/c2bd2412e517a796c7f5db31c1462896dd4e75 b/.git/objects/41/c2bd2412e517a796c7f5db31c1462896dd4e75 new file mode 100644 index 0000000..862b1fb Binary files /dev/null and b/.git/objects/41/c2bd2412e517a796c7f5db31c1462896dd4e75 differ diff --git a/.git/objects/42/0e58800c59ba5c9feeaa194c8757fcc0370619 b/.git/objects/42/0e58800c59ba5c9feeaa194c8757fcc0370619 new file mode 100644 index 0000000..7c3aff1 Binary files /dev/null and b/.git/objects/42/0e58800c59ba5c9feeaa194c8757fcc0370619 differ diff --git a/.git/objects/42/239a63789ec72285523ae24e6174c23edbaadf b/.git/objects/42/239a63789ec72285523ae24e6174c23edbaadf new file mode 100644 index 0000000..cd06c97 Binary files /dev/null and b/.git/objects/42/239a63789ec72285523ae24e6174c23edbaadf differ diff --git a/.git/objects/42/33ac34c94efb4dc2296ee2777b8ec282351257 b/.git/objects/42/33ac34c94efb4dc2296ee2777b8ec282351257 new file mode 100644 index 0000000..e1d4727 Binary files /dev/null and b/.git/objects/42/33ac34c94efb4dc2296ee2777b8ec282351257 differ diff --git a/.git/objects/42/352799cbec042baddda3f5545fde59fa4390dd b/.git/objects/42/352799cbec042baddda3f5545fde59fa4390dd new file mode 100644 index 0000000..627f85e Binary files /dev/null and b/.git/objects/42/352799cbec042baddda3f5545fde59fa4390dd differ diff --git a/.git/objects/42/643e8a8536109ceccc9a7f5e4ee74216aba7d5 b/.git/objects/42/643e8a8536109ceccc9a7f5e4ee74216aba7d5 new file mode 100644 index 0000000..86bdfcb Binary files /dev/null and b/.git/objects/42/643e8a8536109ceccc9a7f5e4ee74216aba7d5 differ diff --git a/.git/objects/42/6a8db5e0a31dd2de2c4366627a366a4b2fb003 b/.git/objects/42/6a8db5e0a31dd2de2c4366627a366a4b2fb003 new file mode 100644 index 0000000..17f7a06 Binary files /dev/null and b/.git/objects/42/6a8db5e0a31dd2de2c4366627a366a4b2fb003 differ diff --git a/.git/objects/42/6af8298a0abeb398c3cbeb36255ec81ae5f2b9 b/.git/objects/42/6af8298a0abeb398c3cbeb36255ec81ae5f2b9 new file mode 100644 index 0000000..7cfa219 --- /dev/null +++ b/.git/objects/42/6af8298a0abeb398c3cbeb36255ec81ae5f2b9 @@ -0,0 +1 @@ +x-j0D{W칥F+e B KOX [$7zwx̸,LhбV HAHdrNp kXJP Z'$hF3Xe*'E[s]oppL.7~8^s{-xK˙W8Q^b«]'WNpkPZi;bJxJ'u4T \ No newline at end of file diff --git a/.git/objects/42/73e3e0386a661eaeb532f07f6538d41eb28dc7 b/.git/objects/42/73e3e0386a661eaeb532f07f6538d41eb28dc7 new file mode 100644 index 0000000..c6801fe Binary files /dev/null and b/.git/objects/42/73e3e0386a661eaeb532f07f6538d41eb28dc7 differ diff --git a/.git/objects/42/97db978608c7adaee1273a70260a5ae93934aa b/.git/objects/42/97db978608c7adaee1273a70260a5ae93934aa new file mode 100644 index 0000000..68da065 --- /dev/null +++ b/.git/objects/42/97db978608c7adaee1273a70260a5ae93934aa @@ -0,0 +1,3 @@ +x-Kn0 D)/PR n7=eYFuߋU ș!zd >$k%rڎ[qu\u$!X؉kzG-)cZ#L=1u/ +, ޗ!t$w +g%4p? џAՈ[cbU%w.w^lDN ?|ޖ릱^+/pe.!3d` $GC\s \ No newline at end of file diff --git a/.git/objects/42/9e3b775f643eb54ee15eef591365c7eda6bb40 b/.git/objects/42/9e3b775f643eb54ee15eef591365c7eda6bb40 new file mode 100644 index 0000000..d974b40 Binary files /dev/null and b/.git/objects/42/9e3b775f643eb54ee15eef591365c7eda6bb40 differ diff --git a/.git/objects/42/bb1eb9ea8d798c95dfcd46407c8b390837ec64 b/.git/objects/42/bb1eb9ea8d798c95dfcd46407c8b390837ec64 new file mode 100644 index 0000000..9dd9e9b --- /dev/null +++ b/.git/objects/42/bb1eb9ea8d798c95dfcd46407c8b390837ec64 @@ -0,0 +1 @@ +xOKN0eS@qUvˢBc{6Bz2\ +7蓼s6C;9 9 \ }RI^7$f9ע>0@$ȔQh472(Ǧ6(fRSᒧ" .:p|qRAJI1=nX[BG60VJۄr&0A"jSZ [G +`ڑBqgS.(\kSZ(jnKz\gBKӋUa-ꈅ=}q u \ No newline at end of file diff --git a/.git/objects/43/18c46cc68c9aeb00cffbaa564a7b4f9ac32e5f b/.git/objects/43/18c46cc68c9aeb00cffbaa564a7b4f9ac32e5f new file mode 100644 index 0000000..619ca98 Binary files /dev/null and b/.git/objects/43/18c46cc68c9aeb00cffbaa564a7b4f9ac32e5f differ diff --git a/.git/objects/43/1b54e9b2c6f4e88eaaf576e774fc90a1f74ccd b/.git/objects/43/1b54e9b2c6f4e88eaaf576e774fc90a1f74ccd new file mode 100644 index 0000000..fd8f307 Binary files /dev/null and b/.git/objects/43/1b54e9b2c6f4e88eaaf576e774fc90a1f74ccd differ diff --git a/.git/objects/43/8fbc9ac1b0042bcd0964fe302b72e0af82bbb1 b/.git/objects/43/8fbc9ac1b0042bcd0964fe302b72e0af82bbb1 new file mode 100644 index 0000000..eedb713 Binary files /dev/null and b/.git/objects/43/8fbc9ac1b0042bcd0964fe302b72e0af82bbb1 differ diff --git a/.git/objects/43/a3e896c5f74ae036b5219e65af6e2ef94f6a13 b/.git/objects/43/a3e896c5f74ae036b5219e65af6e2ef94f6a13 new file mode 100644 index 0000000..205442e Binary files /dev/null and b/.git/objects/43/a3e896c5f74ae036b5219e65af6e2ef94f6a13 differ diff --git a/.git/objects/43/af0708c9347e8e40911ff1696d128b5b7f784a b/.git/objects/43/af0708c9347e8e40911ff1696d128b5b7f784a new file mode 100644 index 0000000..e758988 --- /dev/null +++ b/.git/objects/43/af0708c9347e8e40911ff1696d128b5b7f784a @@ -0,0 +1,2 @@ +x1n DSb1VF&'d8,}.H3ofl +~*ޡ蘲Y>1g'ƅ^$NHl) 3eOB :aɮ,)J?e6x7GսI)M8׽R<3XcKy_##\mxGho|`6Tm[SSkÞrqs7 5 ]; \ No newline at end of file diff --git a/.git/objects/43/b73d2faef84af2d4e3d736bf217670e971ee52 b/.git/objects/43/b73d2faef84af2d4e3d736bf217670e971ee52 new file mode 100644 index 0000000..de1cbde --- /dev/null +++ b/.git/objects/43/b73d2faef84af2d4e3d736bf217670e971ee52 @@ -0,0 +1 @@ +x%AN0 EYޱ@MR4B`;l8mFmR)܌=Âe{.-K(Pwd"iwn0ζ%ZtJENT+f&e4N־Z-=z=P^e/2fm;G=&oglUD-DS.uas#F89/*Zxd)QU+g8R~ 9R&R` v0R&`c)R Gc \ No newline at end of file diff --git a/.git/objects/43/c512b6e00b8500a3ef058cd7838d029386e496 b/.git/objects/43/c512b6e00b8500a3ef058cd7838d029386e496 new file mode 100644 index 0000000..37446ec Binary files /dev/null and b/.git/objects/43/c512b6e00b8500a3ef058cd7838d029386e496 differ diff --git a/.git/objects/43/d3ced757fd7af891447220397ee7ca2c7f1029 b/.git/objects/43/d3ced757fd7af891447220397ee7ca2c7f1029 new file mode 100644 index 0000000..4d6cfaa Binary files /dev/null and b/.git/objects/43/d3ced757fd7af891447220397ee7ca2c7f1029 differ diff --git a/.git/objects/43/e3e6bebccb1ac391f464646ee6799324e08032 b/.git/objects/43/e3e6bebccb1ac391f464646ee6799324e08032 new file mode 100644 index 0000000..dc06f5e --- /dev/null +++ b/.git/objects/43/e3e6bebccb1ac391f464646ee6799324e08032 @@ -0,0 +1 @@ +x5MN0YoTl887cH+،Fͧфe¸syPZ ,cQh@lN)0*DcVEo7.HQtF5Xq82aRןh=^d-\sX) ƚp^61+<`}fԹ<-nꍯ(&6XMC`W\ \ No newline at end of file diff --git a/.git/objects/44/25bf054a97c487de392a7584f5fa7ce920bc7e b/.git/objects/44/25bf054a97c487de392a7584f5fa7ce920bc7e new file mode 100644 index 0000000..571899b Binary files /dev/null and b/.git/objects/44/25bf054a97c487de392a7584f5fa7ce920bc7e differ diff --git a/.git/objects/44/34202e4e5fd611371ed91515df65efdbfafa45 b/.git/objects/44/34202e4e5fd611371ed91515df65efdbfafa45 new file mode 100644 index 0000000..f4c847e Binary files /dev/null and b/.git/objects/44/34202e4e5fd611371ed91515df65efdbfafa45 differ diff --git a/.git/objects/44/3fc8f8dd8ff7b0feeb132ddc3f3ab3110b057c b/.git/objects/44/3fc8f8dd8ff7b0feeb132ddc3f3ab3110b057c new file mode 100644 index 0000000..30b8a6d Binary files /dev/null and b/.git/objects/44/3fc8f8dd8ff7b0feeb132ddc3f3ab3110b057c differ diff --git a/.git/objects/44/515862ed5d9826c0ff21a752974d22e96443c5 b/.git/objects/44/515862ed5d9826c0ff21a752974d22e96443c5 new file mode 100644 index 0000000..d0c47de Binary files /dev/null and b/.git/objects/44/515862ed5d9826c0ff21a752974d22e96443c5 differ diff --git a/.git/objects/44/7825b8e601569c8a35ed4d2464807671402998 b/.git/objects/44/7825b8e601569c8a35ed4d2464807671402998 new file mode 100644 index 0000000..99bb82b Binary files /dev/null and b/.git/objects/44/7825b8e601569c8a35ed4d2464807671402998 differ diff --git a/.git/objects/44/8b0018a9aaa6fd866fd60a3a82b1b9d51898f1 b/.git/objects/44/8b0018a9aaa6fd866fd60a3a82b1b9d51898f1 new file mode 100644 index 0000000..5243bf6 Binary files /dev/null and b/.git/objects/44/8b0018a9aaa6fd866fd60a3a82b1b9d51898f1 differ diff --git a/.git/objects/44/9d1721df301ed4f674f48a040798bde55375a8 b/.git/objects/44/9d1721df301ed4f674f48a040798bde55375a8 new file mode 100644 index 0000000..9ee77b0 Binary files /dev/null and b/.git/objects/44/9d1721df301ed4f674f48a040798bde55375a8 differ diff --git a/.git/objects/44/bc97bab99fae5d5db7eecf818bba7be7627051 b/.git/objects/44/bc97bab99fae5d5db7eecf818bba7be7627051 new file mode 100644 index 0000000..b31db03 Binary files /dev/null and b/.git/objects/44/bc97bab99fae5d5db7eecf818bba7be7627051 differ diff --git a/.git/objects/44/d0402a21eb3f2752e286dde089e533037f7ba5 b/.git/objects/44/d0402a21eb3f2752e286dde089e533037f7ba5 new file mode 100644 index 0000000..dff312f Binary files /dev/null and b/.git/objects/44/d0402a21eb3f2752e286dde089e533037f7ba5 differ diff --git a/.git/objects/44/d414d8960019d47fd82aa1e08445e99d2c1af5 b/.git/objects/44/d414d8960019d47fd82aa1e08445e99d2c1af5 new file mode 100644 index 0000000..ff6106c Binary files /dev/null and b/.git/objects/44/d414d8960019d47fd82aa1e08445e99d2c1af5 differ diff --git a/.git/objects/44/d49015bd38efb814411bad41176622a56f71cb b/.git/objects/44/d49015bd38efb814411bad41176622a56f71cb new file mode 100644 index 0000000..c28ca32 Binary files /dev/null and b/.git/objects/44/d49015bd38efb814411bad41176622a56f71cb differ diff --git a/.git/objects/45/0cc1ad98e317dac674fe23a3a161cd05aa8bcd b/.git/objects/45/0cc1ad98e317dac674fe23a3a161cd05aa8bcd new file mode 100644 index 0000000..cd900ab Binary files /dev/null and b/.git/objects/45/0cc1ad98e317dac674fe23a3a161cd05aa8bcd differ diff --git a/.git/objects/45/1e7e751ff16d7000ee5c278c17f8c118ce67c8 b/.git/objects/45/1e7e751ff16d7000ee5c278c17f8c118ce67c8 new file mode 100644 index 0000000..8065980 Binary files /dev/null and b/.git/objects/45/1e7e751ff16d7000ee5c278c17f8c118ce67c8 differ diff --git a/.git/objects/45/37f93955afe75bc236df0ea72cb7e54743c47b b/.git/objects/45/37f93955afe75bc236df0ea72cb7e54743c47b new file mode 100644 index 0000000..954b670 Binary files /dev/null and b/.git/objects/45/37f93955afe75bc236df0ea72cb7e54743c47b differ diff --git a/.git/objects/45/458d71fb60292f262dd19ba76c6d207801e930 b/.git/objects/45/458d71fb60292f262dd19ba76c6d207801e930 new file mode 100644 index 0000000..1da07cb Binary files /dev/null and b/.git/objects/45/458d71fb60292f262dd19ba76c6d207801e930 differ diff --git a/.git/objects/45/a38873b9e9de4793950c047ad8b1bf2f1b9a88 b/.git/objects/45/a38873b9e9de4793950c047ad8b1bf2f1b9a88 new file mode 100644 index 0000000..d954915 Binary files /dev/null and b/.git/objects/45/a38873b9e9de4793950c047ad8b1bf2f1b9a88 differ diff --git a/.git/objects/45/b70266f4cfa8b0868c58c3719e88a74db9c4ab b/.git/objects/45/b70266f4cfa8b0868c58c3719e88a74db9c4ab new file mode 100644 index 0000000..8eb514d Binary files /dev/null and b/.git/objects/45/b70266f4cfa8b0868c58c3719e88a74db9c4ab differ diff --git a/.git/objects/45/b80101513c14ea3943b1a3ae6941edd2a6d383 b/.git/objects/45/b80101513c14ea3943b1a3ae6941edd2a6d383 new file mode 100644 index 0000000..b81fadc Binary files /dev/null and b/.git/objects/45/b80101513c14ea3943b1a3ae6941edd2a6d383 differ diff --git a/.git/objects/45/ca726fb4f3d186049752fcd1d960ddc6738ed9 b/.git/objects/45/ca726fb4f3d186049752fcd1d960ddc6738ed9 new file mode 100644 index 0000000..34cc20c Binary files /dev/null and b/.git/objects/45/ca726fb4f3d186049752fcd1d960ddc6738ed9 differ diff --git a/.git/objects/45/df7f24051cb751f24b8c4fa8e7dc2ec2032073 b/.git/objects/45/df7f24051cb751f24b8c4fa8e7dc2ec2032073 new file mode 100644 index 0000000..3f72423 Binary files /dev/null and b/.git/objects/45/df7f24051cb751f24b8c4fa8e7dc2ec2032073 differ diff --git a/.git/objects/46/0af69ae58222a3201a75b53c58a905ba691715 b/.git/objects/46/0af69ae58222a3201a75b53c58a905ba691715 new file mode 100644 index 0000000..912ae3c --- /dev/null +++ b/.git/objects/46/0af69ae58222a3201a75b53c58a905ba691715 @@ -0,0 +1,5 @@ +xKJ1Ego U/z"҂c'. +T%J3n us7fH1~1 GJ Zy +hf2Zf v󌆬DR ]Z8E_Rrǟsg+ +u'~GZc| \ No newline at end of file diff --git a/.git/objects/46/3140e0659a791754efc68f905e61a26e3bafe1 b/.git/objects/46/3140e0659a791754efc68f905e61a26e3bafe1 new file mode 100644 index 0000000..205b36d Binary files /dev/null and b/.git/objects/46/3140e0659a791754efc68f905e61a26e3bafe1 differ diff --git a/.git/objects/46/353221d19c64ffea85a7b035fc5883b8c5723e b/.git/objects/46/353221d19c64ffea85a7b035fc5883b8c5723e new file mode 100644 index 0000000..d0acd81 Binary files /dev/null and b/.git/objects/46/353221d19c64ffea85a7b035fc5883b8c5723e differ diff --git a/.git/objects/46/436219c6ce60d815fbee3359f023e756df90a6 b/.git/objects/46/436219c6ce60d815fbee3359f023e756df90a6 new file mode 100644 index 0000000..a40292f Binary files /dev/null and b/.git/objects/46/436219c6ce60d815fbee3359f023e756df90a6 differ diff --git a/.git/objects/46/6a1773a851339f0b39e1ba12892f3a9cacffc2 b/.git/objects/46/6a1773a851339f0b39e1ba12892f3a9cacffc2 new file mode 100644 index 0000000..61ba54e Binary files /dev/null and b/.git/objects/46/6a1773a851339f0b39e1ba12892f3a9cacffc2 differ diff --git a/.git/objects/46/76826f47998708c402ec717cc4c67e513a2555 b/.git/objects/46/76826f47998708c402ec717cc4c67e513a2555 new file mode 100644 index 0000000..ab831f7 Binary files /dev/null and b/.git/objects/46/76826f47998708c402ec717cc4c67e513a2555 differ diff --git a/.git/objects/46/8224f701e43feff0737775a04293def5217a55 b/.git/objects/46/8224f701e43feff0737775a04293def5217a55 new file mode 100644 index 0000000..7d6cda9 Binary files /dev/null and b/.git/objects/46/8224f701e43feff0737775a04293def5217a55 differ diff --git a/.git/objects/46/894d8834b351bef44116c993e44ea622768f33 b/.git/objects/46/894d8834b351bef44116c993e44ea622768f33 new file mode 100644 index 0000000..ca94b00 Binary files /dev/null and b/.git/objects/46/894d8834b351bef44116c993e44ea622768f33 differ diff --git a/.git/objects/46/c3b53837e5f35409c3f907d06ce050c91c7eec b/.git/objects/46/c3b53837e5f35409c3f907d06ce050c91c7eec new file mode 100644 index 0000000..214580b Binary files /dev/null and b/.git/objects/46/c3b53837e5f35409c3f907d06ce050c91c7eec differ diff --git a/.git/objects/46/cf1e982fb41e2ff024dcbc92e97d44679cc8fd b/.git/objects/46/cf1e982fb41e2ff024dcbc92e97d44679cc8fd new file mode 100644 index 0000000..f052800 Binary files /dev/null and b/.git/objects/46/cf1e982fb41e2ff024dcbc92e97d44679cc8fd differ diff --git a/.git/objects/46/e3f876cf90effc0f01c81e034a16513fa5fd3b b/.git/objects/46/e3f876cf90effc0f01c81e034a16513fa5fd3b new file mode 100644 index 0000000..a0f66c8 --- /dev/null +++ b/.git/objects/46/e3f876cf90effc0f01c81e034a16513fa5fd3b @@ -0,0 +1 @@ +xOKj0Z}eIB);JN0cC,%ͺ*{?q޶paf:?aGEQOeu"4ʼnѠGd؍Q,D1sDCmB{ u-Hy{AFQunUMp5"okNpK/Wd \ No newline at end of file diff --git a/.git/objects/46/fd96309ac5e60fb08137f17b9aaded9874fe03 b/.git/objects/46/fd96309ac5e60fb08137f17b9aaded9874fe03 new file mode 100644 index 0000000..faff7b5 Binary files /dev/null and b/.git/objects/46/fd96309ac5e60fb08137f17b9aaded9874fe03 differ diff --git a/.git/objects/47/033faa627af4b42f1ab0197f11141d5623702b b/.git/objects/47/033faa627af4b42f1ab0197f11141d5623702b new file mode 100644 index 0000000..4f4d150 Binary files /dev/null and b/.git/objects/47/033faa627af4b42f1ab0197f11141d5623702b differ diff --git a/.git/objects/47/3b057047ec9a6fe882448a549522474aa71340 b/.git/objects/47/3b057047ec9a6fe882448a549522474aa71340 new file mode 100644 index 0000000..03f2e39 Binary files /dev/null and b/.git/objects/47/3b057047ec9a6fe882448a549522474aa71340 differ diff --git a/.git/objects/47/6b5d686cb607adcf3717f99d0d2f2d43bd6488 b/.git/objects/47/6b5d686cb607adcf3717f99d0d2f2d43bd6488 new file mode 100644 index 0000000..4a6e0db Binary files /dev/null and b/.git/objects/47/6b5d686cb607adcf3717f99d0d2f2d43bd6488 differ diff --git a/.git/objects/47/bbdd5123c4f5bf6ea8381002d103e517911712 b/.git/objects/47/bbdd5123c4f5bf6ea8381002d103e517911712 new file mode 100644 index 0000000..b7cb892 Binary files /dev/null and b/.git/objects/47/bbdd5123c4f5bf6ea8381002d103e517911712 differ diff --git a/.git/objects/47/f150b4ce2305184ac2e923f06809113b574b65 b/.git/objects/47/f150b4ce2305184ac2e923f06809113b574b65 new file mode 100644 index 0000000..4fb7298 --- /dev/null +++ b/.git/objects/47/f150b4ce2305184ac2e923f06809113b574b65 @@ -0,0 +1,3 @@ +x%NMN vS +m13ĝn<1%)RgnދItc(F}W23r`shԎ4)m0Z`PC4Z59I{YY%}GS煯:(-xy'>A(Gx WpaH +2o)pXY ^ \ No newline at end of file diff --git a/.git/objects/48/0a08fecd36c1e1e2b1e166e68452c15bdc5b1a b/.git/objects/48/0a08fecd36c1e1e2b1e166e68452c15bdc5b1a new file mode 100644 index 0000000..de0ac1e --- /dev/null +++ b/.git/objects/48/0a08fecd36c1e1e2b1e166e68452c15bdc5b1a @@ -0,0 +1,2 @@ +xn0DSGAk0HӝR'M`mɘfg T 4= `mUV˞WEڶJŃ"jRf ڮEMcԠ40se_ +-M<0alW=Sy[#đ<\rRWr&kdoxq=8?\u%x2>eu3ǃ渺6` \ No newline at end of file diff --git a/.git/objects/48/19411da057bd1041227f289bb3c31561d4be13 b/.git/objects/48/19411da057bd1041227f289bb3c31561d4be13 new file mode 100644 index 0000000..5e0ba7c Binary files /dev/null and b/.git/objects/48/19411da057bd1041227f289bb3c31561d4be13 differ diff --git a/.git/objects/48/366e5852244687e6f45233f7a97cfe3e05e493 b/.git/objects/48/366e5852244687e6f45233f7a97cfe3e05e493 new file mode 100644 index 0000000..9a9c518 Binary files /dev/null and b/.git/objects/48/366e5852244687e6f45233f7a97cfe3e05e493 differ diff --git a/.git/objects/48/5cfb39aab06283ab8948abb06900da9d3b0341 b/.git/objects/48/5cfb39aab06283ab8948abb06900da9d3b0341 new file mode 100644 index 0000000..124e1fe Binary files /dev/null and b/.git/objects/48/5cfb39aab06283ab8948abb06900da9d3b0341 differ diff --git a/.git/objects/48/65ad5ac64d5310bfddd22f61f334bddad2c89d b/.git/objects/48/65ad5ac64d5310bfddd22f61f334bddad2c89d new file mode 100644 index 0000000..2939e05 Binary files /dev/null and b/.git/objects/48/65ad5ac64d5310bfddd22f61f334bddad2c89d differ diff --git a/.git/objects/48/73f49bcdfd14dd14ff160d8ef9567d56e70c8c b/.git/objects/48/73f49bcdfd14dd14ff160d8ef9567d56e70c8c new file mode 100644 index 0000000..5cd60ff Binary files /dev/null and b/.git/objects/48/73f49bcdfd14dd14ff160d8ef9567d56e70c8c differ diff --git a/.git/objects/48/9698c29ff0a8aac82c77cf9dbe7b197f3be423 b/.git/objects/48/9698c29ff0a8aac82c77cf9dbe7b197f3be423 new file mode 100644 index 0000000..a6ba171 Binary files /dev/null and b/.git/objects/48/9698c29ff0a8aac82c77cf9dbe7b197f3be423 differ diff --git a/.git/objects/48/f6013ecd84a80de87b6ea6e73d9a8bb7a66ca6 b/.git/objects/48/f6013ecd84a80de87b6ea6e73d9a8bb7a66ca6 new file mode 100644 index 0000000..5ad173c --- /dev/null +++ b/.git/objects/48/f6013ecd84a80de87b6ea6e73d9a8bb7a66ca6 @@ -0,0 +1,5 @@ +xUmo6W\WJa @bZ8ϲj9~J/^fٛw,6^*9lℓ8=7ʖh&Y爇qYJ8~qYnk[Pp1q.&^F\lǰ.Qmx G#5EsakKJ +'s&Ydj+86G`҄Ô~dX*|<Q\`M(~@!n8 X^̑0:/ӓLà l̼1VJH?>?vJx߈I>G޵ʡ=Gm߱ p%)BAcA+u.9 DhܠlAp뤏"FW!3zLZ E6<+iq[;.ڣp {[aB2Y0aU6x1 +2Ys$ J9 i }[U@! uJုmP==-}Iojj!{eb BWj~ ]<:kf^&.)S8dv @ m[C黵a;# \ No newline at end of file diff --git a/.git/objects/48/fbb4e5523226e0b4301dce4f30d92a27d52334 b/.git/objects/48/fbb4e5523226e0b4301dce4f30d92a27d52334 new file mode 100644 index 0000000..4f2d51d Binary files /dev/null and b/.git/objects/48/fbb4e5523226e0b4301dce4f30d92a27d52334 differ diff --git a/.git/objects/49/0e95e3ef2abde940e458b408324385123d2c42 b/.git/objects/49/0e95e3ef2abde940e458b408324385123d2c42 new file mode 100644 index 0000000..bc9117a Binary files /dev/null and b/.git/objects/49/0e95e3ef2abde940e458b408324385123d2c42 differ diff --git a/.git/objects/49/236ff593e6dfad99e957c3a721973a5df4f0fa b/.git/objects/49/236ff593e6dfad99e957c3a721973a5df4f0fa new file mode 100644 index 0000000..ca99e11 Binary files /dev/null and b/.git/objects/49/236ff593e6dfad99e957c3a721973a5df4f0fa differ diff --git a/.git/objects/49/8a2bd4b03e7d1327570660110dea2f676a36a3 b/.git/objects/49/8a2bd4b03e7d1327570660110dea2f676a36a3 new file mode 100644 index 0000000..949ac1a --- /dev/null +++ b/.git/objects/49/8a2bd4b03e7d1327570660110dea2f676a36a3 @@ -0,0 +1,2 @@ +xN09)c;BE np Gq}37q)4dfpF+?zeo4bs̱h-::D?X$"ݻQ2 +_(z𱸴u?9ڬ7ĮGƝB̼p\AzIi;55Gׂd*Usӻb"JIB6kDvFe J dکV)&x哂LU|| +43iMRw̻/f76 Aޕ V=9ңvbD1*,r7fNz@%PMVS'3R''k Gh44x%exZ8ÛisXKYxpNRQOB4Ky^5#m\~me:iP t7/ +LH>>;l8s Z \ No newline at end of file diff --git a/.git/objects/4a/b84307719d2513c6c6928b0367c13d33d8b64e b/.git/objects/4a/b84307719d2513c6c6928b0367c13d33d8b64e new file mode 100644 index 0000000..87ce208 Binary files /dev/null and b/.git/objects/4a/b84307719d2513c6c6928b0367c13d33d8b64e differ diff --git a/.git/objects/4a/be0f3f09880c25c3b9b70a4038873c976ffcf1 b/.git/objects/4a/be0f3f09880c25c3b9b70a4038873c976ffcf1 new file mode 100644 index 0000000..21f3055 Binary files /dev/null and b/.git/objects/4a/be0f3f09880c25c3b9b70a4038873c976ffcf1 differ diff --git a/.git/objects/4a/d6e8a41a791c186ec89f7f24c00651eb16d893 b/.git/objects/4a/d6e8a41a791c186ec89f7f24c00651eb16d893 new file mode 100644 index 0000000..42a5362 Binary files /dev/null and b/.git/objects/4a/d6e8a41a791c186ec89f7f24c00651eb16d893 differ diff --git a/.git/objects/4a/d898b7e025159cb6f796bfbe39c72be12c243e b/.git/objects/4a/d898b7e025159cb6f796bfbe39c72be12c243e new file mode 100644 index 0000000..2f7e7ae Binary files /dev/null and b/.git/objects/4a/d898b7e025159cb6f796bfbe39c72be12c243e differ diff --git a/.git/objects/4a/e6982dd496c04fa9ea9f3fc858ffe05fed926f b/.git/objects/4a/e6982dd496c04fa9ea9f3fc858ffe05fed926f new file mode 100644 index 0000000..0efa317 Binary files /dev/null and b/.git/objects/4a/e6982dd496c04fa9ea9f3fc858ffe05fed926f differ diff --git a/.git/objects/4b/02a73f150326ce4cc0143af0640dbf7f666506 b/.git/objects/4b/02a73f150326ce4cc0143af0640dbf7f666506 new file mode 100644 index 0000000..7e8e86d Binary files /dev/null and b/.git/objects/4b/02a73f150326ce4cc0143af0640dbf7f666506 differ diff --git a/.git/objects/4b/0498d0ce71194b33d6ac7713c1e88abdb8e8d2 b/.git/objects/4b/0498d0ce71194b33d6ac7713c1e88abdb8e8d2 new file mode 100644 index 0000000..26d631e Binary files /dev/null and b/.git/objects/4b/0498d0ce71194b33d6ac7713c1e88abdb8e8d2 differ diff --git a/.git/objects/4b/13adfd55d7c0a4fb0cca83507922fe959e17e3 b/.git/objects/4b/13adfd55d7c0a4fb0cca83507922fe959e17e3 new file mode 100644 index 0000000..89eff33 Binary files /dev/null and b/.git/objects/4b/13adfd55d7c0a4fb0cca83507922fe959e17e3 differ diff --git a/.git/objects/4b/2d0e186d5900e19c51f7e051388578e762d6cd b/.git/objects/4b/2d0e186d5900e19c51f7e051388578e762d6cd new file mode 100644 index 0000000..6c54187 Binary files /dev/null and b/.git/objects/4b/2d0e186d5900e19c51f7e051388578e762d6cd differ diff --git a/.git/objects/4b/453e1e5a932fcdf2c2a069129787f9eaeb703d b/.git/objects/4b/453e1e5a932fcdf2c2a069129787f9eaeb703d new file mode 100644 index 0000000..d8e2995 Binary files /dev/null and b/.git/objects/4b/453e1e5a932fcdf2c2a069129787f9eaeb703d differ diff --git a/.git/objects/4b/4e0aeb3bf71ae9147fab8ab2c8a707d9e33ccc b/.git/objects/4b/4e0aeb3bf71ae9147fab8ab2c8a707d9e33ccc new file mode 100644 index 0000000..7b1f151 --- /dev/null +++ b/.git/objects/4b/4e0aeb3bf71ae9147fab8ab2c8a707d9e33ccc @@ -0,0 +1,4 @@ +xTmO0W+k8PQH :uB$Gώ.ctlX{&\&^EUQs70*R0%$ %Uc~ >(n=Oʑ{FI\[kzRB7Q/8N y\pL=g S6kZ 3r;8orN;ۯ\K-G|@36KL.e *'RN-Y|fr\< (wKB=?3py \ No newline at end of file diff --git a/.git/objects/4b/f9fbb6a6cf905cd1a5f0d207256551388cc62c b/.git/objects/4b/f9fbb6a6cf905cd1a5f0d207256551388cc62c new file mode 100644 index 0000000..e331281 Binary files /dev/null and b/.git/objects/4b/f9fbb6a6cf905cd1a5f0d207256551388cc62c differ diff --git a/.git/objects/4c/05f0518058592fc679a5cafb6133d6fc6e648b b/.git/objects/4c/05f0518058592fc679a5cafb6133d6fc6e648b new file mode 100644 index 0000000..43cce71 --- /dev/null +++ b/.git/objects/4c/05f0518058592fc679a5cafb6133d6fc6e648b @@ -0,0 +1,2 @@ +x-J0=)"$Ϳ.zV M&Yw̻/fXd.3al +a-$+POFQ!tKPL w5MSd?pC%#8)[Rh9BXۙZeË3|6mcߟqi,JfNqЌR#t%;<GndڣDxûzP+7Un \ No newline at end of file diff --git a/.git/objects/4c/06d4103300db7cf8a181073bb3fbd5e64be4b1 b/.git/objects/4c/06d4103300db7cf8a181073bb3fbd5e64be4b1 new file mode 100644 index 0000000..72be091 --- /dev/null +++ b/.git/objects/4c/06d4103300db7cf8a181073bb3fbd5e64be4b1 @@ -0,0 +1,3 @@ +x-j0D{WH$+%@o_6Z&ɟ=eT/ + ;%\u%u*QI:RwAeu*0>$˔ga +}QNkz*M/8to}^@ʃWN³B4ԝq#&8aN8K{]cKaǍ霁a*ބ^bNo41@̙?aX \ No newline at end of file diff --git a/.git/objects/4c/32c596e441c2beb66ff9150c3f9b67f9b8d6ee b/.git/objects/4c/32c596e441c2beb66ff9150c3f9b67f9b8d6ee new file mode 100644 index 0000000..1816041 Binary files /dev/null and b/.git/objects/4c/32c596e441c2beb66ff9150c3f9b67f9b8d6ee differ diff --git a/.git/objects/4c/63ef1b700d2421140c82a1243b594dd8c9270b b/.git/objects/4c/63ef1b700d2421140c82a1243b594dd8c9270b new file mode 100644 index 0000000..c76597f Binary files /dev/null and b/.git/objects/4c/63ef1b700d2421140c82a1243b594dd8c9270b differ diff --git a/.git/objects/4c/811248f779d6287b99fc5acc8edf6b383c7389 b/.git/objects/4c/811248f779d6287b99fc5acc8edf6b383c7389 new file mode 100644 index 0000000..61ea948 Binary files /dev/null and b/.git/objects/4c/811248f779d6287b99fc5acc8edf6b383c7389 differ diff --git a/.git/objects/4c/a8bb1ce3d8ccb1dbe3235fe2e6c7bd5c692cb5 b/.git/objects/4c/a8bb1ce3d8ccb1dbe3235fe2e6c7bd5c692cb5 new file mode 100644 index 0000000..9af613b Binary files /dev/null and b/.git/objects/4c/a8bb1ce3d8ccb1dbe3235fe2e6c7bd5c692cb5 differ diff --git a/.git/objects/4c/b60dc9dfd6758ac4d27c1f45a91307884e0c49 b/.git/objects/4c/b60dc9dfd6758ac4d27c1f45a91307884e0c49 new file mode 100644 index 0000000..0d8da08 Binary files /dev/null and b/.git/objects/4c/b60dc9dfd6758ac4d27c1f45a91307884e0c49 differ diff --git a/.git/objects/4d/19f10b54b8ad1bb79d782e267e15bfb76be3c3 b/.git/objects/4d/19f10b54b8ad1bb79d782e267e15bfb76be3c3 new file mode 100644 index 0000000..5e22493 Binary files /dev/null and b/.git/objects/4d/19f10b54b8ad1bb79d782e267e15bfb76be3c3 differ diff --git a/.git/objects/4d/43a0f07ecd7f9dadce13a6c24bff3b6243322b b/.git/objects/4d/43a0f07ecd7f9dadce13a6c24bff3b6243322b new file mode 100644 index 0000000..8436af9 Binary files /dev/null and b/.git/objects/4d/43a0f07ecd7f9dadce13a6c24bff3b6243322b differ diff --git a/.git/objects/4d/478466900ec1cf086e94578d92b7e2a9db1400 b/.git/objects/4d/478466900ec1cf086e94578d92b7e2a9db1400 new file mode 100644 index 0000000..e60d1d3 Binary files /dev/null and b/.git/objects/4d/478466900ec1cf086e94578d92b7e2a9db1400 differ diff --git a/.git/objects/4d/a30180c9179fde05dd53006dcbd417550e51d2 b/.git/objects/4d/a30180c9179fde05dd53006dcbd417550e51d2 new file mode 100644 index 0000000..26521fb Binary files /dev/null and b/.git/objects/4d/a30180c9179fde05dd53006dcbd417550e51d2 differ diff --git a/.git/objects/4d/ac9908813e6e17316e7366b109208f4c1e80d0 b/.git/objects/4d/ac9908813e6e17316e7366b109208f4c1e80d0 new file mode 100644 index 0000000..7bc4aac Binary files /dev/null and b/.git/objects/4d/ac9908813e6e17316e7366b109208f4c1e80d0 differ diff --git a/.git/objects/4d/af8757d29d22dc3e9b7e6570cf0474c68b2a85 b/.git/objects/4d/af8757d29d22dc3e9b7e6570cf0474c68b2a85 new file mode 100644 index 0000000..6404c08 Binary files /dev/null and b/.git/objects/4d/af8757d29d22dc3e9b7e6570cf0474c68b2a85 differ diff --git a/.git/objects/4d/b2d674d4acf9222ac7c34e04d71a5bda138148 b/.git/objects/4d/b2d674d4acf9222ac7c34e04d71a5bda138148 new file mode 100644 index 0000000..4b55dfb Binary files /dev/null and b/.git/objects/4d/b2d674d4acf9222ac7c34e04d71a5bda138148 differ diff --git a/.git/objects/4d/df6442c6b5c9107f49cd1abf941eb7a8ce50af b/.git/objects/4d/df6442c6b5c9107f49cd1abf941eb7a8ce50af new file mode 100644 index 0000000..2a29187 Binary files /dev/null and b/.git/objects/4d/df6442c6b5c9107f49cd1abf941eb7a8ce50af differ diff --git a/.git/objects/4e/3ecd24911583114b229904493e41b1601b761d b/.git/objects/4e/3ecd24911583114b229904493e41b1601b761d new file mode 100644 index 0000000..d611172 Binary files /dev/null and b/.git/objects/4e/3ecd24911583114b229904493e41b1601b761d differ diff --git a/.git/objects/4e/40de50940ddefe6747db54c33a7223ccf977a4 b/.git/objects/4e/40de50940ddefe6747db54c33a7223ccf977a4 new file mode 100644 index 0000000..4b2bb59 Binary files /dev/null and b/.git/objects/4e/40de50940ddefe6747db54c33a7223ccf977a4 differ diff --git a/.git/objects/4e/65b9e962f1a249fbaba91049a07b751758b8f5 b/.git/objects/4e/65b9e962f1a249fbaba91049a07b751758b8f5 new file mode 100644 index 0000000..bb4fa20 Binary files /dev/null and b/.git/objects/4e/65b9e962f1a249fbaba91049a07b751758b8f5 differ diff --git a/.git/objects/4e/8d759dbdd9a3f042d12a8871c1f4aceaea1268 b/.git/objects/4e/8d759dbdd9a3f042d12a8871c1f4aceaea1268 new file mode 100644 index 0000000..fee32f2 Binary files /dev/null and b/.git/objects/4e/8d759dbdd9a3f042d12a8871c1f4aceaea1268 differ diff --git a/.git/objects/4e/c6597ac22f54dab8fd5835d9f679e3f8192bf7 b/.git/objects/4e/c6597ac22f54dab8fd5835d9f679e3f8192bf7 new file mode 100644 index 0000000..841f26e Binary files /dev/null and b/.git/objects/4e/c6597ac22f54dab8fd5835d9f679e3f8192bf7 differ diff --git a/.git/objects/4e/dfd0d2bbcbbc87f570b7a33d2288b15c417c93 b/.git/objects/4e/dfd0d2bbcbbc87f570b7a33d2288b15c417c93 new file mode 100644 index 0000000..3d50603 Binary files /dev/null and b/.git/objects/4e/dfd0d2bbcbbc87f570b7a33d2288b15c417c93 differ diff --git a/.git/objects/4e/ea69d27159eafd8dfd782049c8ec6b93adda26 b/.git/objects/4e/ea69d27159eafd8dfd782049c8ec6b93adda26 new file mode 100644 index 0000000..456ed0e Binary files /dev/null and b/.git/objects/4e/ea69d27159eafd8dfd782049c8ec6b93adda26 differ diff --git a/.git/objects/4e/f5ab6cf5d29d8754be1f2328d00c04a29b0a0c b/.git/objects/4e/f5ab6cf5d29d8754be1f2328d00c04a29b0a0c new file mode 100644 index 0000000..549bbc6 Binary files /dev/null and b/.git/objects/4e/f5ab6cf5d29d8754be1f2328d00c04a29b0a0c differ diff --git a/.git/objects/4f/12624d9160e518430027363faf67501d87e9c7 b/.git/objects/4f/12624d9160e518430027363faf67501d87e9c7 new file mode 100644 index 0000000..f956ced Binary files /dev/null and b/.git/objects/4f/12624d9160e518430027363faf67501d87e9c7 differ diff --git a/.git/objects/4f/1464197185aef75742e4283a3f304d01c94e63 b/.git/objects/4f/1464197185aef75742e4283a3f304d01c94e63 new file mode 100644 index 0000000..f5931ee Binary files /dev/null and b/.git/objects/4f/1464197185aef75742e4283a3f304d01c94e63 differ diff --git a/.git/objects/4f/1bc23433f5afc831984a5edf43e55b180484fb b/.git/objects/4f/1bc23433f5afc831984a5edf43e55b180484fb new file mode 100644 index 0000000..300ebe6 Binary files /dev/null and b/.git/objects/4f/1bc23433f5afc831984a5edf43e55b180484fb differ diff --git a/.git/objects/4f/27788072404a7bc2f59766617c3102af6102b3 b/.git/objects/4f/27788072404a7bc2f59766617c3102af6102b3 new file mode 100644 index 0000000..edeb073 Binary files /dev/null and b/.git/objects/4f/27788072404a7bc2f59766617c3102af6102b3 differ diff --git a/.git/objects/4f/486b66fb17213626995b2f63cafa038221a3cb b/.git/objects/4f/486b66fb17213626995b2f63cafa038221a3cb new file mode 100644 index 0000000..698038c Binary files /dev/null and b/.git/objects/4f/486b66fb17213626995b2f63cafa038221a3cb differ diff --git a/.git/objects/4f/4f24e355bd467f2950cfd37084a15974fc0e95 b/.git/objects/4f/4f24e355bd467f2950cfd37084a15974fc0e95 new file mode 100644 index 0000000..e12d5ad Binary files /dev/null and b/.git/objects/4f/4f24e355bd467f2950cfd37084a15974fc0e95 differ diff --git a/.git/objects/4f/5b30ab75aedb42fafd4f661673ff803f412db5 b/.git/objects/4f/5b30ab75aedb42fafd4f661673ff803f412db5 new file mode 100644 index 0000000..3cfcf27 Binary files /dev/null and b/.git/objects/4f/5b30ab75aedb42fafd4f661673ff803f412db5 differ diff --git a/.git/objects/4f/64a68f60b6b87803f3c20dcab7878e42ec5b01 b/.git/objects/4f/64a68f60b6b87803f3c20dcab7878e42ec5b01 new file mode 100644 index 0000000..b13a84f Binary files /dev/null and b/.git/objects/4f/64a68f60b6b87803f3c20dcab7878e42ec5b01 differ diff --git a/.git/objects/4f/6b22c82e202fdf53020f35d069a38972a2a3a8 b/.git/objects/4f/6b22c82e202fdf53020f35d069a38972a2a3a8 new file mode 100644 index 0000000..4e1dc34 Binary files /dev/null and b/.git/objects/4f/6b22c82e202fdf53020f35d069a38972a2a3a8 differ diff --git a/.git/objects/4f/6f546def06c32545d3e219fcee9f9f8818870d b/.git/objects/4f/6f546def06c32545d3e219fcee9f9f8818870d new file mode 100644 index 0000000..47dc64d Binary files /dev/null and b/.git/objects/4f/6f546def06c32545d3e219fcee9f9f8818870d differ diff --git a/.git/objects/4f/792a28ba361d8fe2bc22e77a05b13b14aab166 b/.git/objects/4f/792a28ba361d8fe2bc22e77a05b13b14aab166 new file mode 100644 index 0000000..fcc53fd --- /dev/null +++ b/.git/objects/4f/792a28ba361d8fe2bc22e77a05b13b14aab166 @@ -0,0 +1,3 @@ +xP1n LWlNER\` `]XHhfm\W_eCIDJ2F=lI(+"iC +͆BAH83ҸJw-*x{cׅ0۸)w +z)3UN1'\n4<2XSڻԜ9 ט& p?ಯO4v.dDŽRd7Д~1>L\h/3F\1D LPܶ[,>g \ No newline at end of file diff --git a/.git/objects/4f/7ab9a8b495a330f745e04bfc6aaf50d71930a3 b/.git/objects/4f/7ab9a8b495a330f745e04bfc6aaf50d71930a3 new file mode 100644 index 0000000..12e6f12 Binary files /dev/null and b/.git/objects/4f/7ab9a8b495a330f745e04bfc6aaf50d71930a3 differ diff --git a/.git/objects/4f/afd3db57f1a7219dc2551f77eb8d402e8663f7 b/.git/objects/4f/afd3db57f1a7219dc2551f77eb8d402e8663f7 new file mode 100644 index 0000000..f412067 Binary files /dev/null and b/.git/objects/4f/afd3db57f1a7219dc2551f77eb8d402e8663f7 differ diff --git a/.git/objects/4f/be57c1e129ec90d61d251710addaf7c21afada b/.git/objects/4f/be57c1e129ec90d61d251710addaf7c21afada new file mode 100644 index 0000000..61e29c0 Binary files /dev/null and b/.git/objects/4f/be57c1e129ec90d61d251710addaf7c21afada differ diff --git a/.git/objects/4f/ee566be1f97255c5292ad639e1e4ae15cf66c9 b/.git/objects/4f/ee566be1f97255c5292ad639e1e4ae15cf66c9 new file mode 100644 index 0000000..502ffca Binary files /dev/null and b/.git/objects/4f/ee566be1f97255c5292ad639e1e4ae15cf66c9 differ diff --git a/.git/objects/50/0c6a3fa239e53664cb149f77cb97004aac82d4 b/.git/objects/50/0c6a3fa239e53664cb149f77cb97004aac82d4 new file mode 100644 index 0000000..34d4889 Binary files /dev/null and b/.git/objects/50/0c6a3fa239e53664cb149f77cb97004aac82d4 differ diff --git a/.git/objects/50/4817d08f5e2336f7ac79f102a2577924ab1fc3 b/.git/objects/50/4817d08f5e2336f7ac79f102a2577924ab1fc3 new file mode 100644 index 0000000..84ff767 --- /dev/null +++ b/.git/objects/50/4817d08f5e2336f7ac79f102a2577924ab1fc3 @@ -0,0 +1 @@ +x-MN0 Y#FI $vnL#I{.F==y]c4f0($Z )N7E±6**hhIdv1h٠0{}Ъι_&.}^sx3>E q9xixsoɎJ +ݧ#ڸ[ew/%_r={xO~)nqghwn {H.?i \ No newline at end of file diff --git a/.git/objects/50/74bb97ec50ed535a6339fc721f8230b14fff38 b/.git/objects/50/74bb97ec50ed535a6339fc721f8230b14fff38 new file mode 100644 index 0000000..8564945 Binary files /dev/null and b/.git/objects/50/74bb97ec50ed535a6339fc721f8230b14fff38 differ diff --git a/.git/objects/50/81bc0a48f895fc444d0386febfeb29c8309e80 b/.git/objects/50/81bc0a48f895fc444d0386febfeb29c8309e80 new file mode 100644 index 0000000..34cdb39 --- /dev/null +++ b/.git/objects/50/81bc0a48f895fc444d0386febfeb29c8309e80 @@ -0,0 +1,2 @@ +xKN0DYG9b$Ab߱;937c!+(۶48޴ laS*yS@yϑ0e ٠iV:7Zo FhY*We^jǖ9tr=E`DPiD +z/+7M>o\Ei;L3Htpl) \ No newline at end of file diff --git a/.git/objects/50/b3caf09b7941b13d1d258638a5a19b656d3eda b/.git/objects/50/b3caf09b7941b13d1d258638a5a19b656d3eda new file mode 100644 index 0000000..35fc453 Binary files /dev/null and b/.git/objects/50/b3caf09b7941b13d1d258638a5a19b656d3eda differ diff --git a/.git/objects/50/cb6273816fb2524362795bc956e576ec71d35b b/.git/objects/50/cb6273816fb2524362795bc956e576ec71d35b new file mode 100644 index 0000000..09595ff Binary files /dev/null and b/.git/objects/50/cb6273816fb2524362795bc956e576ec71d35b differ diff --git a/.git/objects/51/1353717a8a15ca6be8ec4b1937bf92d01e0959 b/.git/objects/51/1353717a8a15ca6be8ec4b1937bf92d01e0959 new file mode 100644 index 0000000..878e688 Binary files /dev/null and b/.git/objects/51/1353717a8a15ca6be8ec4b1937bf92d01e0959 differ diff --git a/.git/objects/51/3ba1a433fd3a50559bdd6205cbf85dd6b850d9 b/.git/objects/51/3ba1a433fd3a50559bdd6205cbf85dd6b850d9 new file mode 100644 index 0000000..c810e8f Binary files /dev/null and b/.git/objects/51/3ba1a433fd3a50559bdd6205cbf85dd6b850d9 differ diff --git a/.git/objects/51/539416f1ffabd6cb20f7531583838cf761dd79 b/.git/objects/51/539416f1ffabd6cb20f7531583838cf761dd79 new file mode 100644 index 0000000..ba1688e Binary files /dev/null and b/.git/objects/51/539416f1ffabd6cb20f7531583838cf761dd79 differ diff --git a/.git/objects/51/710bb22deffd060d89daeb1af77f263dbb7068 b/.git/objects/51/710bb22deffd060d89daeb1af77f263dbb7068 new file mode 100644 index 0000000..fa59718 Binary files /dev/null and b/.git/objects/51/710bb22deffd060d89daeb1af77f263dbb7068 differ diff --git a/.git/objects/51/7dd355111a253100f39c57419c44b28a352758 b/.git/objects/51/7dd355111a253100f39c57419c44b28a352758 new file mode 100644 index 0000000..44e48b9 Binary files /dev/null and b/.git/objects/51/7dd355111a253100f39c57419c44b28a352758 differ diff --git a/.git/objects/51/8d23825f67cef503ff68a6d983a8c79d4f0b96 b/.git/objects/51/8d23825f67cef503ff68a6d983a8c79d4f0b96 new file mode 100644 index 0000000..7b87ba3 Binary files /dev/null and b/.git/objects/51/8d23825f67cef503ff68a6d983a8c79d4f0b96 differ diff --git a/.git/objects/51/db18bbf651d1149a613789cd9226b6d45e7b9d b/.git/objects/51/db18bbf651d1149a613789cd9226b6d45e7b9d new file mode 100644 index 0000000..99e2d5b Binary files /dev/null and b/.git/objects/51/db18bbf651d1149a613789cd9226b6d45e7b9d differ diff --git a/.git/objects/51/e1e99250209fcda8bdc3462adc30959c640844 b/.git/objects/51/e1e99250209fcda8bdc3462adc30959c640844 new file mode 100644 index 0000000..c27e7a1 Binary files /dev/null and b/.git/objects/51/e1e99250209fcda8bdc3462adc30959c640844 differ diff --git a/.git/objects/52/05247069f0878fa9933469783a42fd431524eb b/.git/objects/52/05247069f0878fa9933469783a42fd431524eb new file mode 100644 index 0000000..7c93989 Binary files /dev/null and b/.git/objects/52/05247069f0878fa9933469783a42fd431524eb differ diff --git a/.git/objects/52/0beca26885e903e2a0fff2d62da53e1a22f1f3 b/.git/objects/52/0beca26885e903e2a0fff2d62da53e1a22f1f3 new file mode 100644 index 0000000..1d8ce5f Binary files /dev/null and b/.git/objects/52/0beca26885e903e2a0fff2d62da53e1a22f1f3 differ diff --git a/.git/objects/52/17f4d1119c8cfa7c110804aea40b9576fe6e3e b/.git/objects/52/17f4d1119c8cfa7c110804aea40b9576fe6e3e new file mode 100644 index 0000000..4901b83 Binary files /dev/null and b/.git/objects/52/17f4d1119c8cfa7c110804aea40b9576fe6e3e differ diff --git a/.git/objects/52/4489dc63bbe0bbae86e990cfc0abae0213c3a3 b/.git/objects/52/4489dc63bbe0bbae86e990cfc0abae0213c3a3 new file mode 100644 index 0000000..27a0cd4 Binary files /dev/null and b/.git/objects/52/4489dc63bbe0bbae86e990cfc0abae0213c3a3 differ diff --git a/.git/objects/52/506667fac4edc450a3bf3ac478c60ce5eed9e8 b/.git/objects/52/506667fac4edc450a3bf3ac478c60ce5eed9e8 new file mode 100644 index 0000000..19a9621 Binary files /dev/null and b/.git/objects/52/506667fac4edc450a3bf3ac478c60ce5eed9e8 differ diff --git a/.git/objects/52/6f291d2a5b2d3780ca3fa46fa10cc35f4c7a5d b/.git/objects/52/6f291d2a5b2d3780ca3fa46fa10cc35f4c7a5d new file mode 100644 index 0000000..2d4b3b1 Binary files /dev/null and b/.git/objects/52/6f291d2a5b2d3780ca3fa46fa10cc35f4c7a5d differ diff --git a/.git/objects/52/89fff28c8e9c794b04dab4ea4c278dc4e50226 b/.git/objects/52/89fff28c8e9c794b04dab4ea4c278dc4e50226 new file mode 100644 index 0000000..addbb25 --- /dev/null +++ b/.git/objects/52/89fff28c8e9c794b04dab4ea4c278dc4e50226 @@ -0,0 +1,2 @@ +xKn0D22 fE d3'h,1&7> guU*2J? e]au +lUQJl2=b!)[u dԲHceAkcW ޜ\??ROxiݦ2@YI-GQ Q ϼǣ64İTK,h3] gSL #_=L,40c 9㐴_Oo^ \ No newline at end of file diff --git a/.git/objects/52/b0bae49f4914904076437915d3e091008a226b b/.git/objects/52/b0bae49f4914904076437915d3e091008a226b new file mode 100644 index 0000000..8823dff Binary files /dev/null and b/.git/objects/52/b0bae49f4914904076437915d3e091008a226b differ diff --git a/.git/objects/52/b4f03c0f3cb661e7b7f6b7c81927c87406a414 b/.git/objects/52/b4f03c0f3cb661e7b7f6b7c81927c87406a414 new file mode 100644 index 0000000..c0df754 Binary files /dev/null and b/.git/objects/52/b4f03c0f3cb661e7b7f6b7c81927c87406a414 differ diff --git a/.git/objects/52/c08a93111f40320fc9ad9d7923a7f011dc663d b/.git/objects/52/c08a93111f40320fc9ad9d7923a7f011dc663d new file mode 100644 index 0000000..dcd14aa Binary files /dev/null and b/.git/objects/52/c08a93111f40320fc9ad9d7923a7f011dc663d differ diff --git a/.git/objects/52/cd2fc55dd39821578dfb1dd33a9b432c140f3d b/.git/objects/52/cd2fc55dd39821578dfb1dd33a9b432c140f3d new file mode 100644 index 0000000..4fbc09b --- /dev/null +++ b/.git/objects/52/cd2fc55dd39821578dfb1dd33a9b432c140f3d @@ -0,0 +1 @@ +x%N;N0)GD'F+N0'K9ތaA.k sMBYj7FXH3FK#6,*(!E#ђI(2|PNH;< vdW\=umkyYJ- &81k0>-Gx Wma 9A {~~WV \ No newline at end of file diff --git a/.git/objects/53/1249ae2d36e8e6b3d69e002c5b8219c80aa410 b/.git/objects/53/1249ae2d36e8e6b3d69e002c5b8219c80aa410 new file mode 100644 index 0000000..a859121 Binary files /dev/null and b/.git/objects/53/1249ae2d36e8e6b3d69e002c5b8219c80aa410 differ diff --git a/.git/objects/53/2c34d3d3ac4b5fdc5d55bd2f4c0a8f86b540bc b/.git/objects/53/2c34d3d3ac4b5fdc5d55bd2f4c0a8f86b540bc new file mode 100644 index 0000000..61d817b Binary files /dev/null and b/.git/objects/53/2c34d3d3ac4b5fdc5d55bd2f4c0a8f86b540bc differ diff --git a/.git/objects/53/393007d43b66eecf12bb10eb7c0d216d104d17 b/.git/objects/53/393007d43b66eecf12bb10eb7c0d216d104d17 new file mode 100644 index 0000000..126cffe Binary files /dev/null and b/.git/objects/53/393007d43b66eecf12bb10eb7c0d216d104d17 differ diff --git a/.git/objects/53/393dc78b1ea0acb2430bf741be8be73305cf11 b/.git/objects/53/393dc78b1ea0acb2430bf741be8be73305cf11 new file mode 100644 index 0000000..c5e0cb8 Binary files /dev/null and b/.git/objects/53/393dc78b1ea0acb2430bf741be8be73305cf11 differ diff --git a/.git/objects/53/6ad716887df8dd7c88546ac575d032cbdcb9c5 b/.git/objects/53/6ad716887df8dd7c88546ac575d032cbdcb9c5 new file mode 100644 index 0000000..555313f Binary files /dev/null and b/.git/objects/53/6ad716887df8dd7c88546ac575d032cbdcb9c5 differ diff --git a/.git/objects/53/8a5345a261bdd30482ae7702fdec76d62abd1e b/.git/objects/53/8a5345a261bdd30482ae7702fdec76d62abd1e new file mode 100644 index 0000000..9007820 Binary files /dev/null and b/.git/objects/53/8a5345a261bdd30482ae7702fdec76d62abd1e differ diff --git a/.git/objects/53/92dc3be8c3ff7ab9fb3701193a059e1957baee b/.git/objects/53/92dc3be8c3ff7ab9fb3701193a059e1957baee new file mode 100644 index 0000000..39e8bdd --- /dev/null +++ b/.git/objects/53/92dc3be8c3ff7ab9fb3701193a059e1957baee @@ -0,0 +1 @@ +x%OK0=SXMXdA"EH-ݤG?q/X*=CC+D@HAg 2qdh7^Ie[,"#zTgIKw0tp<)pmS.p ||D}mv-87Lk9G&xש +o\0ƻ5%ȭqcN7RCB +W: K 96Kɖj + 4u2mj \ No newline at end of file diff --git a/.git/objects/53/ad01cb504110e979dda9ff016927cf8c6ca742 b/.git/objects/53/ad01cb504110e979dda9ff016927cf8c6ca742 new file mode 100644 index 0000000..d6c42de Binary files /dev/null and b/.git/objects/53/ad01cb504110e979dda9ff016927cf8c6ca742 differ diff --git a/.git/objects/54/0e39dbbd7eef1766f6ec380796aa5558c6481a b/.git/objects/54/0e39dbbd7eef1766f6ec380796aa5558c6481a new file mode 100644 index 0000000..b42aec7 --- /dev/null +++ b/.git/objects/54/0e39dbbd7eef1766f6ec380796aa5558c6481a @@ -0,0 +1 @@ +x%KN0DYGDvFhF 'IPlG07cŰ`WW*J!:=> H=FR5h ңdIG7mn9p!OpJPTJYek(Kp o+ ;GxΑw8aMeV9{K)QH!ߥ.yN#ewCM'I7i`*W8s~s0g s XO \ No newline at end of file diff --git a/.git/objects/54/4ea07d47be06d8684304a3c1b549077464564d b/.git/objects/54/4ea07d47be06d8684304a3c1b549077464564d new file mode 100644 index 0000000..dc05016 Binary files /dev/null and b/.git/objects/54/4ea07d47be06d8684304a3c1b549077464564d differ diff --git a/.git/objects/54/6fbf2f71dfa8c5d0e7d9a6df740720cb8297ff b/.git/objects/54/6fbf2f71dfa8c5d0e7d9a6df740720cb8297ff new file mode 100644 index 0000000..4263549 Binary files /dev/null and b/.git/objects/54/6fbf2f71dfa8c5d0e7d9a6df740720cb8297ff differ diff --git a/.git/objects/54/9d6759f71cb7d75c8b1cb20eeff9090dfc95c7 b/.git/objects/54/9d6759f71cb7d75c8b1cb20eeff9090dfc95c7 new file mode 100644 index 0000000..b3b9053 Binary files /dev/null and b/.git/objects/54/9d6759f71cb7d75c8b1cb20eeff9090dfc95c7 differ diff --git a/.git/objects/54/a4b3196f4e44395d7c9546495ce85fef91d890 b/.git/objects/54/a4b3196f4e44395d7c9546495ce85fef91d890 new file mode 100644 index 0000000..9442365 Binary files /dev/null and b/.git/objects/54/a4b3196f4e44395d7c9546495ce85fef91d890 differ diff --git a/.git/objects/54/b9c3ec18e12c6e03d93e5fccf4a173bbeb5624 b/.git/objects/54/b9c3ec18e12c6e03d93e5fccf4a173bbeb5624 new file mode 100644 index 0000000..cfca252 Binary files /dev/null and b/.git/objects/54/b9c3ec18e12c6e03d93e5fccf4a173bbeb5624 differ diff --git a/.git/objects/54/d367b9ff41c71c4533d34c70678913a6fe02f1 b/.git/objects/54/d367b9ff41c71c4533d34c70678913a6fe02f1 new file mode 100644 index 0000000..be414e0 Binary files /dev/null and b/.git/objects/54/d367b9ff41c71c4533d34c70678913a6fe02f1 differ diff --git a/.git/objects/55/31d067781c4e32b1c39a0e21984de3ab20e3c6 b/.git/objects/55/31d067781c4e32b1c39a0e21984de3ab20e3c6 new file mode 100644 index 0000000..02e9940 Binary files /dev/null and b/.git/objects/55/31d067781c4e32b1c39a0e21984de3ab20e3c6 differ diff --git a/.git/objects/55/3cb8ea1fb5f784053ce89ea362d07829978fdb b/.git/objects/55/3cb8ea1fb5f784053ce89ea362d07829978fdb new file mode 100644 index 0000000..aabccbf Binary files /dev/null and b/.git/objects/55/3cb8ea1fb5f784053ce89ea362d07829978fdb differ diff --git a/.git/objects/55/4de6de26176bc2b86ae07148647b4131c39fbe b/.git/objects/55/4de6de26176bc2b86ae07148647b4131c39fbe new file mode 100644 index 0000000..e6f6a71 Binary files /dev/null and b/.git/objects/55/4de6de26176bc2b86ae07148647b4131c39fbe differ diff --git a/.git/objects/55/60eaaba30454597d90d93bc9ad132cd5443ad7 b/.git/objects/55/60eaaba30454597d90d93bc9ad132cd5443ad7 new file mode 100644 index 0000000..91a7afa --- /dev/null +++ b/.git/objects/55/60eaaba30454597d90d93bc9ad132cd5443ad7 @@ -0,0 +1,3 @@ +xMN0`9+*eHj/vJz3\}͘94L?BGIA+$.uºrݻ)p➏<7Q? +JqH"vfiS.pks4J ޾>K +/z!-z Őq`&oDVtoQ9stFAVe0Fo`pg \ No newline at end of file diff --git a/.git/objects/55/af0947a6b9c1aef74240e52484fd8434c7b7fa b/.git/objects/55/af0947a6b9c1aef74240e52484fd8434c7b7fa new file mode 100644 index 0000000..7cfb044 Binary files /dev/null and b/.git/objects/55/af0947a6b9c1aef74240e52484fd8434c7b7fa differ diff --git a/.git/objects/55/b01103badc5666eec22b514785edc4173664f3 b/.git/objects/55/b01103badc5666eec22b514785edc4173664f3 new file mode 100644 index 0000000..321ce36 Binary files /dev/null and b/.git/objects/55/b01103badc5666eec22b514785edc4173664f3 differ diff --git a/.git/objects/55/bfefb8e4ac76138140076d787a8715f9b84b31 b/.git/objects/55/bfefb8e4ac76138140076d787a8715f9b84b31 new file mode 100644 index 0000000..fda87ca Binary files /dev/null and b/.git/objects/55/bfefb8e4ac76138140076d787a8715f9b84b31 differ diff --git a/.git/objects/55/d1c758690dedf3e554d3bfc6c6f14d04cca58e b/.git/objects/55/d1c758690dedf3e554d3bfc6c6f14d04cca58e new file mode 100644 index 0000000..8c38309 Binary files /dev/null and b/.git/objects/55/d1c758690dedf3e554d3bfc6c6f14d04cca58e differ diff --git a/.git/objects/55/d6d36bf69dc2bd3865c38971f4105637a959f6 b/.git/objects/55/d6d36bf69dc2bd3865c38971f4105637a959f6 new file mode 100644 index 0000000..ca4e091 Binary files /dev/null and b/.git/objects/55/d6d36bf69dc2bd3865c38971f4105637a959f6 differ diff --git a/.git/objects/55/d9f32c0a50aac2aaa63b04e5e50e676ab2fc81 b/.git/objects/55/d9f32c0a50aac2aaa63b04e5e50e676ab2fc81 new file mode 100644 index 0000000..b2f9b9c --- /dev/null +++ b/.git/objects/55/d9f32c0a50aac2aaa63b04e5e50e676ab2fc81 @@ -0,0 +1 @@ +x%N0D9+v&Q* .|@$(#Qɟq06y32FV1L/4b/5 AԷ Qg RuAk% eԚy/ GxtՖwJz# V o AB;H EaU;o!QqR2l[B^eN%szʯ ,1, cyM~8q~He \ No newline at end of file diff --git a/.git/objects/55/e325dc80d5547bf4ab9552f2f21e152ca81696 b/.git/objects/55/e325dc80d5547bf4ab9552f2f21e152ca81696 new file mode 100644 index 0000000..9e8f4ce Binary files /dev/null and b/.git/objects/55/e325dc80d5547bf4ab9552f2f21e152ca81696 differ diff --git a/.git/objects/56/08bf0cd206688d146ac9e663dac0389995ed4f b/.git/objects/56/08bf0cd206688d146ac9e663dac0389995ed4f new file mode 100644 index 0000000..e0ee96c Binary files /dev/null and b/.git/objects/56/08bf0cd206688d146ac9e663dac0389995ed4f differ diff --git a/.git/objects/56/0b4bdb18a4661810b5ce5e2e7c7038668ae850 b/.git/objects/56/0b4bdb18a4661810b5ce5e2e7c7038668ae850 new file mode 100644 index 0000000..6d33fe1 Binary files /dev/null and b/.git/objects/56/0b4bdb18a4661810b5ce5e2e7c7038668ae850 differ diff --git a/.git/objects/56/1682cd231bdc676d822f7c3b1497de007007ef b/.git/objects/56/1682cd231bdc676d822f7c3b1497de007007ef new file mode 100644 index 0000000..4a0c32d Binary files /dev/null and b/.git/objects/56/1682cd231bdc676d822f7c3b1497de007007ef differ diff --git a/.git/objects/56/1ceebfbe51a4735d491a63ecad67a9cb60e25f b/.git/objects/56/1ceebfbe51a4735d491a63ecad67a9cb60e25f new file mode 100644 index 0000000..731c970 Binary files /dev/null and b/.git/objects/56/1ceebfbe51a4735d491a63ecad67a9cb60e25f differ diff --git a/.git/objects/56/1e44573dec650cfab8f650588c15da5d01e8f0 b/.git/objects/56/1e44573dec650cfab8f650588c15da5d01e8f0 new file mode 100644 index 0000000..93c49bc Binary files /dev/null and b/.git/objects/56/1e44573dec650cfab8f650588c15da5d01e8f0 differ diff --git a/.git/objects/56/65241fca21f40b17657577215b1c2ab102547e b/.git/objects/56/65241fca21f40b17657577215b1c2ab102547e new file mode 100644 index 0000000..160a9bc --- /dev/null +++ b/.git/objects/56/65241fca21f40b17657577215b1c2ab102547e @@ -0,0 +1,3 @@ +xM1k0;WY:ɲB :tvOH2*}w{6 )J&.G)UR;g4{7t +=tQfLE$\h9(J))hZ*\˔2s9*a ϭMx$b 7[׻}I%<ڛ + J2\,l^3#K9`)t)iJW+h j uFX3fK j?kTty \ No newline at end of file diff --git a/.git/objects/56/72f2e82b2ce1dd458b135890802abf9ae4fa09 b/.git/objects/56/72f2e82b2ce1dd458b135890802abf9ae4fa09 new file mode 100644 index 0000000..b788f3c --- /dev/null +++ b/.git/objects/56/72f2e82b2ce1dd458b135890802abf9ae4fa09 @@ -0,0 +1 @@ +x-NKj0ڧxҠ%[BJvc=}o_^D[{!:D!NV \ No newline at end of file diff --git a/.git/objects/56/7ae1d04b1f3cffa3a0113df752ba693ac3ca3e b/.git/objects/56/7ae1d04b1f3cffa3a0113df752ba693ac3ca3e new file mode 100644 index 0000000..ce52ee5 --- /dev/null +++ b/.git/objects/56/7ae1d04b1f3cffa3a0113df752ba693ac3ca3e @@ -0,0 +1,9 @@ +xUkPg AeT"*Tj @PBA7K : +hNhtDVQD妆(zȸ?|y99 ^˽ە'C)T9/;0w~x~w옙S !$ {Z= R1RYqk&0M4.nDQZ U|{p1'0)PT.K˺ ^+-Yq;['ј"?#9& l6-C,d"JZx㜚gݻ qu +|øS Ji}]gZvrl{x WN@ ++F}q V>isͦ!,5>ߩ?>Fb8˷9͈), P9׿0 @~y}$sN4lE \ No newline at end of file diff --git a/.git/objects/57/a134580120511e5e6412dca3b6ed41440cdb97 b/.git/objects/57/a134580120511e5e6412dca3b6ed41440cdb97 new file mode 100644 index 0000000..25c8a67 Binary files /dev/null and b/.git/objects/57/a134580120511e5e6412dca3b6ed41440cdb97 differ diff --git a/.git/objects/57/aa6d5fbe47fc22e6941db1968864123f416f5d b/.git/objects/57/aa6d5fbe47fc22e6941db1968864123f416f5d new file mode 100644 index 0000000..18cb146 Binary files /dev/null and b/.git/objects/57/aa6d5fbe47fc22e6941db1968864123f416f5d differ diff --git a/.git/objects/57/f51ee1e45ba023555a62b88b81e8c2b923d4b9 b/.git/objects/57/f51ee1e45ba023555a62b88b81e8c2b923d4b9 new file mode 100644 index 0000000..b7bb3f0 Binary files /dev/null and b/.git/objects/57/f51ee1e45ba023555a62b88b81e8c2b923d4b9 differ diff --git a/.git/objects/57/f92a438a038a58073f78d676d69426de044cc8 b/.git/objects/57/f92a438a038a58073f78d676d69426de044cc8 new file mode 100644 index 0000000..7f7a4ea Binary files /dev/null and b/.git/objects/57/f92a438a038a58073f78d676d69426de044cc8 differ diff --git a/.git/objects/57/fcb57f4930340760db321ead6827f7ac39a835 b/.git/objects/57/fcb57f4930340760db321ead6827f7ac39a835 new file mode 100644 index 0000000..7c37163 Binary files /dev/null and b/.git/objects/57/fcb57f4930340760db321ead6827f7ac39a835 differ diff --git a/.git/objects/58/0e6e5a153e4234bd20fcb00c5e0c87013a0324 b/.git/objects/58/0e6e5a153e4234bd20fcb00c5e0c87013a0324 new file mode 100644 index 0000000..2b5fa2f Binary files /dev/null and b/.git/objects/58/0e6e5a153e4234bd20fcb00c5e0c87013a0324 differ diff --git a/.git/objects/58/161aa13b9738765a1b740008b527eef3a9fd0b b/.git/objects/58/161aa13b9738765a1b740008b527eef3a9fd0b new file mode 100644 index 0000000..4fc5b79 Binary files /dev/null and b/.git/objects/58/161aa13b9738765a1b740008b527eef3a9fd0b differ diff --git a/.git/objects/58/371668f01777e7528b93e5c1c0d0606997d3b9 b/.git/objects/58/371668f01777e7528b93e5c1c0d0606997d3b9 new file mode 100644 index 0000000..8d0b9fb Binary files /dev/null and b/.git/objects/58/371668f01777e7528b93e5c1c0d0606997d3b9 differ diff --git a/.git/objects/58/4b0d67e0b990f6c7f11f33eb8a9c0b3d5d9001 b/.git/objects/58/4b0d67e0b990f6c7f11f33eb8a9c0b3d5d9001 new file mode 100644 index 0000000..5d4ea0e Binary files /dev/null and b/.git/objects/58/4b0d67e0b990f6c7f11f33eb8a9c0b3d5d9001 differ diff --git a/.git/objects/58/53a10d4d5c7f6ab2a4212ad4c643b4117d240e b/.git/objects/58/53a10d4d5c7f6ab2a4212ad4c643b4117d240e new file mode 100644 index 0000000..a514743 Binary files /dev/null and b/.git/objects/58/53a10d4d5c7f6ab2a4212ad4c643b4117d240e differ diff --git a/.git/objects/58/5476a06e49ec62b3bda34d9f8d721d9fcb9bdd b/.git/objects/58/5476a06e49ec62b3bda34d9f8d721d9fcb9bdd new file mode 100644 index 0000000..72269cc Binary files /dev/null and b/.git/objects/58/5476a06e49ec62b3bda34d9f8d721d9fcb9bdd differ diff --git a/.git/objects/58/75da01a70acc421a9dd62d2b17d14f81b29853 b/.git/objects/58/75da01a70acc421a9dd62d2b17d14f81b29853 new file mode 100644 index 0000000..628ad74 --- /dev/null +++ b/.git/objects/58/75da01a70acc421a9dd62d2b17d14f81b29853 @@ -0,0 +1,4 @@ +x%AN0EYcN&BE-N0uƉQbG67cH76γPa3BM +5V6bҰ#m\oX(q5j!Mt]ܷVS1&xFƉ|+ISyJt4İ6ίt` + {β>&9|?N4msy]|+:E|g +4pz."i̷ Q̸ه(DJW^[fF \ No newline at end of file diff --git a/.git/objects/58/7c85f20cab57f875df3bf3f7eb04a0ae0a81e1 b/.git/objects/58/7c85f20cab57f875df3bf3f7eb04a0ae0a81e1 new file mode 100644 index 0000000..dd29ed9 Binary files /dev/null and b/.git/objects/58/7c85f20cab57f875df3bf3f7eb04a0ae0a81e1 differ diff --git a/.git/objects/58/7c866e163c658b2de9e0fcf70cb1a8c8df965d b/.git/objects/58/7c866e163c658b2de9e0fcf70cb1a8c8df965d new file mode 100644 index 0000000..049c92a Binary files /dev/null and b/.git/objects/58/7c866e163c658b2de9e0fcf70cb1a8c8df965d differ diff --git a/.git/objects/58/a490baa2e36698c936dec0bf455bad3d299144 b/.git/objects/58/a490baa2e36698c936dec0bf455bad3d299144 new file mode 100644 index 0000000..d08600e --- /dev/null +++ b/.git/objects/58/a490baa2e36698c936dec0bf455bad3d299144 @@ -0,0 +1,2 @@ +xNKj0ڧxRJJv(OO,fbY ckj }j&g-#R2*>hfQk[!W_)7pi" +g%V0q%9 <ͥB7UJX(oʹwf{D)>bY_ .rixfw;sM|z>/:\HaԕR /L[|ZW \ No newline at end of file diff --git a/.git/objects/58/cb715261c8c8ddee166e47296230dce0bf1038 b/.git/objects/58/cb715261c8c8ddee166e47296230dce0bf1038 new file mode 100644 index 0000000..340fda5 Binary files /dev/null and b/.git/objects/58/cb715261c8c8ddee166e47296230dce0bf1038 differ diff --git a/.git/objects/58/e23dcc765003f0b5977c752e431cf4aac09972 b/.git/objects/58/e23dcc765003f0b5977c752e431cf4aac09972 new file mode 100644 index 0000000..6e45aa2 Binary files /dev/null and b/.git/objects/58/e23dcc765003f0b5977c752e431cf4aac09972 differ diff --git a/.git/objects/58/ef8e62e55b740e8d97ca164289f2f6cd0096da b/.git/objects/58/ef8e62e55b740e8d97ca164289f2f6cd0096da new file mode 100644 index 0000000..a39a53e --- /dev/null +++ b/.git/objects/58/ef8e62e55b740e8d97ca164289f2f6cd0096da @@ -0,0 +1,2 @@ +xEON uݯ{c53ĝn \$&ƙ?sY'&N={\I)6ݵJdGRJ{C;p5rdC`;c܀97㨜di +iAi}[K.=Ux,x])Wʹ4Tw%=%{&5V 3\#.[?ϱ'ٍB[ݾ6si/PZ,M:] \ No newline at end of file diff --git a/.git/objects/59/197773379c1332865922f650e6048e0ac8e8b1 b/.git/objects/59/197773379c1332865922f650e6048e0ac8e8b1 new file mode 100644 index 0000000..017b1db Binary files /dev/null and b/.git/objects/59/197773379c1332865922f650e6048e0ac8e8b1 differ diff --git a/.git/objects/59/1cf938b52f4ac74b1fb0a259346e776ce02ba1 b/.git/objects/59/1cf938b52f4ac74b1fb0a259346e776ce02ba1 new file mode 100644 index 0000000..a1a0594 --- /dev/null +++ b/.git/objects/59/1cf938b52f4ac74b1fb0a259346e776ce02ba1 @@ -0,0 +1,4 @@ +xMn }W*@7]t=!F"7+Ϻt +$껺2(-Oc? +"UVz? !GGӌ(VN-( +Tz̤z0h]W8DQrsspϏ5qGcH|>J+et&oK͞9mG_;Ęߡp乆tRFאSC#7hO](/j \ No newline at end of file diff --git a/.git/objects/59/3c0d2a2e0fd617b825e4fc4bb2605dbb2695a5 b/.git/objects/59/3c0d2a2e0fd617b825e4fc4bb2605dbb2695a5 new file mode 100644 index 0000000..8aaa174 Binary files /dev/null and b/.git/objects/59/3c0d2a2e0fd617b825e4fc4bb2605dbb2695a5 differ diff --git a/.git/objects/59/49294195b100c20c95803107f552ebdae7a1be b/.git/objects/59/49294195b100c20c95803107f552ebdae7a1be new file mode 100644 index 0000000..c3462d4 Binary files /dev/null and b/.git/objects/59/49294195b100c20c95803107f552ebdae7a1be differ diff --git a/.git/objects/59/495a1df85eb97137b305208f5c4f3092d0f1e9 b/.git/objects/59/495a1df85eb97137b305208f5c4f3092d0f1e9 new file mode 100644 index 0000000..52aa38f Binary files /dev/null and b/.git/objects/59/495a1df85eb97137b305208f5c4f3092d0f1e9 differ diff --git a/.git/objects/59/620cdfe80218d1e3fcfa99438fac25279c8b9a b/.git/objects/59/620cdfe80218d1e3fcfa99438fac25279c8b9a new file mode 100644 index 0000000..38eb2fd Binary files /dev/null and b/.git/objects/59/620cdfe80218d1e3fcfa99438fac25279c8b9a differ diff --git a/.git/objects/59/72e9e015dc054605dd0a1788014b30469256a8 b/.git/objects/59/72e9e015dc054605dd0a1788014b30469256a8 new file mode 100644 index 0000000..2cfec6d Binary files /dev/null and b/.git/objects/59/72e9e015dc054605dd0a1788014b30469256a8 differ diff --git a/.git/objects/59/919c9af5d6c48c278920f879b2ac42c5f31224 b/.git/objects/59/919c9af5d6c48c278920f879b2ac42c5f31224 new file mode 100644 index 0000000..484104e Binary files /dev/null and b/.git/objects/59/919c9af5d6c48c278920f879b2ac42c5f31224 differ diff --git a/.git/objects/59/f2640ae6be5350bd1b7945ff0b07dc9b620e81 b/.git/objects/59/f2640ae6be5350bd1b7945ff0b07dc9b620e81 new file mode 100644 index 0000000..07f32a4 Binary files /dev/null and b/.git/objects/59/f2640ae6be5350bd1b7945ff0b07dc9b620e81 differ diff --git a/.git/objects/5a/31b9d5c8c301c4d78285f7ef77f045ca80fc16 b/.git/objects/5a/31b9d5c8c301c4d78285f7ef77f045ca80fc16 new file mode 100644 index 0000000..7483457 --- /dev/null +++ b/.git/objects/5a/31b9d5c8c301c4d78285f7ef77f045ca80fc16 @@ -0,0 +1 @@ +x-N0D#NkNbtB 6&q1,D5})_dfЂ#5J4u4ζT6S8(l9V\o RvD֣k]CGYR?):mZk?9g,ԓ4ќɦBވN)(ݥyY5"m3ZpmUowc) {p[Ꚑ>0d-ozڶ[*n~Uf \ No newline at end of file diff --git a/.git/objects/5a/989bd8c5f89f8ab2e62d67d900d9c42b67e0ce b/.git/objects/5a/989bd8c5f89f8ab2e62d67d900d9c42b67e0ce new file mode 100644 index 0000000..2736ae0 Binary files /dev/null and b/.git/objects/5a/989bd8c5f89f8ab2e62d67d900d9c42b67e0ce differ diff --git a/.git/objects/5a/9e078df620ab1f29ace3f9f6f78ced726c762b b/.git/objects/5a/9e078df620ab1f29ace3f9f6f78ced726c762b new file mode 100644 index 0000000..5909b78 Binary files /dev/null and b/.git/objects/5a/9e078df620ab1f29ace3f9f6f78ced726c762b differ diff --git a/.git/objects/5a/a648f8d0bf1227e30bc227275696fb9596ffe9 b/.git/objects/5a/a648f8d0bf1227e30bc227275696fb9596ffe9 new file mode 100644 index 0000000..d962007 Binary files /dev/null and b/.git/objects/5a/a648f8d0bf1227e30bc227275696fb9596ffe9 differ diff --git a/.git/objects/5a/cc64052fb5b13a490e9d9d251e77995473d78a b/.git/objects/5a/cc64052fb5b13a490e9d9d251e77995473d78a new file mode 100644 index 0000000..8533230 Binary files /dev/null and b/.git/objects/5a/cc64052fb5b13a490e9d9d251e77995473d78a differ diff --git a/.git/objects/5a/e587c11326bc06f45c89eb764d6f07c2120017 b/.git/objects/5a/e587c11326bc06f45c89eb764d6f07c2120017 new file mode 100644 index 0000000..c6f462b Binary files /dev/null and b/.git/objects/5a/e587c11326bc06f45c89eb764d6f07c2120017 differ diff --git a/.git/objects/5a/fa0b5b7efd46b80aa78a76d7af7cc7164afdac b/.git/objects/5a/fa0b5b7efd46b80aa78a76d7af7cc7164afdac new file mode 100644 index 0000000..e6eb7ed Binary files /dev/null and b/.git/objects/5a/fa0b5b7efd46b80aa78a76d7af7cc7164afdac differ diff --git a/.git/objects/5a/fa1598df01487ce37b022bbdbb30eb73b2dcfb b/.git/objects/5a/fa1598df01487ce37b022bbdbb30eb73b2dcfb new file mode 100644 index 0000000..9310385 Binary files /dev/null and b/.git/objects/5a/fa1598df01487ce37b022bbdbb30eb73b2dcfb differ diff --git a/.git/objects/5b/041cb2818f65f972013393cfdbfb4c96f208bc b/.git/objects/5b/041cb2818f65f972013393cfdbfb4c96f208bc new file mode 100644 index 0000000..ea1258d Binary files /dev/null and b/.git/objects/5b/041cb2818f65f972013393cfdbfb4c96f208bc differ diff --git a/.git/objects/5b/3797e1e33312338c377d639e646927f7ca2bf1 b/.git/objects/5b/3797e1e33312338c377d639e646927f7ca2bf1 new file mode 100644 index 0000000..278fc34 Binary files /dev/null and b/.git/objects/5b/3797e1e33312338c377d639e646927f7ca2bf1 differ diff --git a/.git/objects/5b/3a80a74707cbd10860a45f6997e9cefcef1522 b/.git/objects/5b/3a80a74707cbd10860a45f6997e9cefcef1522 new file mode 100644 index 0000000..620d421 Binary files /dev/null and b/.git/objects/5b/3a80a74707cbd10860a45f6997e9cefcef1522 differ diff --git a/.git/objects/5b/3bde22109cfb8deda24db3243ccb5cd18adfab b/.git/objects/5b/3bde22109cfb8deda24db3243ccb5cd18adfab new file mode 100644 index 0000000..092f9d7 --- /dev/null +++ b/.git/objects/5b/3bde22109cfb8deda24db3243ccb5cd18adfab @@ -0,0 +1,2 @@ +xKN0DYGB&is6L2JlxFs1l_Ъ$4{-zPM))ĪOHd617gQtmKpr ++dYxE^)3K?q_XGZuw1LAgT7Z3neMPe~||6("/e7 \ No newline at end of file diff --git a/.git/objects/5b/a0f54effc24c67c2f5d7466def971ac7fba89d b/.git/objects/5b/a0f54effc24c67c2f5d7466def971ac7fba89d new file mode 100644 index 0000000..5d4728d Binary files /dev/null and b/.git/objects/5b/a0f54effc24c67c2f5d7466def971ac7fba89d differ diff --git a/.git/objects/5b/d1bef2f753158fc5ac682208ae98d397ac0954 b/.git/objects/5b/d1bef2f753158fc5ac682208ae98d397ac0954 new file mode 100644 index 0000000..c032d59 Binary files /dev/null and b/.git/objects/5b/d1bef2f753158fc5ac682208ae98d397ac0954 differ diff --git a/.git/objects/5b/ebf7df14e248b86baa77ffa4bf9a966c36ab61 b/.git/objects/5b/ebf7df14e248b86baa77ffa4bf9a966c36ab61 new file mode 100644 index 0000000..d36ed17 Binary files /dev/null and b/.git/objects/5b/ebf7df14e248b86baa77ffa4bf9a966c36ab61 differ diff --git a/.git/objects/5b/fd1be79e79a44693beeae1e8ce0102000b3f5c b/.git/objects/5b/fd1be79e79a44693beeae1e8ce0102000b3f5c new file mode 100644 index 0000000..1d13a1e Binary files /dev/null and b/.git/objects/5b/fd1be79e79a44693beeae1e8ce0102000b3f5c differ diff --git a/.git/objects/5c/01fd1c1f2e0f15e0ba4e9b80a63b3a1cd2cea9 b/.git/objects/5c/01fd1c1f2e0f15e0ba4e9b80a63b3a1cd2cea9 new file mode 100644 index 0000000..0780312 Binary files /dev/null and b/.git/objects/5c/01fd1c1f2e0f15e0ba4e9b80a63b3a1cd2cea9 differ diff --git a/.git/objects/5c/2f379b195d8abb75bed764910e79fb576acc6e b/.git/objects/5c/2f379b195d8abb75bed764910e79fb576acc6e new file mode 100644 index 0000000..a705664 Binary files /dev/null and b/.git/objects/5c/2f379b195d8abb75bed764910e79fb576acc6e differ diff --git a/.git/objects/5c/40b91fdc18ccb7c15e3cbb5ffb816d7570a27e b/.git/objects/5c/40b91fdc18ccb7c15e3cbb5ffb816d7570a27e new file mode 100644 index 0000000..36e4af8 Binary files /dev/null and b/.git/objects/5c/40b91fdc18ccb7c15e3cbb5ffb816d7570a27e differ diff --git a/.git/objects/5c/5d97c4bae1ab08f19f23e15615dcce785cec52 b/.git/objects/5c/5d97c4bae1ab08f19f23e15615dcce785cec52 new file mode 100644 index 0000000..a083fe8 Binary files /dev/null and b/.git/objects/5c/5d97c4bae1ab08f19f23e15615dcce785cec52 differ diff --git a/.git/objects/5c/6b3bb45ede3a31b0c388dd5decb3bb2b1ebb66 b/.git/objects/5c/6b3bb45ede3a31b0c388dd5decb3bb2b1ebb66 new file mode 100644 index 0000000..7c64a80 --- /dev/null +++ b/.git/objects/5c/6b3bb45ede3a31b0c388dd5decb3bb2b1ebb66 @@ -0,0 +1 @@ +x-MN0Yo%i~ b BkM$z3\2bgl,ڻ֢R\zdP;X1oZk;t͊"zej-w$3vKUƸ: O3}a54^(wT{MG$ 8\Zs+\ g~ףyʡK#F&8os '?r)[x`%xV3J qJB͵4z_^' \ No newline at end of file diff --git a/.git/objects/5c/91961d12b88a9ea6952aedaa792b29f286bb04 b/.git/objects/5c/91961d12b88a9ea6952aedaa792b29f286bb04 new file mode 100644 index 0000000..595cdf2 Binary files /dev/null and b/.git/objects/5c/91961d12b88a9ea6952aedaa792b29f286bb04 differ diff --git a/.git/objects/5c/935fb95b9fb4be011c54d641f83b48000c3b57 b/.git/objects/5c/935fb95b9fb4be011c54d641f83b48000c3b57 new file mode 100644 index 0000000..d5da99c Binary files /dev/null and b/.git/objects/5c/935fb95b9fb4be011c54d641f83b48000c3b57 differ diff --git a/.git/objects/5c/96a586a731727f1d9aa2538270d9129934243f b/.git/objects/5c/96a586a731727f1d9aa2538270d9129934243f new file mode 100644 index 0000000..ed10259 Binary files /dev/null and b/.git/objects/5c/96a586a731727f1d9aa2538270d9129934243f differ diff --git a/.git/objects/5c/ce3b1c5f5252209c5707d66785928a1a6be372 b/.git/objects/5c/ce3b1c5f5252209c5707d66785928a1a6be372 new file mode 100644 index 0000000..972ad54 --- /dev/null +++ b/.git/objects/5c/ce3b1c5f5252209c5707d66785928a1a6be372 @@ -0,0 +1,2 @@ +xMj0)f_GV(%P(=HنX + ͲŢC{񅲮KKE?8eLj8H$VH,nT978houT& rԎS=j,eJIRʿ#WZB} ?y7~R g<<pVS UM/N£BTt]9-1ML.ږ_oFЇ^ᓩ\1Kک!GbH&8rGa \ No newline at end of file diff --git a/.git/objects/5e/2484fdc0cd3bade88043fbfe019e03e7315568 b/.git/objects/5e/2484fdc0cd3bade88043fbfe019e03e7315568 new file mode 100644 index 0000000..102bbaf Binary files /dev/null and b/.git/objects/5e/2484fdc0cd3bade88043fbfe019e03e7315568 differ diff --git a/.git/objects/5e/8fd574028300da4a381061e3df0ae6e6d1463a b/.git/objects/5e/8fd574028300da4a381061e3df0ae6e6d1463a new file mode 100644 index 0000000..09ac02f Binary files /dev/null and b/.git/objects/5e/8fd574028300da4a381061e3df0ae6e6d1463a differ diff --git a/.git/objects/5e/93891bdcdbb9c86c5c07d0be6f03aea388ea61 b/.git/objects/5e/93891bdcdbb9c86c5c07d0be6f03aea388ea61 new file mode 100644 index 0000000..7f7bd08 Binary files /dev/null and b/.git/objects/5e/93891bdcdbb9c86c5c07d0be6f03aea388ea61 differ diff --git a/.git/objects/5e/a8ca240864e0570f1d91c79b66738a716a54d1 b/.git/objects/5e/a8ca240864e0570f1d91c79b66738a716a54d1 new file mode 100644 index 0000000..290ec74 Binary files /dev/null and b/.git/objects/5e/a8ca240864e0570f1d91c79b66738a716a54d1 differ diff --git a/.git/objects/5e/e8bf07a41c2e6f56736e82ee0533bf0be919a6 b/.git/objects/5e/e8bf07a41c2e6f56736e82ee0533bf0be919a6 new file mode 100644 index 0000000..d2f8c73 Binary files /dev/null and b/.git/objects/5e/e8bf07a41c2e6f56736e82ee0533bf0be919a6 differ diff --git a/.git/objects/5e/ee2d389471e79a027287eaec93611e50ba9cff b/.git/objects/5e/ee2d389471e79a027287eaec93611e50ba9cff new file mode 100644 index 0000000..e51a3ee Binary files /dev/null and b/.git/objects/5e/ee2d389471e79a027287eaec93611e50ba9cff differ diff --git a/.git/objects/5e/f81380877f6f5b840251a85f0a11f8ee6a9404 b/.git/objects/5e/f81380877f6f5b840251a85f0a11f8ee6a9404 new file mode 100644 index 0000000..37f9fb2 Binary files /dev/null and b/.git/objects/5e/f81380877f6f5b840251a85f0a11f8ee6a9404 differ diff --git a/.git/objects/5e/fb42a05a1859f3d590f908b8a727908a1d25d7 b/.git/objects/5e/fb42a05a1859f3d590f908b8a727908a1d25d7 new file mode 100644 index 0000000..7cf5d01 Binary files /dev/null and b/.git/objects/5e/fb42a05a1859f3d590f908b8a727908a1d25d7 differ diff --git a/.git/objects/5f/1c4cdad376817805b81a1cc0ae860ff8cec0ec b/.git/objects/5f/1c4cdad376817805b81a1cc0ae860ff8cec0ec new file mode 100644 index 0000000..78da0f8 Binary files /dev/null and b/.git/objects/5f/1c4cdad376817805b81a1cc0ae860ff8cec0ec differ diff --git a/.git/objects/5f/486e740691152c4393549a669b015783448800 b/.git/objects/5f/486e740691152c4393549a669b015783448800 new file mode 100644 index 0000000..efd8b9a Binary files /dev/null and b/.git/objects/5f/486e740691152c4393549a669b015783448800 differ diff --git a/.git/objects/5f/4ce4de7a145a71f57c635063fdb45d1167772a b/.git/objects/5f/4ce4de7a145a71f57c635063fdb45d1167772a new file mode 100644 index 0000000..d567bca Binary files /dev/null and b/.git/objects/5f/4ce4de7a145a71f57c635063fdb45d1167772a differ diff --git a/.git/objects/5f/790f141fb9a4deaa7d880c38dffcb6409faca4 b/.git/objects/5f/790f141fb9a4deaa7d880c38dffcb6409faca4 new file mode 100644 index 0000000..25049f2 Binary files /dev/null and b/.git/objects/5f/790f141fb9a4deaa7d880c38dffcb6409faca4 differ diff --git a/.git/objects/5f/b701dd2274d75853c7c8fecb12946d7adef232 b/.git/objects/5f/b701dd2274d75853c7c8fecb12946d7adef232 new file mode 100644 index 0000000..6976d4b Binary files /dev/null and b/.git/objects/5f/b701dd2274d75853c7c8fecb12946d7adef232 differ diff --git a/.git/objects/5f/baddd9f1f9372467cc9cedeb2035444a038565 b/.git/objects/5f/baddd9f1f9372467cc9cedeb2035444a038565 new file mode 100644 index 0000000..0a0a4be --- /dev/null +++ b/.git/objects/5f/baddd9f1f9372467cc9cedeb2035444a038565 @@ -0,0 +1 @@ +x-MN0YGDc;IU"N0ǍĎ 7cŰ鹼,A "(4쥖d` AoGaljV,4^4R;%Mކvc,0l+Bwr<x.x(wIkz≦Z/9ZGJvVh4 %DS+y*q\.?qy_گ5P)i6~AӒ? !W7.s &W`r /_b \ No newline at end of file diff --git a/.git/objects/5f/c5e4dc6004452029e5e45a8e8d6138bd2b20d5 b/.git/objects/5f/c5e4dc6004452029e5e45a8e8d6138bd2b20d5 new file mode 100644 index 0000000..6c3300f Binary files /dev/null and b/.git/objects/5f/c5e4dc6004452029e5e45a8e8d6138bd2b20d5 differ diff --git a/.git/objects/60/1fc11101b4cde740259c8f371cc53a66718059 b/.git/objects/60/1fc11101b4cde740259c8f371cc53a66718059 new file mode 100644 index 0000000..8589484 Binary files /dev/null and b/.git/objects/60/1fc11101b4cde740259c8f371cc53a66718059 differ diff --git a/.git/objects/60/49b2c2bfb8d4f0ab2f6a0c5bee89c594ef1975 b/.git/objects/60/49b2c2bfb8d4f0ab2f6a0c5bee89c594ef1975 new file mode 100644 index 0000000..b364a7f Binary files /dev/null and b/.git/objects/60/49b2c2bfb8d4f0ab2f6a0c5bee89c594ef1975 differ diff --git a/.git/objects/60/558942984e86f5d63eeb295a8024ca30131e2c b/.git/objects/60/558942984e86f5d63eeb295a8024ca30131e2c new file mode 100644 index 0000000..90b34b7 Binary files /dev/null and b/.git/objects/60/558942984e86f5d63eeb295a8024ca30131e2c differ diff --git a/.git/objects/60/7b1305772ab820953e3529a5e1a3785f861e1b b/.git/objects/60/7b1305772ab820953e3529a5e1a3785f861e1b new file mode 100644 index 0000000..64492b0 Binary files /dev/null and b/.git/objects/60/7b1305772ab820953e3529a5e1a3785f861e1b differ diff --git a/.git/objects/61/1b83b8d8f3a8450133e4605271f76f68f42525 b/.git/objects/61/1b83b8d8f3a8450133e4605271f76f68f42525 new file mode 100644 index 0000000..f50f9b8 Binary files /dev/null and b/.git/objects/61/1b83b8d8f3a8450133e4605271f76f68f42525 differ diff --git a/.git/objects/61/4a1c937b04a14e609464a2620a3452a266bd34 b/.git/objects/61/4a1c937b04a14e609464a2620a3452a266bd34 new file mode 100644 index 0000000..7a3b9e3 Binary files /dev/null and b/.git/objects/61/4a1c937b04a14e609464a2620a3452a266bd34 differ diff --git a/.git/objects/61/56d1aee3a497dc21b487bd735f85d99522135a b/.git/objects/61/56d1aee3a497dc21b487bd735f85d99522135a new file mode 100644 index 0000000..a1505ba Binary files /dev/null and b/.git/objects/61/56d1aee3a497dc21b487bd735f85d99522135a differ diff --git a/.git/objects/61/65781bbd9a520efc97976f3712e6c40d2779cd b/.git/objects/61/65781bbd9a520efc97976f3712e6c40d2779cd new file mode 100644 index 0000000..d8fa5e1 Binary files /dev/null and b/.git/objects/61/65781bbd9a520efc97976f3712e6c40d2779cd differ diff --git a/.git/objects/61/89f66980baff9477b708164df31766fe000b9a b/.git/objects/61/89f66980baff9477b708164df31766fe000b9a new file mode 100644 index 0000000..ed0f233 Binary files /dev/null and b/.git/objects/61/89f66980baff9477b708164df31766fe000b9a differ diff --git a/.git/objects/61/a6d93b42280005dcca986763b96c3f691f729a b/.git/objects/61/a6d93b42280005dcca986763b96c3f691f729a new file mode 100644 index 0000000..0dc309f Binary files /dev/null and b/.git/objects/61/a6d93b42280005dcca986763b96c3f691f729a differ diff --git a/.git/objects/61/d2291e3beb2e39d345b516af7f0f5b6be4489e b/.git/objects/61/d2291e3beb2e39d345b516af7f0f5b6be4489e new file mode 100644 index 0000000..b98afa4 --- /dev/null +++ b/.git/objects/61/d2291e3beb2e39d345b516af7f0f5b6be4489e @@ -0,0 +1,4 @@ +x%MN0YokP ĢH ^$(+fvoFҲLW%A/v Z9)):/% \8iϭ9cX`q:ty^ҨqK1 +)L=ex\RiXF+)^Z;Z!gn]ØN)?qy[ڏԒR0UMɕF( +C +RyZ_6~!h\ \ No newline at end of file diff --git a/.git/objects/61/e6b6b5189a4cae4bd3ff6ea7eba6f497907574 b/.git/objects/61/e6b6b5189a4cae4bd3ff6ea7eba6f497907574 new file mode 100644 index 0000000..c628540 Binary files /dev/null and b/.git/objects/61/e6b6b5189a4cae4bd3ff6ea7eba6f497907574 differ diff --git a/.git/objects/61/ea5e8200838e73a1c937dbc1129754bbad9a93 b/.git/objects/61/ea5e8200838e73a1c937dbc1129754bbad9a93 new file mode 100644 index 0000000..9f3dfbc Binary files /dev/null and b/.git/objects/61/ea5e8200838e73a1c937dbc1129754bbad9a93 differ diff --git a/.git/objects/61/ed570790ceb7e237cc00292824dc2dc079f64d b/.git/objects/61/ed570790ceb7e237cc00292824dc2dc079f64d new file mode 100644 index 0000000..b7da586 Binary files /dev/null and b/.git/objects/61/ed570790ceb7e237cc00292824dc2dc079f64d differ diff --git a/.git/objects/61/ee50d4a6996c5bacc1a9ab16e0ac6410c6efad b/.git/objects/61/ee50d4a6996c5bacc1a9ab16e0ac6410c6efad new file mode 100644 index 0000000..3337fc0 Binary files /dev/null and b/.git/objects/61/ee50d4a6996c5bacc1a9ab16e0ac6410c6efad differ diff --git a/.git/objects/61/f5397a9d9e389f3a1e610600abaff67c9aaa42 b/.git/objects/61/f5397a9d9e389f3a1e610600abaff67c9aaa42 new file mode 100644 index 0000000..d079d79 Binary files /dev/null and b/.git/objects/61/f5397a9d9e389f3a1e610600abaff67c9aaa42 differ diff --git a/.git/objects/61/f66bb3db5ad7c654369ddea878f4131fc69272 b/.git/objects/61/f66bb3db5ad7c654369ddea878f4131fc69272 new file mode 100644 index 0000000..c6fe7c7 Binary files /dev/null and b/.git/objects/61/f66bb3db5ad7c654369ddea878f4131fc69272 differ diff --git a/.git/objects/62/42978f1c2ae9ccb76143652a571be4cd5ade0a b/.git/objects/62/42978f1c2ae9ccb76143652a571be4cd5ade0a new file mode 100644 index 0000000..3fb7c1c Binary files /dev/null and b/.git/objects/62/42978f1c2ae9ccb76143652a571be4cd5ade0a differ diff --git a/.git/objects/62/4b7b1fe7479c72084b1f457a7df25f00c105dc b/.git/objects/62/4b7b1fe7479c72084b1f457a7df25f00c105dc new file mode 100644 index 0000000..7831346 Binary files /dev/null and b/.git/objects/62/4b7b1fe7479c72084b1f457a7df25f00c105dc differ diff --git a/.git/objects/62/8b77d5780f6e9cf8e7fd8b1e0331ed978d5ead b/.git/objects/62/8b77d5780f6e9cf8e7fd8b1e0331ed978d5ead new file mode 100644 index 0000000..12c2bcc Binary files /dev/null and b/.git/objects/62/8b77d5780f6e9cf8e7fd8b1e0331ed978d5ead differ diff --git a/.git/objects/62/8bc7c7673d57e4f15f91c53a71400641705b48 b/.git/objects/62/8bc7c7673d57e4f15f91c53a71400641705b48 new file mode 100644 index 0000000..180f040 --- /dev/null +++ b/.git/objects/62/8bc7c7673d57e4f15f91c53a71400641705b48 @@ -0,0 +1 @@ +x-Kj0D)zb$Ya3dlr- YfeE, qۖҪ|Zd]꾗BI4Z[}gK)Pyacy5vF"W8{Һ5-ã1}/ 2|,C\)wkz+3͵Gb8!n hւxsV]ۜc0u ckiiIK%9>vLi{؏b.0VqY&OY9]1 \ No newline at end of file diff --git a/.git/objects/62/9305708b1a5d1b3be10059035af6e43839610a b/.git/objects/62/9305708b1a5d1b3be10059035af6e43839610a new file mode 100644 index 0000000..cacd23b Binary files /dev/null and b/.git/objects/62/9305708b1a5d1b3be10059035af6e43839610a differ diff --git a/.git/objects/62/97b686d4162117bfa44f6d36805d19e65a02a3 b/.git/objects/62/97b686d4162117bfa44f6d36805d19e65a02a3 new file mode 100644 index 0000000..e06ee79 Binary files /dev/null and b/.git/objects/62/97b686d4162117bfa44f6d36805d19e65a02a3 differ diff --git a/.git/objects/62/b1c7406db3f3a623379dfa8fb3bd7feab8050e b/.git/objects/62/b1c7406db3f3a623379dfa8fb3bd7feab8050e new file mode 100644 index 0000000..7e06ee9 Binary files /dev/null and b/.git/objects/62/b1c7406db3f3a623379dfa8fb3bd7feab8050e differ diff --git a/.git/objects/62/e3a98fca06912ea3f02f203797fe1fa14691c1 b/.git/objects/62/e3a98fca06912ea3f02f203797fe1fa14691c1 new file mode 100644 index 0000000..9060587 --- /dev/null +++ b/.git/objects/62/e3a98fca06912ea3f02f203797fe1fa14691c1 @@ -0,0 +1 @@ +x%MN0YQ'NBXÆ=Rbz3\'=9Pz(%ᴭv7Mä4\˝U`Xn%Io-KV1ĖM[S3&'G^ጻ{)#{$8x;4?]'G!ww^VxMyg?6pdTXxfWא DpX8R>6ւ?j Y \ No newline at end of file diff --git a/.git/objects/62/fb0e7ed89662f87372cedf8df240b56d889af3 b/.git/objects/62/fb0e7ed89662f87372cedf8df240b56d889af3 new file mode 100644 index 0000000..f5e3798 Binary files /dev/null and b/.git/objects/62/fb0e7ed89662f87372cedf8df240b56d889af3 differ diff --git a/.git/objects/63/354919e93700149c6fd47e9a93191113284de1 b/.git/objects/63/354919e93700149c6fd47e9a93191113284de1 new file mode 100644 index 0000000..9f0aad9 Binary files /dev/null and b/.git/objects/63/354919e93700149c6fd47e9a93191113284de1 differ diff --git a/.git/objects/63/554bf917bdb16b6c3451062cda116d6957485d b/.git/objects/63/554bf917bdb16b6c3451062cda116d6957485d new file mode 100644 index 0000000..d55d098 Binary files /dev/null and b/.git/objects/63/554bf917bdb16b6c3451062cda116d6957485d differ diff --git a/.git/objects/63/61b26cb206e1d973987aec585931d852d9dab1 b/.git/objects/63/61b26cb206e1d973987aec585931d852d9dab1 new file mode 100644 index 0000000..83e7a7e --- /dev/null +++ b/.git/objects/63/61b26cb206e1d973987aec585931d852d9dab1 @@ -0,0 +1,2 @@ +x-MN0YGDc;T"e Hq{.U\^XAP 3 %ĈJjǃs(E#JSEꠕs^ꉼ޸Q(NG +RfPu^{ty >~J Synӭwy}!&-A4kj]\\.;h{]NO8zVK{9=Ù>*٥rSk-Y \ No newline at end of file diff --git a/.git/objects/63/762543dc080e5216b4ee966d44c9b2a4aab28b b/.git/objects/63/762543dc080e5216b4ee966d44c9b2a4aab28b new file mode 100644 index 0000000..fe910c1 Binary files /dev/null and b/.git/objects/63/762543dc080e5216b4ee966d44c9b2a4aab28b differ diff --git a/.git/objects/63/82d9246a6dbe43c3ad4ab7b1cb4bfebecd2bb4 b/.git/objects/63/82d9246a6dbe43c3ad4ab7b1cb4bfebecd2bb4 new file mode 100644 index 0000000..4d4084a Binary files /dev/null and b/.git/objects/63/82d9246a6dbe43c3ad4ab7b1cb4bfebecd2bb4 differ diff --git a/.git/objects/63/85503a1c526d4d13ccc770bce74200826ecd6a b/.git/objects/63/85503a1c526d4d13ccc770bce74200826ecd6a new file mode 100644 index 0000000..58f6bed Binary files /dev/null and b/.git/objects/63/85503a1c526d4d13ccc770bce74200826ecd6a differ diff --git a/.git/objects/63/8e5ca8e626081652e65b7cdf66ae22ec119709 b/.git/objects/63/8e5ca8e626081652e65b7cdf66ae22ec119709 new file mode 100644 index 0000000..e0894e2 Binary files /dev/null and b/.git/objects/63/8e5ca8e626081652e65b7cdf66ae22ec119709 differ diff --git a/.git/objects/63/a42c5a2223105637f14d1eda78785939c13c20 b/.git/objects/63/a42c5a2223105637f14d1eda78785939c13c20 new file mode 100644 index 0000000..0122303 --- /dev/null +++ b/.git/objects/63/a42c5a2223105637f14d1eda78785939c13c20 @@ -0,0 +1,3 @@ +xN0 9)|Q%ڦ҄&qO%nh.M@dHK;CWGR(jEUH +>r?skө^(^_O<6 \ No newline at end of file diff --git a/.git/objects/63/a5e037675a7f1aed50b7c261c1f3329c33c43a b/.git/objects/63/a5e037675a7f1aed50b7c261c1f3329c33c43a new file mode 100644 index 0000000..9bfe8b7 Binary files /dev/null and b/.git/objects/63/a5e037675a7f1aed50b7c261c1f3329c33c43a differ diff --git a/.git/objects/63/cc86103f15135b91f17fc8896ce601928943de b/.git/objects/63/cc86103f15135b91f17fc8896ce601928943de new file mode 100644 index 0000000..2576c03 Binary files /dev/null and b/.git/objects/63/cc86103f15135b91f17fc8896ce601928943de differ diff --git a/.git/objects/63/cf2128a3ba7f69fa1bf6abe727357eec3e1f65 b/.git/objects/63/cf2128a3ba7f69fa1bf6abe727357eec3e1f65 new file mode 100644 index 0000000..666eb31 --- /dev/null +++ b/.git/objects/63/cf2128a3ba7f69fa1bf6abe727357eec3e1f65 @@ -0,0 +1,2 @@ +x%j0D{WH,%S=֫m $cm7 u34]3\s.XkYxqNѺTrPgh[gpqۿb8-++WAs~T,e39/PZQ \ No newline at end of file diff --git a/.git/objects/64/9af375dc5c35fc1e68fe8c40c2052a5753636a b/.git/objects/64/9af375dc5c35fc1e68fe8c40c2052a5753636a new file mode 100644 index 0000000..f2218b3 Binary files /dev/null and b/.git/objects/64/9af375dc5c35fc1e68fe8c40c2052a5753636a differ diff --git a/.git/objects/64/9b93b3c60dd78aeb9d2aaeb4770904cf1b4610 b/.git/objects/64/9b93b3c60dd78aeb9d2aaeb4770904cf1b4610 new file mode 100644 index 0000000..605f47a Binary files /dev/null and b/.git/objects/64/9b93b3c60dd78aeb9d2aaeb4770904cf1b4610 differ diff --git a/.git/objects/64/a9306d31e5b18879850fcdbd549f246753f04e b/.git/objects/64/a9306d31e5b18879850fcdbd549f246753f04e new file mode 100644 index 0000000..7152b08 Binary files /dev/null and b/.git/objects/64/a9306d31e5b18879850fcdbd549f246753f04e differ diff --git a/.git/objects/64/a970f9b8b0ae480cd03d08087989a9f602af17 b/.git/objects/64/a970f9b8b0ae480cd03d08087989a9f602af17 new file mode 100644 index 0000000..007d08e Binary files /dev/null and b/.git/objects/64/a970f9b8b0ae480cd03d08087989a9f602af17 differ diff --git a/.git/objects/64/afbb2fe67c801e7e7a66a40b910a8f07d3557e b/.git/objects/64/afbb2fe67c801e7e7a66a40b910a8f07d3557e new file mode 100644 index 0000000..6a9d8d9 Binary files /dev/null and b/.git/objects/64/afbb2fe67c801e7e7a66a40b910a8f07d3557e differ diff --git a/.git/objects/64/cd85218f15269dfb564ff840e5bcb19c5ebaaf b/.git/objects/64/cd85218f15269dfb564ff840e5bcb19c5ebaaf new file mode 100644 index 0000000..65b6dc9 Binary files /dev/null and b/.git/objects/64/cd85218f15269dfb564ff840e5bcb19c5ebaaf differ diff --git a/.git/objects/64/e103719a70813eb43e8a5ca6639b4465f8157a b/.git/objects/64/e103719a70813eb43e8a5ca6639b4465f8157a new file mode 100644 index 0000000..e08007a Binary files /dev/null and b/.git/objects/64/e103719a70813eb43e8a5ca6639b4465f8157a differ diff --git a/.git/objects/64/f3219c94e2d2806dd0ce866b0ad8e7917013c0 b/.git/objects/64/f3219c94e2d2806dd0ce866b0ad8e7917013c0 new file mode 100644 index 0000000..ca4d623 Binary files /dev/null and b/.git/objects/64/f3219c94e2d2806dd0ce866b0ad8e7917013c0 differ diff --git a/.git/objects/64/f3cc62939de94e35d86ad4bc676d468b340f54 b/.git/objects/64/f3cc62939de94e35d86ad4bc676d468b340f54 new file mode 100644 index 0000000..7c385d9 Binary files /dev/null and b/.git/objects/64/f3cc62939de94e35d86ad4bc676d468b340f54 differ diff --git a/.git/objects/65/0418231ce34a55c362b4b72d138de8dfd4a2f3 b/.git/objects/65/0418231ce34a55c362b4b72d138de8dfd4a2f3 new file mode 100644 index 0000000..f24d9d5 Binary files /dev/null and b/.git/objects/65/0418231ce34a55c362b4b72d138de8dfd4a2f3 differ diff --git a/.git/objects/65/08c7f430da1d37fa08b296357a50e19e3c0efd b/.git/objects/65/08c7f430da1d37fa08b296357a50e19e3c0efd new file mode 100644 index 0000000..6fb7d74 Binary files /dev/null and b/.git/objects/65/08c7f430da1d37fa08b296357a50e19e3c0efd differ diff --git a/.git/objects/65/0f5d7c4949c61564e6ac1ab16bd0dcb1e708fc b/.git/objects/65/0f5d7c4949c61564e6ac1ab16bd0dcb1e708fc new file mode 100644 index 0000000..f28947c --- /dev/null +++ b/.git/objects/65/0f5d7c4949c61564e6ac1ab16bd0dcb1e708fc @@ -0,0 +1,2 @@ +x-[n EUxHFL]N "DMJǺ>*Hja7i%<$Z;%H;2RX#џ 6,*8'أIH?a<9RԤPe<[:< ܎i^þx#9IA6#< -Dִrr1q} =9Jm>^` +?b֐!j?1 Cbr9̫Y \ No newline at end of file diff --git a/.git/objects/65/1f43273416a173c1006e850748b342ba925556 b/.git/objects/65/1f43273416a173c1006e850748b342ba925556 new file mode 100644 index 0000000..a90877f Binary files /dev/null and b/.git/objects/65/1f43273416a173c1006e850748b342ba925556 differ diff --git a/.git/objects/65/2ae012e24bcb1d1b8b6048cc5364b4c260d50c b/.git/objects/65/2ae012e24bcb1d1b8b6048cc5364b4c260d50c new file mode 100644 index 0000000..8d80caf Binary files /dev/null and b/.git/objects/65/2ae012e24bcb1d1b8b6048cc5364b4c260d50c differ diff --git a/.git/objects/65/56896797207ab16319f51244b86495455461a4 b/.git/objects/65/56896797207ab16319f51244b86495455461a4 new file mode 100644 index 0000000..b4dd653 Binary files /dev/null and b/.git/objects/65/56896797207ab16319f51244b86495455461a4 differ diff --git a/.git/objects/65/5a5b5333c669d185eb1927c12cebac6201abad b/.git/objects/65/5a5b5333c669d185eb1927c12cebac6201abad new file mode 100644 index 0000000..50709a3 Binary files /dev/null and b/.git/objects/65/5a5b5333c669d185eb1927c12cebac6201abad differ diff --git a/.git/objects/65/8056bd91693bfa87fdd0735b8034d3ab095c2f b/.git/objects/65/8056bd91693bfa87fdd0735b8034d3ab095c2f new file mode 100644 index 0000000..23b76c5 --- /dev/null +++ b/.git/objects/65/8056bd91693bfa87fdd0735b8034d3ab095c2f @@ -0,0 +1,2 @@ +x=N0`uH'qvH4=!"f\ vf4b޶38{p1z$;K8b1CKVb6:!Ml3Sԇx<ɵιoфBK̫(}AOڗ:cnh=)7Fv8 =[Rڅ6s?)y.]^Z9WI\@=s@;GPʎJ-ܢB~KyKˉGlr;}@;o*%NĜ-*PnT"@.,XHb:u?e \ No newline at end of file diff --git a/.git/objects/67/2ac8c2ab59a3b836b089e5951f77b6b77039e6 b/.git/objects/67/2ac8c2ab59a3b836b089e5951f77b6b77039e6 new file mode 100644 index 0000000..5a71df4 Binary files /dev/null and b/.git/objects/67/2ac8c2ab59a3b836b089e5951f77b6b77039e6 differ diff --git a/.git/objects/67/2adb9f432c9be508f42741c4e08ab78f58fa27 b/.git/objects/67/2adb9f432c9be508f42741c4e08ab78f58fa27 new file mode 100644 index 0000000..195a0b8 Binary files /dev/null and b/.git/objects/67/2adb9f432c9be508f42741c4e08ab78f58fa27 differ diff --git a/.git/objects/67/4c180b03117545dfef0d7023b42a72de1c0a2a b/.git/objects/67/4c180b03117545dfef0d7023b42a72de1c0a2a new file mode 100644 index 0000000..0dd7876 Binary files /dev/null and b/.git/objects/67/4c180b03117545dfef0d7023b42a72de1c0a2a differ diff --git a/.git/objects/67/89ec0ddf3b73cf58225b2fe6d90207c47694e9 b/.git/objects/67/89ec0ddf3b73cf58225b2fe6d90207c47694e9 new file mode 100644 index 0000000..90660b2 Binary files /dev/null and b/.git/objects/67/89ec0ddf3b73cf58225b2fe6d90207c47694e9 differ diff --git a/.git/objects/67/c888c4a52c0f00c4902a9e27e647a9140bb007 b/.git/objects/67/c888c4a52c0f00c4902a9e27e647a9140bb007 new file mode 100644 index 0000000..ede8919 Binary files /dev/null and b/.git/objects/67/c888c4a52c0f00c4902a9e27e647a9140bb007 differ diff --git a/.git/objects/67/ca2322880d90d7d33c6868fb48d76a3b740a1f b/.git/objects/67/ca2322880d90d7d33c6868fb48d76a3b740a1f new file mode 100644 index 0000000..2109274 Binary files /dev/null and b/.git/objects/67/ca2322880d90d7d33c6868fb48d76a3b740a1f differ diff --git a/.git/objects/68/08c187ebfd4c485b71d2eaf8ef02636966ab56 b/.git/objects/68/08c187ebfd4c485b71d2eaf8ef02636966ab56 new file mode 100644 index 0000000..f4e7c8b --- /dev/null +++ b/.git/objects/68/08c187ebfd4c485b71d2eaf8ef02636966ab56 @@ -0,0 +1,3 @@ +x-J0])^,kMa )>mr3 4IIRu̽/fwqL +WZLjb4 $ \,MBI=p!0Jt;fSHNpH8ݨH3:<29u?az@73iۖZC"]Ǝ v#Y샦n䨹rXk +6ڸAra XDÆ2 U8mi.>~seVR)O YGi 'J5խܥb3gx.s[-qځue \ No newline at end of file diff --git a/.git/objects/68/fb35dc5ebb942238d23caaefdc6c8f908403ee b/.git/objects/68/fb35dc5ebb942238d23caaefdc6c8f908403ee new file mode 100644 index 0000000..b57ef75 Binary files /dev/null and b/.git/objects/68/fb35dc5ebb942238d23caaefdc6c8f908403ee differ diff --git a/.git/objects/69/279798228df16f6423532bef5e860d0fbe99fb b/.git/objects/69/279798228df16f6423532bef5e860d0fbe99fb new file mode 100644 index 0000000..aa88f9b Binary files /dev/null and b/.git/objects/69/279798228df16f6423532bef5e860d0fbe99fb differ diff --git a/.git/objects/69/2c2abbfc79662934ad14743381a1ca27879bed b/.git/objects/69/2c2abbfc79662934ad14743381a1ca27879bed new file mode 100644 index 0000000..e491ad9 Binary files /dev/null and b/.git/objects/69/2c2abbfc79662934ad14743381a1ca27879bed differ diff --git a/.git/objects/69/3e6a6ba0c02ba24a381ae94906a99a12bcd0d6 b/.git/objects/69/3e6a6ba0c02ba24a381ae94906a99a12bcd0d6 new file mode 100644 index 0000000..49492fb Binary files /dev/null and b/.git/objects/69/3e6a6ba0c02ba24a381ae94906a99a12bcd0d6 differ diff --git a/.git/objects/69/64d6909228cd64df20ce55c120ec3b1a01e488 b/.git/objects/69/64d6909228cd64df20ce55c120ec3b1a01e488 new file mode 100644 index 0000000..93de441 Binary files /dev/null and b/.git/objects/69/64d6909228cd64df20ce55c120ec3b1a01e488 differ diff --git a/.git/objects/69/9d1f9fb05bab3bb168847fef097a248f4d7726 b/.git/objects/69/9d1f9fb05bab3bb168847fef097a248f4d7726 new file mode 100644 index 0000000..644a5ae Binary files /dev/null and b/.git/objects/69/9d1f9fb05bab3bb168847fef097a248f4d7726 differ diff --git a/.git/objects/69/a8503a881fab8572149bd8624a4de16431902d b/.git/objects/69/a8503a881fab8572149bd8624a4de16431902d new file mode 100644 index 0000000..b88279b Binary files /dev/null and b/.git/objects/69/a8503a881fab8572149bd8624a4de16431902d differ diff --git a/.git/objects/69/b14f58c75454c3fb52fe47a69a6f90f667dda1 b/.git/objects/69/b14f58c75454c3fb52fe47a69a6f90f667dda1 new file mode 100644 index 0000000..9f4e0e4 Binary files /dev/null and b/.git/objects/69/b14f58c75454c3fb52fe47a69a6f90f667dda1 differ diff --git a/.git/objects/69/c32f109bc275b24ce33f2f3905846d85ee0398 b/.git/objects/69/c32f109bc275b24ce33f2f3905846d85ee0398 new file mode 100644 index 0000000..16feef5 Binary files /dev/null and b/.git/objects/69/c32f109bc275b24ce33f2f3905846d85ee0398 differ diff --git a/.git/objects/69/c4517757384bbb56ee2b6b2acaa84980d0fb24 b/.git/objects/69/c4517757384bbb56ee2b6b2acaa84980d0fb24 new file mode 100644 index 0000000..68853b1 Binary files /dev/null and b/.git/objects/69/c4517757384bbb56ee2b6b2acaa84980d0fb24 differ diff --git a/.git/objects/69/d584ed85e1fba3285015d472136cfca5c8dca2 b/.git/objects/69/d584ed85e1fba3285015d472136cfca5c8dca2 new file mode 100644 index 0000000..82f459a Binary files /dev/null and b/.git/objects/69/d584ed85e1fba3285015d472136cfca5c8dca2 differ diff --git a/.git/objects/69/fc5d682856839d26a05681f6250ee732bc9d5c b/.git/objects/69/fc5d682856839d26a05681f6250ee732bc9d5c new file mode 100644 index 0000000..5320470 Binary files /dev/null and b/.git/objects/69/fc5d682856839d26a05681f6250ee732bc9d5c differ diff --git a/.git/objects/69/fd63da5e60a78af4b780e16d42f536d319f650 b/.git/objects/69/fd63da5e60a78af4b780e16d42f536d319f650 new file mode 100644 index 0000000..918e39b Binary files /dev/null and b/.git/objects/69/fd63da5e60a78af4b780e16d42f536d319f650 differ diff --git a/.git/objects/6a/1716a7171f0b12074e1ab1fa91bef11a0ea799 b/.git/objects/6a/1716a7171f0b12074e1ab1fa91bef11a0ea799 new file mode 100644 index 0000000..b4ac9ed Binary files /dev/null and b/.git/objects/6a/1716a7171f0b12074e1ab1fa91bef11a0ea799 differ diff --git a/.git/objects/6a/282f8c12828f14182175cd7c6c22806a507504 b/.git/objects/6a/282f8c12828f14182175cd7c6c22806a507504 new file mode 100644 index 0000000..0ad2b0d Binary files /dev/null and b/.git/objects/6a/282f8c12828f14182175cd7c6c22806a507504 differ diff --git a/.git/objects/6a/6f3c3e0b925fd500dbf2ee845a469e3fbbdc5e b/.git/objects/6a/6f3c3e0b925fd500dbf2ee845a469e3fbbdc5e new file mode 100644 index 0000000..a621bbe Binary files /dev/null and b/.git/objects/6a/6f3c3e0b925fd500dbf2ee845a469e3fbbdc5e differ diff --git a/.git/objects/6a/702161df94003a6e9f2d1a58912a65b5273541 b/.git/objects/6a/702161df94003a6e9f2d1a58912a65b5273541 new file mode 100644 index 0000000..e6986f6 Binary files /dev/null and b/.git/objects/6a/702161df94003a6e9f2d1a58912a65b5273541 differ diff --git a/.git/objects/6a/82a4fe3ab487d6b0c4e8b6ad2fb455bf19fc48 b/.git/objects/6a/82a4fe3ab487d6b0c4e8b6ad2fb455bf19fc48 new file mode 100644 index 0000000..62adbe6 --- /dev/null +++ b/.git/objects/6a/82a4fe3ab487d6b0c4e8b6ad2fb455bf19fc48 @@ -0,0 +1,2 @@ +xKN0DYGIFh VDff6RWV@h +x?y(, =K$-pB* B2*&Qژ x5x;*%)*+9r|έQLs;# wu-[\Lpvn.uN;n0JNĦo`#貥B(9BڠP=V?Y \ No newline at end of file diff --git a/.git/objects/6a/ae664adf07bff6bbe43430d18f3c3fbe12c9f5 b/.git/objects/6a/ae664adf07bff6bbe43430d18f3c3fbe12c9f5 new file mode 100644 index 0000000..fbd7a31 Binary files /dev/null and b/.git/objects/6a/ae664adf07bff6bbe43430d18f3c3fbe12c9f5 differ diff --git a/.git/objects/6a/af4fcead647b593cacd94c56d776a651f461e0 b/.git/objects/6a/af4fcead647b593cacd94c56d776a651f461e0 new file mode 100644 index 0000000..af13474 Binary files /dev/null and b/.git/objects/6a/af4fcead647b593cacd94c56d776a651f461e0 differ diff --git a/.git/objects/6a/dbc18c0f29f3a7c4fcac995d7ffe02c6d5c579 b/.git/objects/6a/dbc18c0f29f3a7c4fcac995d7ffe02c6d5c579 new file mode 100644 index 0000000..eba3598 Binary files /dev/null and b/.git/objects/6a/dbc18c0f29f3a7c4fcac995d7ffe02c6d5c579 differ diff --git a/.git/objects/6a/e149e626edf11129d123123e779b09666a1a40 b/.git/objects/6a/e149e626edf11129d123123e779b09666a1a40 new file mode 100644 index 0000000..570023f Binary files /dev/null and b/.git/objects/6a/e149e626edf11129d123123e779b09666a1a40 differ diff --git a/.git/objects/6a/edf5a19cf4c462a263978cb76b3f1335b9369c b/.git/objects/6a/edf5a19cf4c462a263978cb76b3f1335b9369c new file mode 100644 index 0000000..6c932b9 Binary files /dev/null and b/.git/objects/6a/edf5a19cf4c462a263978cb76b3f1335b9369c differ diff --git a/.git/objects/6a/f28648fa21d2c7c887e0b5d61e23ef5c5005db b/.git/objects/6a/f28648fa21d2c7c887e0b5d61e23ef5c5005db new file mode 100644 index 0000000..74db4b2 Binary files /dev/null and b/.git/objects/6a/f28648fa21d2c7c887e0b5d61e23ef5c5005db differ diff --git a/.git/objects/6b/2cd7732133d7f0a2b99259ce5e79373a66e8d4 b/.git/objects/6b/2cd7732133d7f0a2b99259ce5e79373a66e8d4 new file mode 100644 index 0000000..f35e0f3 Binary files /dev/null and b/.git/objects/6b/2cd7732133d7f0a2b99259ce5e79373a66e8d4 differ diff --git a/.git/objects/6b/324f71bf939668def2aeaffdd694f9609a6659 b/.git/objects/6b/324f71bf939668def2aeaffdd694f9609a6659 new file mode 100644 index 0000000..5416483 Binary files /dev/null and b/.git/objects/6b/324f71bf939668def2aeaffdd694f9609a6659 differ diff --git a/.git/objects/6b/48113a8f75b7f4df448015d909c42c90884c71 b/.git/objects/6b/48113a8f75b7f4df448015d909c42c90884c71 new file mode 100644 index 0000000..2cac500 --- /dev/null +++ b/.git/objects/6b/48113a8f75b7f4df448015d909c42c90884c71 @@ -0,0 +1 @@ +x=N0`bzc;A- % 'pRb#eoFXjyz_5uJI0jâ"!HjFraxsr壏A[I[$XPF-@TDTxZhw9P.2~L _z\R|^-uzIPeޯ4_gKt/kG!kJC++1 rbe \ No newline at end of file diff --git a/.git/objects/6b/4e3b3374bcd5f7d8ae7b3083422486ca4ac21e b/.git/objects/6b/4e3b3374bcd5f7d8ae7b3083422486ca4ac21e new file mode 100644 index 0000000..56c8b92 Binary files /dev/null and b/.git/objects/6b/4e3b3374bcd5f7d8ae7b3083422486ca4ac21e differ diff --git a/.git/objects/6b/91d3778ba7dcb4085bc67a29b34d161731a0ff b/.git/objects/6b/91d3778ba7dcb4085bc67a29b34d161731a0ff new file mode 100644 index 0000000..5d28b76 Binary files /dev/null and b/.git/objects/6b/91d3778ba7dcb4085bc67a29b34d161731a0ff differ diff --git a/.git/objects/6b/9332ab2fdee89c7e873622f2c63b0f9e346c87 b/.git/objects/6b/9332ab2fdee89c7e873622f2c63b0f9e346c87 new file mode 100644 index 0000000..0a6bcbc Binary files /dev/null and b/.git/objects/6b/9332ab2fdee89c7e873622f2c63b0f9e346c87 differ diff --git a/.git/objects/6b/aeeaa16aa59514f3a5012938338d9db3231d45 b/.git/objects/6b/aeeaa16aa59514f3a5012938338d9db3231d45 new file mode 100644 index 0000000..a2f1af5 Binary files /dev/null and b/.git/objects/6b/aeeaa16aa59514f3a5012938338d9db3231d45 differ diff --git a/.git/objects/6b/d3af86bdd6488be7832a16e213f436a9cef45a b/.git/objects/6b/d3af86bdd6488be7832a16e213f436a9cef45a new file mode 100644 index 0000000..ae6a12c --- /dev/null +++ b/.git/objects/6b/d3af86bdd6488be7832a16e213f436a9cef45a @@ -0,0 +1,2 @@ +xMj0u< #il +7A /Ov_zc`ㄔ,YtZf_Ըt@*hҒ\p84c2kBʂ} ?dnp[Sxg8p8J94,*xA\hd:yZpS.<o||D+:*s-$G% :{]T +lM\pbk&lx G +u_2Kn9<^ \ No newline at end of file diff --git a/.git/objects/6c/3a3c416413a2ec9138126aaad22fdf76b27354 b/.git/objects/6c/3a3c416413a2ec9138126aaad22fdf76b27354 new file mode 100644 index 0000000..faa3100 --- /dev/null +++ b/.git/objects/6c/3a3c416413a2ec9138126aaad22fdf76b27354 @@ -0,0 +1,2 @@ +x-Aj0 E)/  eJN GI ܬ^t!g.435VJ#nP`4myU\F%xk]Z* e5 l]j RR[}i?שeQBxCBpIK}=3}nx<7@X \ No newline at end of file diff --git a/.git/objects/6d/a13c4daecf7246ebcf2b1b1a35503ed0506c29 b/.git/objects/6d/a13c4daecf7246ebcf2b1b1a35503ed0506c29 new file mode 100644 index 0000000..fd67579 Binary files /dev/null and b/.git/objects/6d/a13c4daecf7246ebcf2b1b1a35503ed0506c29 differ diff --git a/.git/objects/6d/d5fe54a2987cbbbda52cc1747c2a5a91f38769 b/.git/objects/6d/d5fe54a2987cbbbda52cc1747c2a5a91f38769 new file mode 100644 index 0000000..f9b64c7 Binary files /dev/null and b/.git/objects/6d/d5fe54a2987cbbbda52cc1747c2a5a91f38769 differ diff --git a/.git/objects/6d/e74d37f93811b2eb21306749a13b456e478df5 b/.git/objects/6d/e74d37f93811b2eb21306749a13b456e478df5 new file mode 100644 index 0000000..e8c2d82 Binary files /dev/null and b/.git/objects/6d/e74d37f93811b2eb21306749a13b456e478df5 differ diff --git a/.git/objects/6d/f84f117072d13da3dd4e7e5b2b7f738bcfda7b b/.git/objects/6d/f84f117072d13da3dd4e7e5b2b7f738bcfda7b new file mode 100644 index 0000000..db8768e --- /dev/null +++ b/.git/objects/6d/f84f117072d13da3dd4e7e5b2b7f738bcfda7b @@ -0,0 +1,2 @@ +x%PKN0eSI["ְ qɟv{.[v#y_B*H.j&`i4dFƜTl(Ib0 'H #,yFef 4N# pkL7<^ Eɑ +^%koS8ZLA#u65oR^0цqF4t|ku=4'KӈBMPvsضD,k-S.O@9JjeFh \ No newline at end of file diff --git a/.git/objects/6e/28be02b51e00e4324075f5e07ad076de284898 b/.git/objects/6e/28be02b51e00e4324075f5e07ad076de284898 new file mode 100644 index 0000000..7a2790c Binary files /dev/null and b/.git/objects/6e/28be02b51e00e4324075f5e07ad076de284898 differ diff --git a/.git/objects/6e/2ccf993dadee3f772f884a2f2ca6203dd6cd79 b/.git/objects/6e/2ccf993dadee3f772f884a2f2ca6203dd6cd79 new file mode 100644 index 0000000..561596e Binary files /dev/null and b/.git/objects/6e/2ccf993dadee3f772f884a2f2ca6203dd6cd79 differ diff --git a/.git/objects/6e/37cf3596a8b3e178750616aba6e8cacacf51ff b/.git/objects/6e/37cf3596a8b3e178750616aba6e8cacacf51ff new file mode 100644 index 0000000..a5b23ad --- /dev/null +++ b/.git/objects/6e/37cf3596a8b3e178750616aba6e8cacacf51ff @@ -0,0 +1,8 @@ +x]kPW@hR0HJ m RhM ݅,IvcvC@Db24* +8TABˠXڐȴcw9GQ<^az W{- 9ڵAWD"ِu5r + OG1L$ٰ+O䔻y-C:y!-0'ۅNۼkH)8^ɐ;OPݢsnM0Wҁup;bx8g8p:&V6aS0uc|AW]F!J.l-YW!Gʼ:3tJ=a$Q[ocE ? +/|{g +Dr +H⚷[e'&}^LL"1-F++oǚ*lޟ=4i0V.[Ӣi<}Puo +P͹;\hIgrUU_ FgPf)VY<4j:Ę4;/8?!HVNv͟vP ]$ɡ ũwlC?bܼ2YޡmLyft\Zv^ۦzx ˝|Sf_DA`PbIʪ7%3&P8] +鼱٧**T'cZ|FRqo -]$[tY<8u; $iy*(cѣ@"{& GL[ޔ:t)$Pjy@ZQ=jPbtΩj U~D$l]j8"pzM;R_R8OΊP}j 53b~+#QHD X-C▜Ayr_صlB |3{VL霐殱T;mMEATQZ ?^﹠c ݔfSvS@E[Y2cY_b~ 54`1JA$SPӡ%_ wz+#c89#JC]ʼnAEDqV{S +1d_,19Y4.ݱ``KԶfA晒Ҳ1E'>{$i| \ No newline at end of file diff --git a/.git/objects/6e/7b0613b090dbf4fd309892b23b9943d6421cdf b/.git/objects/6e/7b0613b090dbf4fd309892b23b9943d6421cdf new file mode 100644 index 0000000..9e15050 Binary files /dev/null and b/.git/objects/6e/7b0613b090dbf4fd309892b23b9943d6421cdf differ diff --git a/.git/objects/6e/9abaab6874e8a5585e31b21012f4ee0e410bdc b/.git/objects/6e/9abaab6874e8a5585e31b21012f4ee0e410bdc new file mode 100644 index 0000000..bf978ba --- /dev/null +++ b/.git/objects/6e/9abaab6874e8a5585e31b21012f4ee0e410bdc @@ -0,0 +1,4 @@ +x-N0D9+1qU" _׍EG?Ώa!+fqJ4"Z +)Frz yp畾0{*x(wɴ[z -/o$AoDܶ?/K\0ѥ?quO5arޡO11ڎvט?28n +'y8@¸V~ +Nb \ No newline at end of file diff --git a/.git/objects/6e/b3cbfbd2b80e7f78c6232aea97af0de3b81409 b/.git/objects/6e/b3cbfbd2b80e7f78c6232aea97af0de3b81409 new file mode 100644 index 0000000..f85b29e Binary files /dev/null and b/.git/objects/6e/b3cbfbd2b80e7f78c6232aea97af0de3b81409 differ diff --git a/.git/objects/6e/bd4cfa34bbacb681bb1c3ae2704d2136ccc554 b/.git/objects/6e/bd4cfa34bbacb681bb1c3ae2704d2136ccc554 new file mode 100644 index 0000000..8c8a84e --- /dev/null +++ b/.git/objects/6e/bd4cfa34bbacb681bb1c3ae2704d2136ccc554 @@ -0,0 +1 @@ +x-J0D]+^,Iۤ';IhG럹 n93 |N ;d)''ֳ!ŀF e Ufq+5*L eM^6{8 Fn#||hwPMekE%ųAJTFk4n])/O\i;Bu󭝏B+x֛7bO9_[V \ No newline at end of file diff --git a/.git/objects/6e/ccc11979f8bc5201db7bc081f7c98a2e4405ef b/.git/objects/6e/ccc11979f8bc5201db7bc081f7c98a2e4405ef new file mode 100644 index 0000000..15c7d20 --- /dev/null +++ b/.git/objects/6e/ccc11979f8bc5201db7bc081f7c98a2e4405ef @@ -0,0 +1,4 @@ +x5NMN vS.J)ČqO +-I +Tgnދ&|&z +p-oJ"lQMWF )8H#7-^v2!fD@mjfZRτBC;(K|Dlp/KL}@NXsYh8`sYp8cMeR{24c;},B>ar 3ත`q1;$e(_ܰc \ No newline at end of file diff --git a/.git/objects/6f/1de3983796ec23dcc29e79b77aab26c2bdc5b3 b/.git/objects/6f/1de3983796ec23dcc29e79b77aab26c2bdc5b3 new file mode 100644 index 0000000..a7c23f2 Binary files /dev/null and b/.git/objects/6f/1de3983796ec23dcc29e79b77aab26c2bdc5b3 differ diff --git a/.git/objects/6f/26dfc317abd3b1c7be200ec301dbb6b890ea20 b/.git/objects/6f/26dfc317abd3b1c7be200ec301dbb6b890ea20 new file mode 100644 index 0000000..69bf6aa Binary files /dev/null and b/.git/objects/6f/26dfc317abd3b1c7be200ec301dbb6b890ea20 differ diff --git a/.git/objects/6f/3e836d77e1214acb07350222aadc684d22cdae b/.git/objects/6f/3e836d77e1214acb07350222aadc684d22cdae new file mode 100644 index 0000000..313ee3f Binary files /dev/null and b/.git/objects/6f/3e836d77e1214acb07350222aadc684d22cdae differ diff --git a/.git/objects/6f/3ee8788ba14d1790053e2ea4a99ba597624199 b/.git/objects/6f/3ee8788ba14d1790053e2ea4a99ba597624199 new file mode 100644 index 0000000..8cf0b85 Binary files /dev/null and b/.git/objects/6f/3ee8788ba14d1790053e2ea4a99ba597624199 differ diff --git a/.git/objects/6f/70d851b21b46f186d07728b00bfa8d8c7792c2 b/.git/objects/6f/70d851b21b46f186d07728b00bfa8d8c7792c2 new file mode 100644 index 0000000..b409d38 Binary files /dev/null and b/.git/objects/6f/70d851b21b46f186d07728b00bfa8d8c7792c2 differ diff --git a/.git/objects/6f/a7123a58ab58c878d1be151335df26a00a4af7 b/.git/objects/6f/a7123a58ab58c878d1be151335df26a00a4af7 new file mode 100644 index 0000000..9a99c53 Binary files /dev/null and b/.git/objects/6f/a7123a58ab58c878d1be151335df26a00a4af7 differ diff --git a/.git/objects/6f/c60534c3381c26c06c2e0c5e370420bfa92b0a b/.git/objects/6f/c60534c3381c26c06c2e0c5e370420bfa92b0a new file mode 100644 index 0000000..bd7d4e6 Binary files /dev/null and b/.git/objects/6f/c60534c3381c26c06c2e0c5e370420bfa92b0a differ diff --git a/.git/objects/6f/e632d35d28c308e2a9641a3d7d5d786f288725 b/.git/objects/6f/e632d35d28c308e2a9641a3d7d5d786f288725 new file mode 100644 index 0000000..e333bf0 Binary files /dev/null and b/.git/objects/6f/e632d35d28c308e2a9641a3d7d5d786f288725 differ diff --git a/.git/objects/6f/e6c1c197cb3719b8ffcf971958098f424be7db b/.git/objects/6f/e6c1c197cb3719b8ffcf971958098f424be7db new file mode 100644 index 0000000..e03c291 Binary files /dev/null and b/.git/objects/6f/e6c1c197cb3719b8ffcf971958098f424be7db differ diff --git a/.git/objects/6f/fce947b6f4ee1d06de4fc29bccb1ac49108ff7 b/.git/objects/6f/fce947b6f4ee1d06de4fc29bccb1ac49108ff7 new file mode 100644 index 0000000..5210e33 Binary files /dev/null and b/.git/objects/6f/fce947b6f4ee1d06de4fc29bccb1ac49108ff7 differ diff --git a/.git/objects/70/1fb621aaa46b769cb014f4219e60a300d660bb b/.git/objects/70/1fb621aaa46b769cb014f4219e60a300d660bb new file mode 100644 index 0000000..b6abc8e Binary files /dev/null and b/.git/objects/70/1fb621aaa46b769cb014f4219e60a300d660bb differ diff --git a/.git/objects/70/3073e7962984f33f393448ab34b1b806bed63c b/.git/objects/70/3073e7962984f33f393448ab34b1b806bed63c new file mode 100644 index 0000000..a05a82e Binary files /dev/null and b/.git/objects/70/3073e7962984f33f393448ab34b1b806bed63c differ diff --git a/.git/objects/70/3cf62522c5ef3e3344a0f95b90593fbc798d2e b/.git/objects/70/3cf62522c5ef3e3344a0f95b90593fbc798d2e new file mode 100644 index 0000000..b301006 Binary files /dev/null and b/.git/objects/70/3cf62522c5ef3e3344a0f95b90593fbc798d2e differ diff --git a/.git/objects/70/50343d8da3fa8063e589ff9451dc854c523c35 b/.git/objects/70/50343d8da3fa8063e589ff9451dc854c523c35 new file mode 100644 index 0000000..312fbf5 Binary files /dev/null and b/.git/objects/70/50343d8da3fa8063e589ff9451dc854c523c35 differ diff --git a/.git/objects/70/52c62857cada75dc7504971661b1b1166a1838 b/.git/objects/70/52c62857cada75dc7504971661b1b1166a1838 new file mode 100644 index 0000000..b42f90e Binary files /dev/null and b/.git/objects/70/52c62857cada75dc7504971661b1b1166a1838 differ diff --git a/.git/objects/70/55a064e263d3c396647c61052daae1671a92f8 b/.git/objects/70/55a064e263d3c396647c61052daae1671a92f8 new file mode 100644 index 0000000..6a0a0fd Binary files /dev/null and b/.git/objects/70/55a064e263d3c396647c61052daae1671a92f8 differ diff --git a/.git/objects/70/63f608fb59acd66558aa9f92f6382072b203d5 b/.git/objects/70/63f608fb59acd66558aa9f92f6382072b203d5 new file mode 100644 index 0000000..79e609c Binary files /dev/null and b/.git/objects/70/63f608fb59acd66558aa9f92f6382072b203d5 differ diff --git a/.git/objects/70/729a700c63a41da2ae3520a68dbe136b2fdb2b b/.git/objects/70/729a700c63a41da2ae3520a68dbe136b2fdb2b new file mode 100644 index 0000000..483103a Binary files /dev/null and b/.git/objects/70/729a700c63a41da2ae3520a68dbe136b2fdb2b differ diff --git a/.git/objects/70/79d76b620e6a56a709263c109123f93db9f2dc b/.git/objects/70/79d76b620e6a56a709263c109123f93db9f2dc new file mode 100644 index 0000000..dcd047a Binary files /dev/null and b/.git/objects/70/79d76b620e6a56a709263c109123f93db9f2dc differ diff --git a/.git/objects/70/9115740d4c0f49eb511faa80f8bf6c7d7d37e3 b/.git/objects/70/9115740d4c0f49eb511faa80f8bf6c7d7d37e3 new file mode 100644 index 0000000..2ee26ef Binary files /dev/null and b/.git/objects/70/9115740d4c0f49eb511faa80f8bf6c7d7d37e3 differ diff --git a/.git/objects/70/9e418722d3dceb52b2ead58e114a145ddaf305 b/.git/objects/70/9e418722d3dceb52b2ead58e114a145ddaf305 new file mode 100644 index 0000000..4d514f0 Binary files /dev/null and b/.git/objects/70/9e418722d3dceb52b2ead58e114a145ddaf305 differ diff --git a/.git/objects/70/c176a4bc437962e1e901ff1685ef8c91ad9c6d b/.git/objects/70/c176a4bc437962e1e901ff1685ef8c91ad9c6d new file mode 100644 index 0000000..88a5db5 Binary files /dev/null and b/.git/objects/70/c176a4bc437962e1e901ff1685ef8c91ad9c6d differ diff --git a/.git/objects/70/c992a37987254ebe015f7b3cf3589d1d3e2ba2 b/.git/objects/70/c992a37987254ebe015f7b3cf3589d1d3e2ba2 new file mode 100644 index 0000000..e80bdec --- /dev/null +++ b/.git/objects/70/c992a37987254ebe015f7b3cf3589d1d3e2ba2 @@ -0,0 +1,2 @@ +x%KJ1])jC%vwdĵȣ2I<Թ{/fU})WxQ3HӈO#wnȬ9rD6 1j8Lӌ$RraL+n8{t8{ɄQnuI6QզM Exʑ +uWu[;=0 ȕN8m%R>{࠷vuGr%GLJw4k6hQ˫{_T \ No newline at end of file diff --git a/.git/objects/70/d3b358b4b9c4841dfbfadd4b6aa3a947fcddba b/.git/objects/70/d3b358b4b9c4841dfbfadd4b6aa3a947fcddba new file mode 100644 index 0000000..759327b Binary files /dev/null and b/.git/objects/70/d3b358b4b9c4841dfbfadd4b6aa3a947fcddba differ diff --git a/.git/objects/70/e4306e2bfd65b2731fdf7aa82589fa93f1aa0b b/.git/objects/70/e4306e2bfd65b2731fdf7aa82589fa93f1aa0b new file mode 100644 index 0000000..19b1041 Binary files /dev/null and b/.git/objects/70/e4306e2bfd65b2731fdf7aa82589fa93f1aa0b differ diff --git a/.git/objects/70/e9e9195b88c3539d324be847268f05e0c3ae28 b/.git/objects/70/e9e9195b88c3539d324be847268f05e0c3ae28 new file mode 100644 index 0000000..6705f01 Binary files /dev/null and b/.git/objects/70/e9e9195b88c3539d324be847268f05e0c3ae28 differ diff --git a/.git/objects/71/0d79224ab7e26d6ad6d3bb4b8659e4c0f34b6a b/.git/objects/71/0d79224ab7e26d6ad6d3bb4b8659e4c0f34b6a new file mode 100644 index 0000000..3055d9d Binary files /dev/null and b/.git/objects/71/0d79224ab7e26d6ad6d3bb4b8659e4c0f34b6a differ diff --git a/.git/objects/71/3051a44aa78f2be8217ce4375756560e2f7ebb b/.git/objects/71/3051a44aa78f2be8217ce4375756560e2f7ebb new file mode 100644 index 0000000..802fac6 Binary files /dev/null and b/.git/objects/71/3051a44aa78f2be8217ce4375756560e2f7ebb differ diff --git a/.git/objects/71/46dd821bb7dda14cb2c338497ac70f43b6994a b/.git/objects/71/46dd821bb7dda14cb2c338497ac70f43b6994a new file mode 100644 index 0000000..c9dca26 Binary files /dev/null and b/.git/objects/71/46dd821bb7dda14cb2c338497ac70f43b6994a differ diff --git a/.git/objects/71/57ac11a5925d52035cba123f7dab05942a02a7 b/.git/objects/71/57ac11a5925d52035cba123f7dab05942a02a7 new file mode 100644 index 0000000..f3179f6 Binary files /dev/null and b/.git/objects/71/57ac11a5925d52035cba123f7dab05942a02a7 differ diff --git a/.git/objects/71/5f3af1b327eca1caf62a53883667375e44e904 b/.git/objects/71/5f3af1b327eca1caf62a53883667375e44e904 new file mode 100644 index 0000000..11c6030 --- /dev/null +++ b/.git/objects/71/5f3af1b327eca1caf62a53883667375e44e904 @@ -0,0 +1 @@ +x5J0E]+f/i)C'H lдb4r# j[< _[LXwDMշ5Ghp-be⹀^INf=Dk}\vC+x@Yի@2eOsȐqu)th!52X׃1ոg#f8ؒߞsɕX̛Tv3RZ-V?\ \ No newline at end of file diff --git a/.git/objects/73/4de829bfd941f83a41c329aee01bee755bcd61 b/.git/objects/73/4de829bfd941f83a41c329aee01bee755bcd61 new file mode 100644 index 0000000..4a14b4b Binary files /dev/null and b/.git/objects/73/4de829bfd941f83a41c329aee01bee755bcd61 differ diff --git a/.git/objects/73/5e839ad08a36503db06078709d105f291e63b3 b/.git/objects/73/5e839ad08a36503db06078709d105f291e63b3 new file mode 100644 index 0000000..cb1228d Binary files /dev/null and b/.git/objects/73/5e839ad08a36503db06078709d105f291e63b3 differ diff --git a/.git/objects/73/cd969ca38139dd320a8f0dc1a03ab96a390c2c b/.git/objects/73/cd969ca38139dd320a8f0dc1a03ab96a390c2c new file mode 100644 index 0000000..d34aef5 --- /dev/null +++ b/.git/objects/73/cd969ca38139dd320a8f0dc1a03ab96a390c2c @@ -0,0 +1,2 @@ +xAn!C0Ç,r1J[1T M +YTKd7sX8U*rLɠP~jHvx5xq󆷝;*y%[s|AJ0JR^sY0?q5LdR 6(wԐc04#&嗯!@{^ \ No newline at end of file diff --git a/.git/objects/76/1a215542d780ab5dd4550c3b62ee36cdbe71e5 b/.git/objects/76/1a215542d780ab5dd4550c3b62ee36cdbe71e5 new file mode 100644 index 0000000..8c1650c Binary files /dev/null and b/.git/objects/76/1a215542d780ab5dd4550c3b62ee36cdbe71e5 differ diff --git a/.git/objects/76/35f225f2820af4dd0ddfc7df34ac2a7c814d3d b/.git/objects/76/35f225f2820af4dd0ddfc7df34ac2a7c814d3d new file mode 100644 index 0000000..2714386 Binary files /dev/null and b/.git/objects/76/35f225f2820af4dd0ddfc7df34ac2a7c814d3d differ diff --git a/.git/objects/76/43ac8229388d7d01f63054505a03663643bcab b/.git/objects/76/43ac8229388d7d01f63054505a03663643bcab new file mode 100644 index 0000000..868c9eb Binary files /dev/null and b/.git/objects/76/43ac8229388d7d01f63054505a03663643bcab differ diff --git a/.git/objects/76/66f6d0dad9dec741c89c28f0fad5921d9c2e6f b/.git/objects/76/66f6d0dad9dec741c89c28f0fad5921d9c2e6f new file mode 100644 index 0000000..fba3539 --- /dev/null +++ b/.git/objects/76/66f6d0dad9dec741c89c28f0fad5921d9c2e6f @@ -0,0 +1 @@ +xAN E P>8v^F6ݜɹRsy~ kmdstki¬^qC E+N pd.t(EjBOR3\=j::j}:zk3ߑz{Acedaِ] \ No newline at end of file diff --git a/.git/objects/76/680f520e997cbab4f06d5a1d2f9ffd9afece1f b/.git/objects/76/680f520e997cbab4f06d5a1d2f9ffd9afece1f new file mode 100644 index 0000000..1ad7285 Binary files /dev/null and b/.git/objects/76/680f520e997cbab4f06d5a1d2f9ffd9afece1f differ diff --git a/.git/objects/76/80dc11cfa3eeb2835b18d8bca43fecae05e7dd b/.git/objects/76/80dc11cfa3eeb2835b18d8bca43fecae05e7dd new file mode 100644 index 0000000..704088e Binary files /dev/null and b/.git/objects/76/80dc11cfa3eeb2835b18d8bca43fecae05e7dd differ diff --git a/.git/objects/76/82b4ae67294de2786423adda23d07e7eef499f b/.git/objects/76/82b4ae67294de2786423adda23d07e7eef499f new file mode 100644 index 0000000..4a89ef9 Binary files /dev/null and b/.git/objects/76/82b4ae67294de2786423adda23d07e7eef499f differ diff --git a/.git/objects/76/972758ac6c3572ff4eec34d57171a958cfd2b1 b/.git/objects/76/972758ac6c3572ff4eec34d57171a958cfd2b1 new file mode 100644 index 0000000..f461f4d Binary files /dev/null and b/.git/objects/76/972758ac6c3572ff4eec34d57171a958cfd2b1 differ diff --git a/.git/objects/76/a1ebabcc185e88228b1b9025628eafe43a0343 b/.git/objects/76/a1ebabcc185e88228b1b9025628eafe43a0343 new file mode 100644 index 0000000..ee8286a Binary files /dev/null and b/.git/objects/76/a1ebabcc185e88228b1b9025628eafe43a0343 differ diff --git a/.git/objects/76/ad2f7718ee315e5f374daf9d8892cc1362f02d b/.git/objects/76/ad2f7718ee315e5f374daf9d8892cc1362f02d new file mode 100644 index 0000000..82eb52a Binary files /dev/null and b/.git/objects/76/ad2f7718ee315e5f374daf9d8892cc1362f02d differ diff --git a/.git/objects/76/eccc5177a6152b8a851eb429a26bad9ec2de9c b/.git/objects/76/eccc5177a6152b8a851eb429a26bad9ec2de9c new file mode 100644 index 0000000..2a9620c Binary files /dev/null and b/.git/objects/76/eccc5177a6152b8a851eb429a26bad9ec2de9c differ diff --git a/.git/objects/77/034ce3fc9e27879a73b30ce70198367e587b32 b/.git/objects/77/034ce3fc9e27879a73b30ce70198367e587b32 new file mode 100644 index 0000000..b430a3f Binary files /dev/null and b/.git/objects/77/034ce3fc9e27879a73b30ce70198367e587b32 differ diff --git a/.git/objects/77/16baba71358c35187b9804015691e1cfa9d9c8 b/.git/objects/77/16baba71358c35187b9804015691e1cfa9d9c8 new file mode 100644 index 0000000..2ab8272 Binary files /dev/null and b/.git/objects/77/16baba71358c35187b9804015691e1cfa9d9c8 differ diff --git a/.git/objects/77/26fb65d5826d48bebb89cef2cee86c9e6bddef b/.git/objects/77/26fb65d5826d48bebb89cef2cee86c9e6bddef new file mode 100644 index 0000000..aaea837 Binary files /dev/null and b/.git/objects/77/26fb65d5826d48bebb89cef2cee86c9e6bddef differ diff --git a/.git/objects/77/439b44b8b27d502a1e7f8ebb1b7bedb636069f b/.git/objects/77/439b44b8b27d502a1e7f8ebb1b7bedb636069f new file mode 100644 index 0000000..985f261 Binary files /dev/null and b/.git/objects/77/439b44b8b27d502a1e7f8ebb1b7bedb636069f differ diff --git a/.git/objects/77/945ed5251ebf62a882aa500ca1cfe7f3904483 b/.git/objects/77/945ed5251ebf62a882aa500ca1cfe7f3904483 new file mode 100644 index 0000000..ae4810c Binary files /dev/null and b/.git/objects/77/945ed5251ebf62a882aa500ca1cfe7f3904483 differ diff --git a/.git/objects/77/ddac7de65f8b3cd35c391023996500718a6265 b/.git/objects/77/ddac7de65f8b3cd35c391023996500718a6265 new file mode 100644 index 0000000..ed31d1e Binary files /dev/null and b/.git/objects/77/ddac7de65f8b3cd35c391023996500718a6265 differ diff --git a/.git/objects/78/31015375b0bf28c9f5c5562aa175beb154db11 b/.git/objects/78/31015375b0bf28c9f5c5562aa175beb154db11 new file mode 100644 index 0000000..c56aeb9 Binary files /dev/null and b/.git/objects/78/31015375b0bf28c9f5c5562aa175beb154db11 differ diff --git a/.git/objects/78/61ff1cb584f0faafc4630ffb76e2b416fe6413 b/.git/objects/78/61ff1cb584f0faafc4630ffb76e2b416fe6413 new file mode 100644 index 0000000..2685354 --- /dev/null +++ b/.git/objects/78/61ff1cb584f0faafc4630ffb76e2b416fe6413 @@ -0,0 +1 @@ +xMJ1`} RLD./d*dHJڹ{/fB{KmWw"A%L,3%Rt9*-t 3z_本4erzIޠX8/.Fߡ^*zAW.TpmJ[z5$fqK>h=x.vO<(2q++D$a)ӭurk \ No newline at end of file diff --git a/.git/objects/78/66f9e86fd874f69b2bb2c0d638e4acdc7b663f b/.git/objects/78/66f9e86fd874f69b2bb2c0d638e4acdc7b663f new file mode 100644 index 0000000..b439507 Binary files /dev/null and b/.git/objects/78/66f9e86fd874f69b2bb2c0d638e4acdc7b663f differ diff --git a/.git/objects/78/775e682e62736e20cccb9b814b59cb4b79e27a b/.git/objects/78/775e682e62736e20cccb9b814b59cb4b79e27a new file mode 100644 index 0000000..998d6b5 Binary files /dev/null and b/.git/objects/78/775e682e62736e20cccb9b814b59cb4b79e27a differ diff --git a/.git/objects/78/7ae941f0a7786927e7e4fc95f4d092046a6a72 b/.git/objects/78/7ae941f0a7786927e7e4fc95f4d092046a6a72 new file mode 100644 index 0000000..b8d5f81 Binary files /dev/null and b/.git/objects/78/7ae941f0a7786927e7e4fc95f4d092046a6a72 differ diff --git a/.git/objects/78/a18bc59ca6411644beeafef2bf1e722041b1b4 b/.git/objects/78/a18bc59ca6411644beeafef2bf1e722041b1b4 new file mode 100644 index 0000000..629b763 Binary files /dev/null and b/.git/objects/78/a18bc59ca6411644beeafef2bf1e722041b1b4 differ diff --git a/.git/objects/78/a9f3f959d3bee12cdcc7e4ca5311c402d069f5 b/.git/objects/78/a9f3f959d3bee12cdcc7e4ca5311c402d069f5 new file mode 100644 index 0000000..0549b8c Binary files /dev/null and b/.git/objects/78/a9f3f959d3bee12cdcc7e4ca5311c402d069f5 differ diff --git a/.git/objects/78/b6d9bd0499ca38442271cd37491e66405cb056 b/.git/objects/78/b6d9bd0499ca38442271cd37491e66405cb056 new file mode 100644 index 0000000..d0e7f45 Binary files /dev/null and b/.git/objects/78/b6d9bd0499ca38442271cd37491e66405cb056 differ diff --git a/.git/objects/78/ed9d2fb9ed0f7c2c08ac14f67bd662a1594687 b/.git/objects/78/ed9d2fb9ed0f7c2c08ac14f67bd662a1594687 new file mode 100644 index 0000000..9877a3f Binary files /dev/null and b/.git/objects/78/ed9d2fb9ed0f7c2c08ac14f67bd662a1594687 differ diff --git a/.git/objects/79/5445c27a6bad087ffe7415b927ef040631a98a b/.git/objects/79/5445c27a6bad087ffe7415b927ef040631a98a new file mode 100644 index 0000000..3cd1c02 Binary files /dev/null and b/.git/objects/79/5445c27a6bad087ffe7415b927ef040631a98a differ diff --git a/.git/objects/79/97837f191eefe8ab89a25d6849da19e3519004 b/.git/objects/79/97837f191eefe8ab89a25d6849da19e3519004 new file mode 100644 index 0000000..6f25a64 Binary files /dev/null and b/.git/objects/79/97837f191eefe8ab89a25d6849da19e3519004 differ diff --git a/.git/objects/79/b71739fdcff7997a29b35bc3a4872e46ca8209 b/.git/objects/79/b71739fdcff7997a29b35bc3a4872e46ca8209 new file mode 100644 index 0000000..b85a178 Binary files /dev/null and b/.git/objects/79/b71739fdcff7997a29b35bc3a4872e46ca8209 differ diff --git a/.git/objects/79/cc137c69ecc9bcbdbb6ff97cbf023792be4f86 b/.git/objects/79/cc137c69ecc9bcbdbb6ff97cbf023792be4f86 new file mode 100644 index 0000000..c136880 Binary files /dev/null and b/.git/objects/79/cc137c69ecc9bcbdbb6ff97cbf023792be4f86 differ diff --git a/.git/objects/79/db0d2ff7251ac95876ef589129175c7a0cfc78 b/.git/objects/79/db0d2ff7251ac95876ef589129175c7a0cfc78 new file mode 100644 index 0000000..67248cd Binary files /dev/null and b/.git/objects/79/db0d2ff7251ac95876ef589129175c7a0cfc78 differ diff --git a/.git/objects/79/dd0cfcf859b0fdcf8bfebb087630e4df45c71a b/.git/objects/79/dd0cfcf859b0fdcf8bfebb087630e4df45c71a new file mode 100644 index 0000000..8ba5e18 Binary files /dev/null and b/.git/objects/79/dd0cfcf859b0fdcf8bfebb087630e4df45c71a differ diff --git a/.git/objects/79/df5bcdfcad75ac5f95ab648e375f55884a655f b/.git/objects/79/df5bcdfcad75ac5f95ab648e375f55884a655f new file mode 100644 index 0000000..fc52acd --- /dev/null +++ b/.git/objects/79/df5bcdfcad75ac5f95ab648e375f55884a655f @@ -0,0 +1,4 @@ +xMj0F)f(,R t^`,b- +ͲŢCtur[c"kw#͐r#Si  +gii軛BmKeZL 9 +\.vzi -] on0(pJJEZC۽2r^J@:S-xd \ No newline at end of file diff --git a/.git/objects/79/fbc5fdf443cbc525909e8e2a3478558d327070 b/.git/objects/79/fbc5fdf443cbc525909e8e2a3478558d327070 new file mode 100644 index 0000000..550bfa8 Binary files /dev/null and b/.git/objects/79/fbc5fdf443cbc525909e8e2a3478558d327070 differ diff --git a/.git/objects/79/fc1826ad469e8d0cdbdc548f04c15396fcc795 b/.git/objects/79/fc1826ad469e8d0cdbdc548f04c15396fcc795 new file mode 100644 index 0000000..1d5e177 Binary files /dev/null and b/.git/objects/79/fc1826ad469e8d0cdbdc548f04c15396fcc795 differ diff --git a/.git/objects/7a/138bd2c2ad80cb75f7b2cb2bb0d8514e08fbb5 b/.git/objects/7a/138bd2c2ad80cb75f7b2cb2bb0d8514e08fbb5 new file mode 100644 index 0000000..09c552c Binary files /dev/null and b/.git/objects/7a/138bd2c2ad80cb75f7b2cb2bb0d8514e08fbb5 differ diff --git a/.git/objects/7a/1d3efb1cc9b0a596f54cbf2cf1592d514c940a b/.git/objects/7a/1d3efb1cc9b0a596f54cbf2cf1592d514c940a new file mode 100644 index 0000000..3b658de Binary files /dev/null and b/.git/objects/7a/1d3efb1cc9b0a596f54cbf2cf1592d514c940a differ diff --git a/.git/objects/7a/1e7ebf674e37cee6d0f23039a20bbee6966f76 b/.git/objects/7a/1e7ebf674e37cee6d0f23039a20bbee6966f76 new file mode 100644 index 0000000..24ad772 Binary files /dev/null and b/.git/objects/7a/1e7ebf674e37cee6d0f23039a20bbee6966f76 differ diff --git a/.git/objects/7a/28d5484ef3fc93f6e271e1d5df366c32dbbe11 b/.git/objects/7a/28d5484ef3fc93f6e271e1d5df366c32dbbe11 new file mode 100644 index 0000000..a2f56d4 Binary files /dev/null and b/.git/objects/7a/28d5484ef3fc93f6e271e1d5df366c32dbbe11 differ diff --git a/.git/objects/7a/d0a86359fb8afdd27b697f4d6ab608ea55b878 b/.git/objects/7a/d0a86359fb8afdd27b697f4d6ab608ea55b878 new file mode 100644 index 0000000..0772ff3 Binary files /dev/null and b/.git/objects/7a/d0a86359fb8afdd27b697f4d6ab608ea55b878 differ diff --git a/.git/objects/7a/d38b304a4610a45a7c22b68e4f6044f2b96856 b/.git/objects/7a/d38b304a4610a45a7c22b68e4f6044f2b96856 new file mode 100644 index 0000000..0fc7424 Binary files /dev/null and b/.git/objects/7a/d38b304a4610a45a7c22b68e4f6044f2b96856 differ diff --git a/.git/objects/7b/26438a583b5d9559bd67e22511ff67812feadb b/.git/objects/7b/26438a583b5d9559bd67e22511ff67812feadb new file mode 100644 index 0000000..7115a84 --- /dev/null +++ b/.git/objects/7b/26438a583b5d9559bd67e22511ff67812feadb @@ -0,0 +1 @@ +x=J0FS̽$&m`_I2i$)>Yb\+jfERVH?JP;C GSo2oF-w(YQ)}6hz;:2rN9}}&84i\ QjRbT(]kە3,y-L] t_ Obhzf0dR35m 2m>Eة[Ѽ4wQo a \ No newline at end of file diff --git a/.git/objects/7b/445190617d6be7554be60819b4ce669b69318c b/.git/objects/7b/445190617d6be7554be60819b4ce669b69318c new file mode 100644 index 0000000..6f8d6d9 Binary files /dev/null and b/.git/objects/7b/445190617d6be7554be60819b4ce669b69318c differ diff --git a/.git/objects/7b/59e8c6461c50c718872adccb66202046673585 b/.git/objects/7b/59e8c6461c50c718872adccb66202046673585 new file mode 100644 index 0000000..5fb875b Binary files /dev/null and b/.git/objects/7b/59e8c6461c50c718872adccb66202046673585 differ diff --git a/.git/objects/7b/6c13d9cf047e219a6f6402a1baed137cf69e6c b/.git/objects/7b/6c13d9cf047e219a6f6402a1baed137cf69e6c new file mode 100644 index 0000000..adb5b00 Binary files /dev/null and b/.git/objects/7b/6c13d9cf047e219a6f6402a1baed137cf69e6c differ diff --git a/.git/objects/7b/7811bf5e1794addd08cd3344c317d544ab108b b/.git/objects/7b/7811bf5e1794addd08cd3344c317d544ab108b new file mode 100644 index 0000000..c47933a Binary files /dev/null and b/.git/objects/7b/7811bf5e1794addd08cd3344c317d544ab108b differ diff --git a/.git/objects/7b/82cd1ef419ad87132bdc8743795e1c5dc2d1e6 b/.git/objects/7b/82cd1ef419ad87132bdc8743795e1c5dc2d1e6 new file mode 100644 index 0000000..cbcdc72 --- /dev/null +++ b/.git/objects/7b/82cd1ef419ad87132bdc8743795e1c5dc2d1e6 @@ -0,0 +1,3 @@ +xAn ETAcjK6DDͺ!酲kr֪3dl(j71"4$2k3hgu*׌>PX@$X +DS|kKps +_k(?YNm_J⟒0q, NHu%F&*Vʦ^]M \ No newline at end of file diff --git a/.git/objects/7b/9c43662e0df1296d8532bcd69f2ffc3d5a86cf b/.git/objects/7b/9c43662e0df1296d8532bcd69f2ffc3d5a86cf new file mode 100644 index 0000000..46a53a3 Binary files /dev/null and b/.git/objects/7b/9c43662e0df1296d8532bcd69f2ffc3d5a86cf differ diff --git a/.git/objects/7b/a53d4635134979121b998f8356a12fb0e8e5ff b/.git/objects/7b/a53d4635134979121b998f8356a12fb0e8e5ff new file mode 100644 index 0000000..fa70036 Binary files /dev/null and b/.git/objects/7b/a53d4635134979121b998f8356a12fb0e8e5ff differ diff --git a/.git/objects/7b/d571e9f1c9d161276764ec212a5e3551bf4384 b/.git/objects/7b/d571e9f1c9d161276764ec212a5e3551bf4384 new file mode 100644 index 0000000..4004e14 Binary files /dev/null and b/.git/objects/7b/d571e9f1c9d161276764ec212a5e3551bf4384 differ diff --git a/.git/objects/7b/e0f3bb0fb9133094db8abe65a782b09f2b3fa2 b/.git/objects/7b/e0f3bb0fb9133094db8abe65a782b09f2b3fa2 new file mode 100644 index 0000000..f2bc4a1 Binary files /dev/null and b/.git/objects/7b/e0f3bb0fb9133094db8abe65a782b09f2b3fa2 differ diff --git a/.git/objects/7b/e5d6bd34d5c9c2f78df084e8d824b111925dcb b/.git/objects/7b/e5d6bd34d5c9c2f78df084e8d824b111925dcb new file mode 100644 index 0000000..06fc379 --- /dev/null +++ b/.git/objects/7b/e5d6bd34d5c9c2f78df084e8d824b111925dcb @@ -0,0 +1 @@ +xMN0 FY#FA,XFjQs3\0f"`.G^Y nhꮘ)VL Nl5 )ܠu3g #k7Ɖ26#8a"i%[~.6Jf ƺvmkP-#~_.{u =M]7)$<1<.bbX'A!~C%X] \ No newline at end of file diff --git a/.git/objects/7b/f1d1b4db377a74fb222448b98b790896555937 b/.git/objects/7b/f1d1b4db377a74fb222448b98b790896555937 new file mode 100644 index 0000000..11b36f9 Binary files /dev/null and b/.git/objects/7b/f1d1b4db377a74fb222448b98b790896555937 differ diff --git a/.git/objects/7c/1fb25dd152a94877c6c1b09408bf3de040482c b/.git/objects/7c/1fb25dd152a94877c6c1b09408bf3de040482c new file mode 100644 index 0000000..939d8f1 Binary files /dev/null and b/.git/objects/7c/1fb25dd152a94877c6c1b09408bf3de040482c differ diff --git a/.git/objects/7c/bc67f1f546c67ae85d6fd19341d6511a78a7c8 b/.git/objects/7c/bc67f1f546c67ae85d6fd19341d6511a78a7c8 new file mode 100644 index 0000000..b11ca38 Binary files /dev/null and b/.git/objects/7c/bc67f1f546c67ae85d6fd19341d6511a78a7c8 differ diff --git a/.git/objects/7c/c9a302a9fc1020382631ecfeb5efaadc4ffd60 b/.git/objects/7c/c9a302a9fc1020382631ecfeb5efaadc4ffd60 new file mode 100644 index 0000000..5235f41 Binary files /dev/null and b/.git/objects/7c/c9a302a9fc1020382631ecfeb5efaadc4ffd60 differ diff --git a/.git/objects/7c/dd8327712231448fad4c4618e57f352b02f8c1 b/.git/objects/7c/dd8327712231448fad4c4618e57f352b02f8c1 new file mode 100644 index 0000000..a7ed458 Binary files /dev/null and b/.git/objects/7c/dd8327712231448fad4c4618e57f352b02f8c1 differ diff --git a/.git/objects/7c/f3180e808ea5aaf8e979a7c3609390a7d614f8 b/.git/objects/7c/f3180e808ea5aaf8e979a7c3609390a7d614f8 new file mode 100644 index 0000000..d93d327 Binary files /dev/null and b/.git/objects/7c/f3180e808ea5aaf8e979a7c3609390a7d614f8 differ diff --git a/.git/objects/7d/0469978ca35fb176f68c65b1dba90d4479dc5d b/.git/objects/7d/0469978ca35fb176f68c65b1dba90d4479dc5d new file mode 100644 index 0000000..c0a89b7 --- /dev/null +++ b/.git/objects/7d/0469978ca35fb176f68c65b1dba90d4479dc5d @@ -0,0 +1 @@ +x-N E]+fo|@i1/潸֍_0В@(cn2ܛ{mڶPkP  Fa8Yǽऔn|pM^(-#e,+x9;Ъ{Fl 7/K*p_ ϝ"||H;\ҐqNش@{!Gڷ-u)aTfpq.9\^jf05X!g;s*mP+ڒCHh ͩ/1br \ No newline at end of file diff --git a/.git/objects/7d/0bf10710844b66fe6af23493086bf636ca5e00 b/.git/objects/7d/0bf10710844b66fe6af23493086bf636ca5e00 new file mode 100644 index 0000000..c7b4c35 Binary files /dev/null and b/.git/objects/7d/0bf10710844b66fe6af23493086bf636ca5e00 differ diff --git a/.git/objects/7d/4aa559a4357e046326b7d246738e61207ffc02 b/.git/objects/7d/4aa559a4357e046326b7d246738e61207ffc02 new file mode 100644 index 0000000..5f33db5 Binary files /dev/null and b/.git/objects/7d/4aa559a4357e046326b7d246738e61207ffc02 differ diff --git a/.git/objects/7d/5b0ad6b7c59388e940df211612d6bb3724a228 b/.git/objects/7d/5b0ad6b7c59388e940df211612d6bb3724a228 new file mode 100644 index 0000000..88cf197 Binary files /dev/null and b/.git/objects/7d/5b0ad6b7c59388e940df211612d6bb3724a228 differ diff --git a/.git/objects/7d/701010b9b3956f920c8d67e1e99d01a54028e6 b/.git/objects/7d/701010b9b3956f920c8d67e1e99d01a54028e6 new file mode 100644 index 0000000..ad5cf31 Binary files /dev/null and b/.git/objects/7d/701010b9b3956f920c8d67e1e99d01a54028e6 differ diff --git a/.git/objects/7d/749aeebf7907ca4914373dc7483457e49b207d b/.git/objects/7d/749aeebf7907ca4914373dc7483457e49b207d new file mode 100644 index 0000000..65a7349 Binary files /dev/null and b/.git/objects/7d/749aeebf7907ca4914373dc7483457e49b207d differ diff --git a/.git/objects/7d/a3c690780fec9995aafd847b8c81c39043a35d b/.git/objects/7d/a3c690780fec9995aafd847b8c81c39043a35d new file mode 100644 index 0000000..6f9ef93 Binary files /dev/null and b/.git/objects/7d/a3c690780fec9995aafd847b8c81c39043a35d differ diff --git a/.git/objects/7d/c93b85bcd5d7fb73ef550d77fb48f4fc67e318 b/.git/objects/7d/c93b85bcd5d7fb73ef550d77fb48f4fc67e318 new file mode 100644 index 0000000..a8d1f5e Binary files /dev/null and b/.git/objects/7d/c93b85bcd5d7fb73ef550d77fb48f4fc67e318 differ diff --git a/.git/objects/7d/e721672414381fcc0b7b1ed01346422be97160 b/.git/objects/7d/e721672414381fcc0b7b1ed01346422be97160 new file mode 100644 index 0000000..dd901cc --- /dev/null +++ b/.git/objects/7d/e721672414381fcc0b7b1ed01346422be97160 @@ -0,0 +1,3 @@ +x-N0Dۥ@D$vltB ^b)ܟcXn43o4.m[(Odflmz5N+'.b Ak&͕2ifRf~dQVrP5"cCGYR畿(z\Zsy\^j%]hNֹ={B4խKyYr5"'δ[y 7 +BVa/9أř8`BI +/Z \ No newline at end of file diff --git a/.git/objects/7d/fc4b122045ffcff6a214aa620f7823eb0acaff b/.git/objects/7d/fc4b122045ffcff6a214aa620f7823eb0acaff new file mode 100644 index 0000000..bae5c5a Binary files /dev/null and b/.git/objects/7d/fc4b122045ffcff6a214aa620f7823eb0acaff differ diff --git a/.git/objects/7e/1695aa14c90418b1f6cdaca47b406ee917e112 b/.git/objects/7e/1695aa14c90418b1f6cdaca47b406ee917e112 new file mode 100644 index 0000000..9032c89 Binary files /dev/null and b/.git/objects/7e/1695aa14c90418b1f6cdaca47b406ee917e112 differ diff --git a/.git/objects/7e/3f0c13a244be776e275c807c8d4abc234c3199 b/.git/objects/7e/3f0c13a244be776e275c807c8d4abc234c3199 new file mode 100644 index 0000000..b8cb803 Binary files /dev/null and b/.git/objects/7e/3f0c13a244be776e275c807c8d4abc234c3199 differ diff --git a/.git/objects/7e/5264a3d07133ee60495d2206f80daadbb28afd b/.git/objects/7e/5264a3d07133ee60495d2206f80daadbb28afd new file mode 100644 index 0000000..e8c3b13 --- /dev/null +++ b/.git/objects/7e/5264a3d07133ee60495d2206f80daadbb28afd @@ -0,0 +1,3 @@ +x5N =)cCl'-IҬ}3リdfctW jdd \ No newline at end of file diff --git a/.git/objects/82/b018d8744fcf260ae5248000b18a2c603e4c49 b/.git/objects/82/b018d8744fcf260ae5248000b18a2c603e4c49 new file mode 100644 index 0000000..f85b116 Binary files /dev/null and b/.git/objects/82/b018d8744fcf260ae5248000b18a2c603e4c49 differ diff --git a/.git/objects/82/b98e1d76664db1090d5622d804553c5ac66297 b/.git/objects/82/b98e1d76664db1090d5622d804553c5ac66297 new file mode 100644 index 0000000..58a6b92 Binary files /dev/null and b/.git/objects/82/b98e1d76664db1090d5622d804553c5ac66297 differ diff --git a/.git/objects/82/bca0b7e8c24d91814c78ddee75265aedae3ae3 b/.git/objects/82/bca0b7e8c24d91814c78ddee75265aedae3ae3 new file mode 100644 index 0000000..e42eb0f Binary files /dev/null and b/.git/objects/82/bca0b7e8c24d91814c78ddee75265aedae3ae3 differ diff --git a/.git/objects/82/c8383b9ee52e1aa27536ed4a75c4b0ae630390 b/.git/objects/82/c8383b9ee52e1aa27536ed4a75c4b0ae630390 new file mode 100644 index 0000000..0c861e9 Binary files /dev/null and b/.git/objects/82/c8383b9ee52e1aa27536ed4a75c4b0ae630390 differ diff --git a/.git/objects/82/cf8994973efb7b0606627cfd16a0355f5d257d b/.git/objects/82/cf8994973efb7b0606627cfd16a0355f5d257d new file mode 100644 index 0000000..64c1397 Binary files /dev/null and b/.git/objects/82/cf8994973efb7b0606627cfd16a0355f5d257d differ diff --git a/.git/objects/82/fc7309f7853b5d1a826156b2d3315d4d00e73c b/.git/objects/82/fc7309f7853b5d1a826156b2d3315d4d00e73c new file mode 100644 index 0000000..fa625e1 Binary files /dev/null and b/.git/objects/82/fc7309f7853b5d1a826156b2d3315d4d00e73c differ diff --git a/.git/objects/83/1de344b5fe0162d5b7a6bb5c7da819638bc184 b/.git/objects/83/1de344b5fe0162d5b7a6bb5c7da819638bc184 new file mode 100644 index 0000000..67efa59 Binary files /dev/null and b/.git/objects/83/1de344b5fe0162d5b7a6bb5c7da819638bc184 differ diff --git a/.git/objects/83/1e291918668ac9fe6ceef7bb90ee8c05caec02 b/.git/objects/83/1e291918668ac9fe6ceef7bb90ee8c05caec02 new file mode 100644 index 0000000..27694d3 Binary files /dev/null and b/.git/objects/83/1e291918668ac9fe6ceef7bb90ee8c05caec02 differ diff --git a/.git/objects/83/2bcbd33eb02957bc9d4b9c693392e4d1a56da2 b/.git/objects/83/2bcbd33eb02957bc9d4b9c693392e4d1a56da2 new file mode 100644 index 0000000..8c0b827 Binary files /dev/null and b/.git/objects/83/2bcbd33eb02957bc9d4b9c693392e4d1a56da2 differ diff --git a/.git/objects/83/51346adcff5743c0a36c4ba595bdbf6966badd b/.git/objects/83/51346adcff5743c0a36c4ba595bdbf6966badd new file mode 100644 index 0000000..27634c3 Binary files /dev/null and b/.git/objects/83/51346adcff5743c0a36c4ba595bdbf6966badd differ diff --git a/.git/objects/83/5d82e49bee4e1f1d608610698ad29553bdb53f b/.git/objects/83/5d82e49bee4e1f1d608610698ad29553bdb53f new file mode 100644 index 0000000..6116294 --- /dev/null +++ b/.git/objects/83/5d82e49bee4e1f1d608610698ad29553bdb53f @@ -0,0 +1,3 @@ +x-Aj0E)f_j$K,%vL4#`IAfb59ƹBgS-̠1 B`D/W8 +B)-J(sUO=I nu. c".1rߟx\'J8洷>WIg u)湴ff0co,ސR̞ZIqc?7Ji ǁᑕv$$QtK8Gpi{_9r#>⶿z(+HeQf< %D~k#< _mxN~h?bvPM {& !BRB3 h \ No newline at end of file diff --git a/.git/objects/85/38a5a03a0ae6fb37debce6fb58115db3fa54ba b/.git/objects/85/38a5a03a0ae6fb37debce6fb58115db3fa54ba new file mode 100644 index 0000000..9bc4375 Binary files /dev/null and b/.git/objects/85/38a5a03a0ae6fb37debce6fb58115db3fa54ba differ diff --git a/.git/objects/85/4b2df1c89d09faa49c8bc1b0d6fbf6912841da b/.git/objects/85/4b2df1c89d09faa49c8bc1b0d6fbf6912841da new file mode 100644 index 0000000..ae48e4e Binary files /dev/null and b/.git/objects/85/4b2df1c89d09faa49c8bc1b0d6fbf6912841da differ diff --git a/.git/objects/85/84a8c9183f1ea8de66256b939718989e4add4e b/.git/objects/85/84a8c9183f1ea8de66256b939718989e4add4e new file mode 100644 index 0000000..c6ec1c1 Binary files /dev/null and b/.git/objects/85/84a8c9183f1ea8de66256b939718989e4add4e differ diff --git a/.git/objects/85/89cf1a3f9c11b93bc6d1a7f9a976049c9850c7 b/.git/objects/85/89cf1a3f9c11b93bc6d1a7f9a976049c9850c7 new file mode 100644 index 0000000..7df39fc Binary files /dev/null and b/.git/objects/85/89cf1a3f9c11b93bc6d1a7f9a976049c9850c7 differ diff --git a/.git/objects/85/901d578c56753f2e9e68bb649a8990be860b28 b/.git/objects/85/901d578c56753f2e9e68bb649a8990be860b28 new file mode 100644 index 0000000..402cde3 Binary files /dev/null and b/.git/objects/85/901d578c56753f2e9e68bb649a8990be860b28 differ diff --git a/.git/objects/85/aa155c8aeacb202e8e64ec4c9b8a7391c3a1ce b/.git/objects/85/aa155c8aeacb202e8e64ec4c9b8a7391c3a1ce new file mode 100644 index 0000000..7ad6693 Binary files /dev/null and b/.git/objects/85/aa155c8aeacb202e8e64ec4c9b8a7391c3a1ce differ diff --git a/.git/objects/85/c723b1ae537750ccd41c554530320336b4faaa b/.git/objects/85/c723b1ae537750ccd41c554530320336b4faaa new file mode 100644 index 0000000..1db6e26 Binary files /dev/null and b/.git/objects/85/c723b1ae537750ccd41c554530320336b4faaa differ diff --git a/.git/objects/85/e6669a0ba086c5dc5f397f26dd6006c875a6c0 b/.git/objects/85/e6669a0ba086c5dc5f397f26dd6006c875a6c0 new file mode 100644 index 0000000..c44127a Binary files /dev/null and b/.git/objects/85/e6669a0ba086c5dc5f397f26dd6006c875a6c0 differ diff --git a/.git/objects/85/ea36fe0b2b566dde859abf7f3eeed37e1d6c58 b/.git/objects/85/ea36fe0b2b566dde859abf7f3eeed37e1d6c58 new file mode 100644 index 0000000..c581421 Binary files /dev/null and b/.git/objects/85/ea36fe0b2b566dde859abf7f3eeed37e1d6c58 differ diff --git a/.git/objects/86/51f97b9ffd6611da2401e7f563a211d0a65b0a b/.git/objects/86/51f97b9ffd6611da2401e7f563a211d0a65b0a new file mode 100644 index 0000000..e7158ae Binary files /dev/null and b/.git/objects/86/51f97b9ffd6611da2401e7f563a211d0a65b0a differ diff --git a/.git/objects/86/5f73ebfaab4f98b9e6e62280d413d28898a922 b/.git/objects/86/5f73ebfaab4f98b9e6e62280d413d28898a922 new file mode 100644 index 0000000..26665ce Binary files /dev/null and b/.git/objects/86/5f73ebfaab4f98b9e6e62280d413d28898a922 differ diff --git a/.git/objects/86/ca0038e62191b72e21398d81295cde73799789 b/.git/objects/86/ca0038e62191b72e21398d81295cde73799789 new file mode 100644 index 0000000..ab0f3f9 Binary files /dev/null and b/.git/objects/86/ca0038e62191b72e21398d81295cde73799789 differ diff --git a/.git/objects/86/ced92c4c6a92aa34be91c11ffadc445cc9f816 b/.git/objects/86/ced92c4c6a92aa34be91c11ffadc445cc9f816 new file mode 100644 index 0000000..2b14064 --- /dev/null +++ b/.git/objects/86/ced92c4c6a92aa34be91c11ffadc445cc9f816 @@ -0,0 +1,4 @@ +xKj0D)z7BRkl?#r슢^uWuiexi +hDNs*'fT;LKZCMGll#7npՂCMqF4QYl]ʺrV-1_N)Nx^9O + =b8( F+R.sy_58|Y8ms;y'UmN"V*m:Ƽm'̀!L σ7*~a \ No newline at end of file diff --git a/.git/objects/8b/561a2ccec9f0cddbf39bddce681d792e189639 b/.git/objects/8b/561a2ccec9f0cddbf39bddce681d792e189639 new file mode 100644 index 0000000..855db96 Binary files /dev/null and b/.git/objects/8b/561a2ccec9f0cddbf39bddce681d792e189639 differ diff --git a/.git/objects/8b/68cbd00c216202038faa2fbb38a32f50970104 b/.git/objects/8b/68cbd00c216202038faa2fbb38a32f50970104 new file mode 100644 index 0000000..18dafb1 Binary files /dev/null and b/.git/objects/8b/68cbd00c216202038faa2fbb38a32f50970104 differ diff --git a/.git/objects/8b/7713ebd00e445b2c5a3357e3e1c3e29d1b4889 b/.git/objects/8b/7713ebd00e445b2c5a3357e3e1c3e29d1b4889 new file mode 100644 index 0000000..04c17c4 Binary files /dev/null and b/.git/objects/8b/7713ebd00e445b2c5a3357e3e1c3e29d1b4889 differ diff --git a/.git/objects/8b/c3b29bd49d45ed2a0438f76b0d02f1cce57990 b/.git/objects/8b/c3b29bd49d45ed2a0438f76b0d02f1cce57990 new file mode 100644 index 0000000..4ab238e Binary files /dev/null and b/.git/objects/8b/c3b29bd49d45ed2a0438f76b0d02f1cce57990 differ diff --git a/.git/objects/8b/c9b5dc1ce16d7e47adc36c5be1e6172b2ba075 b/.git/objects/8b/c9b5dc1ce16d7e47adc36c5be1e6172b2ba075 new file mode 100644 index 0000000..c71b38d Binary files /dev/null and b/.git/objects/8b/c9b5dc1ce16d7e47adc36c5be1e6172b2ba075 differ diff --git a/.git/objects/8b/d49781ca8b6dd9644514aae217449a493c04f3 b/.git/objects/8b/d49781ca8b6dd9644514aae217449a493c04f3 new file mode 100644 index 0000000..d2c5da8 Binary files /dev/null and b/.git/objects/8b/d49781ca8b6dd9644514aae217449a493c04f3 differ diff --git a/.git/objects/8b/e4e24864a190c5885f8d730fba1c07a9d3e37c b/.git/objects/8b/e4e24864a190c5885f8d730fba1c07a9d3e37c new file mode 100644 index 0000000..f3e78e6 --- /dev/null +++ b/.git/objects/8b/e4e24864a190c5885f8d730fba1c07a9d3e37c @@ -0,0 +1,2 @@ +xAN!E]sڛ&ƥOP 4I7gnދ!\//?}1))#=+8i!`=Ej5.HA$iKFcL3)i;\9AoߨDnC~pߟVgk_yHMtRMNGTbw2KNok.g +Õۑk*>ax \ No newline at end of file diff --git a/.git/objects/8b/e8181219e56e463f3ec8d51c254acdbfa3ed12 b/.git/objects/8b/e8181219e56e463f3ec8d51c254acdbfa3ed12 new file mode 100644 index 0000000..4c4fc97 Binary files /dev/null and b/.git/objects/8b/e8181219e56e463f3ec8d51c254acdbfa3ed12 differ diff --git a/.git/objects/8c/377efdc8361791d31fce0132592d3bf4da448c b/.git/objects/8c/377efdc8361791d31fce0132592d3bf4da448c new file mode 100644 index 0000000..c4cadbc Binary files /dev/null and b/.git/objects/8c/377efdc8361791d31fce0132592d3bf4da448c differ diff --git a/.git/objects/8c/444cc9e3134afb8651b02385f46c8a4076dfca b/.git/objects/8c/444cc9e3134afb8651b02385f46c8a4076dfca new file mode 100644 index 0000000..d467b89 Binary files /dev/null and b/.git/objects/8c/444cc9e3134afb8651b02385f46c8a4076dfca differ diff --git a/.git/objects/8c/49d0c4240c27f9649ef5cc7721fd6919a72dcc b/.git/objects/8c/49d0c4240c27f9649ef5cc7721fd6919a72dcc new file mode 100644 index 0000000..f9564af Binary files /dev/null and b/.git/objects/8c/49d0c4240c27f9649ef5cc7721fd6919a72dcc differ diff --git a/.git/objects/8c/5be3a10dac47ad32ac7a086c880640123ad98d b/.git/objects/8c/5be3a10dac47ad32ac7a086c880640123ad98d new file mode 100644 index 0000000..548947e Binary files /dev/null and b/.git/objects/8c/5be3a10dac47ad32ac7a086c880640123ad98d differ diff --git a/.git/objects/8c/7bd3a5e9229d4b89fc28069bb056d22b0622c8 b/.git/objects/8c/7bd3a5e9229d4b89fc28069bb056d22b0622c8 new file mode 100644 index 0000000..c9991ba --- /dev/null +++ b/.git/objects/8c/7bd3a5e9229d4b89fc28069bb056d22b0622c8 @@ -0,0 +1 @@ +xn D{W콊`FD=~ ccEfu6/0zPB!iä!.,XBczmT8UP4Mn@Fo&9`8pT& N莎:ׅ(y.]^sߒx3Rg[%]^@kF&kn]\)٭OqX-'PR UûS8•a?-щW \ No newline at end of file diff --git a/.git/objects/8c/ab1d90c46811530bbb84a72ab9c4220efa145b b/.git/objects/8c/ab1d90c46811530bbb84a72ab9c4220efa145b new file mode 100644 index 0000000..20f049d Binary files /dev/null and b/.git/objects/8c/ab1d90c46811530bbb84a72ab9c4220efa145b differ diff --git a/.git/objects/8c/d7760f1418c08d4d828b43e6720a9557560ac2 b/.git/objects/8c/d7760f1418c08d4d828b43e6720a9557560ac2 new file mode 100644 index 0000000..621f7d3 Binary files /dev/null and b/.git/objects/8c/d7760f1418c08d4d828b43e6720a9557560ac2 differ diff --git a/.git/objects/8c/e20bbc82487b19d3e2dd3be793d8b909d02e66 b/.git/objects/8c/e20bbc82487b19d3e2dd3be793d8b909d02e66 new file mode 100644 index 0000000..c7592bc Binary files /dev/null and b/.git/objects/8c/e20bbc82487b19d3e2dd3be793d8b909d02e66 differ diff --git a/.git/objects/8d/49bf3c41b01a8de960fde4636e0ae52f0ee4ce b/.git/objects/8d/49bf3c41b01a8de960fde4636e0ae52f0ee4ce new file mode 100644 index 0000000..fcc8275 Binary files /dev/null and b/.git/objects/8d/49bf3c41b01a8de960fde4636e0ae52f0ee4ce differ diff --git a/.git/objects/8d/915a87b12c26ea0f8a36b5d6468a4488433e72 b/.git/objects/8d/915a87b12c26ea0f8a36b5d6468a4488433e72 new file mode 100644 index 0000000..42c9f87 Binary files /dev/null and b/.git/objects/8d/915a87b12c26ea0f8a36b5d6468a4488433e72 differ diff --git a/.git/objects/8d/959727e85e28a0dd7b46671b99a96a9b7e2fc6 b/.git/objects/8d/959727e85e28a0dd7b46671b99a96a9b7e2fc6 new file mode 100644 index 0000000..26cb00e Binary files /dev/null and b/.git/objects/8d/959727e85e28a0dd7b46671b99a96a9b7e2fc6 differ diff --git a/.git/objects/8d/985b651bb903a68e3f8ce7d54f15dd87d87ded b/.git/objects/8d/985b651bb903a68e3f8ce7d54f15dd87d87ded new file mode 100644 index 0000000..a87e2db Binary files /dev/null and b/.git/objects/8d/985b651bb903a68e3f8ce7d54f15dd87d87ded differ diff --git a/.git/objects/8d/9cefe7b69a9cc7c87e51ad17408986e5304874 b/.git/objects/8d/9cefe7b69a9cc7c87e51ad17408986e5304874 new file mode 100644 index 0000000..be39275 --- /dev/null +++ b/.git/objects/8d/9cefe7b69a9cc7c87e51ad17408986e5304874 @@ -0,0 +1,2 @@ +xKN0DYGDݶhf6;)#f!^RuiYU%3[YՆ{X +/elgVL=Fjk\i}2 ] }Gɑ7^QIR]Z^ȒmZI(]1O<n9RSa?uZh2ЫTn!k][XY \ No newline at end of file diff --git a/.git/objects/8d/af89e48aeac17bdd8b0125dbdb451161ba7274 b/.git/objects/8d/af89e48aeac17bdd8b0125dbdb451161ba7274 new file mode 100644 index 0000000..bbd7d29 Binary files /dev/null and b/.git/objects/8d/af89e48aeac17bdd8b0125dbdb451161ba7274 differ diff --git a/.git/objects/8d/bcb0b270e9ab441407005a96638c37851679e0 b/.git/objects/8d/bcb0b270e9ab441407005a96638c37851679e0 new file mode 100644 index 0000000..9d05ed9 Binary files /dev/null and b/.git/objects/8d/bcb0b270e9ab441407005a96638c37851679e0 differ diff --git a/.git/objects/8d/bf0a051f6ae4e1ccf862beca48057a7c1718b9 b/.git/objects/8d/bf0a051f6ae4e1ccf862beca48057a7c1718b9 new file mode 100644 index 0000000..75febff Binary files /dev/null and b/.git/objects/8d/bf0a051f6ae4e1ccf862beca48057a7c1718b9 differ diff --git a/.git/objects/8e/27885f396ffd60d2179604a041049a4f698cef b/.git/objects/8e/27885f396ffd60d2179604a041049a4f698cef new file mode 100644 index 0000000..03c7003 Binary files /dev/null and b/.git/objects/8e/27885f396ffd60d2179604a041049a4f698cef differ diff --git a/.git/objects/8e/2d75a30a8940c5b234d5cecd62e194ec428656 b/.git/objects/8e/2d75a30a8940c5b234d5cecd62e194ec428656 new file mode 100644 index 0000000..def7670 Binary files /dev/null and b/.git/objects/8e/2d75a30a8940c5b234d5cecd62e194ec428656 differ diff --git a/.git/objects/8e/4b058300f3c8686a235f10461ba5ed707618fd b/.git/objects/8e/4b058300f3c8686a235f10461ba5ed707618fd new file mode 100644 index 0000000..b51bec6 Binary files /dev/null and b/.git/objects/8e/4b058300f3c8686a235f10461ba5ed707618fd differ diff --git a/.git/objects/8e/6b4fe2fd621df796883ca8e9d05846980958f4 b/.git/objects/8e/6b4fe2fd621df796883ca8e9d05846980958f4 new file mode 100644 index 0000000..f85c305 --- /dev/null +++ b/.git/objects/8e/6b4fe2fd621df796883ca8e9d05846980958f4 @@ -0,0 +1,2 @@ +x%J0E]+K) 2Bw/k'&%Mzp\ZPCuW23Ikme(QthMQX}&TNst$C&)LCG /o+'8+pouidn-R(G!hs`{8kOBx2rzӔ02 +sH<\k]]Y \ No newline at end of file diff --git a/.git/objects/8f/a51baea2d0aedd290c0c0c13fc7fdc21dc48e4 b/.git/objects/8f/a51baea2d0aedd290c0c0c13fc7fdc21dc48e4 new file mode 100644 index 0000000..b2fa246 Binary files /dev/null and b/.git/objects/8f/a51baea2d0aedd290c0c0c13fc7fdc21dc48e4 differ diff --git a/.git/objects/8f/a869c141692986e29275c3c1a568aae9ffe3fa b/.git/objects/8f/a869c141692986e29275c3c1a568aae9ffe3fa new file mode 100644 index 0000000..0d17775 Binary files /dev/null and b/.git/objects/8f/a869c141692986e29275c3c1a568aae9ffe3fa differ diff --git a/.git/objects/8f/be27e679793f29c99bd581d10f7562fb65c74b b/.git/objects/8f/be27e679793f29c99bd581d10f7562fb65c74b new file mode 100644 index 0000000..cb465dd --- /dev/null +++ b/.git/objects/8f/be27e679793f29c99bd581d10f7562fb65c74b @@ -0,0 +1,2 @@ +xKN0DYr%vDؑc4f۪S=*۶4rk1'#KF7- j5Azo$cMCbFcR:>Drb"6 +/+aN\uypGsy2G eRn_DB1d%_aBؖ =g \ No newline at end of file diff --git a/.git/objects/8f/c9c365636ab53e6e882ddeffe9050a3ad4e7f2 b/.git/objects/8f/c9c365636ab53e6e882ddeffe9050a3ad4e7f2 new file mode 100644 index 0000000..8fc9763 Binary files /dev/null and b/.git/objects/8f/c9c365636ab53e6e882ddeffe9050a3ad4e7f2 differ diff --git a/.git/objects/90/06ee3ea2310a1d5141bf99d3c14031568fd600 b/.git/objects/90/06ee3ea2310a1d5141bf99d3c14031568fd600 new file mode 100644 index 0000000..b7c33b5 --- /dev/null +++ b/.git/objects/90/06ee3ea2310a1d5141bf99d3c14031568fd600 @@ -0,0 +1,2 @@ +xAO@=d[x OµٶcbgwMd/og޼o7̊W'7Maa Q2q4[=U:"UhST́f0AW㦺 7RW~O{=8vZ5hndX&$^?8[a \ No newline at end of file diff --git a/.git/objects/90/71ccf769d315db118f71148a374f1a6fe5f814 b/.git/objects/90/71ccf769d315db118f71148a374f1a6fe5f814 new file mode 100644 index 0000000..8e9b374 Binary files /dev/null and b/.git/objects/90/71ccf769d315db118f71148a374f1a6fe5f814 differ diff --git a/.git/objects/90/7ce1c928da833af007b5764b879700a108eb34 b/.git/objects/90/7ce1c928da833af007b5764b879700a108eb34 new file mode 100644 index 0000000..f8f5900 --- /dev/null +++ b/.git/objects/90/7ce1c928da833af007b5764b879700a108eb34 @@ -0,0 +1 @@ +x5J0])^,IK'8MO`47sw?Ϧ|a]D0sw2(,g։Q)͉[)TcX1i#9)&attRr$ϘkYSgmvP3RVZ[%9\R6G1{۸Ky^?5#mjv\JqLy06? ETi_(B/X$ \ No newline at end of file diff --git a/.git/objects/90/846cb8d2f67ff5da208748a2f47cc175c29216 b/.git/objects/90/846cb8d2f67ff5da208748a2f47cc175c29216 new file mode 100644 index 0000000..846ad6d Binary files /dev/null and b/.git/objects/90/846cb8d2f67ff5da208748a2f47cc175c29216 differ diff --git a/.git/objects/90/883beb63e8eca0abd63002c86e8868df264341 b/.git/objects/90/883beb63e8eca0abd63002c86e8868df264341 new file mode 100644 index 0000000..76a1c1b Binary files /dev/null and b/.git/objects/90/883beb63e8eca0abd63002c86e8868df264341 differ diff --git a/.git/objects/90/a957ed2295e285f021780ea1f0489327dc6d97 b/.git/objects/90/a957ed2295e285f021780ea1f0489327dc6d97 new file mode 100644 index 0000000..f3d9267 Binary files /dev/null and b/.git/objects/90/a957ed2295e285f021780ea1f0489327dc6d97 differ diff --git a/.git/objects/90/abe2c62d19bff914871c64cbab692d4c1c0275 b/.git/objects/90/abe2c62d19bff914871c64cbab692d4c1c0275 new file mode 100644 index 0000000..5ef1051 Binary files /dev/null and b/.git/objects/90/abe2c62d19bff914871c64cbab692d4c1c0275 differ diff --git a/.git/objects/90/c79d0464270730419b6153a38bc74a0e966a2e b/.git/objects/90/c79d0464270730419b6153a38bc74a0e966a2e new file mode 100644 index 0000000..ddfaf51 Binary files /dev/null and b/.git/objects/90/c79d0464270730419b6153a38bc74a0e966a2e differ diff --git a/.git/objects/90/da3ae7f446755b973caf6c6aebaf0b1607d94e b/.git/objects/90/da3ae7f446755b973caf6c6aebaf0b1607d94e new file mode 100644 index 0000000..f5b4e2a --- /dev/null +++ b/.git/objects/90/da3ae7f446755b973caf6c6aebaf0b1607d94e @@ -0,0 +1,2 @@ +x%OJ0tݯ8{i-\N7~Irۤ)c bƦu J&+!;)#g iNF{,{ZXl) % +T%#TG$27x<ʜ2,t(Gis?94WK8x6WȴGk*[w:{F\q9B5޼;n{|BK_;>mÉ_\ \ No newline at end of file diff --git a/.git/objects/91/050dc2272b8b3fbca62ede543a0c798635a511 b/.git/objects/91/050dc2272b8b3fbca62ede543a0c798635a511 new file mode 100644 index 0000000..8d5a966 Binary files /dev/null and b/.git/objects/91/050dc2272b8b3fbca62ede543a0c798635a511 differ diff --git a/.git/objects/91/07119a4073fae7e66e9e3b8376828a92d1ce42 b/.git/objects/91/07119a4073fae7e66e9e3b8376828a92d1ce42 new file mode 100644 index 0000000..5562607 Binary files /dev/null and b/.git/objects/91/07119a4073fae7e66e9e3b8376828a92d1ce42 differ diff --git a/.git/objects/91/1b42e0f9cbd1ff164cbc8dd898a1371c72eb7f b/.git/objects/91/1b42e0f9cbd1ff164cbc8dd898a1371c72eb7f new file mode 100644 index 0000000..25e493b Binary files /dev/null and b/.git/objects/91/1b42e0f9cbd1ff164cbc8dd898a1371c72eb7f differ diff --git a/.git/objects/91/378fc7bc8b4124b24206051afcdb08b0d7fbc6 b/.git/objects/91/378fc7bc8b4124b24206051afcdb08b0d7fbc6 new file mode 100644 index 0000000..75a93e0 Binary files /dev/null and b/.git/objects/91/378fc7bc8b4124b24206051afcdb08b0d7fbc6 differ diff --git a/.git/objects/91/442a6ab1d1af38b807f33b638e2ad7c3b5e177 b/.git/objects/91/442a6ab1d1af38b807f33b638e2ad7c3b5e177 new file mode 100644 index 0000000..a36a106 Binary files /dev/null and b/.git/objects/91/442a6ab1d1af38b807f33b638e2ad7c3b5e177 differ diff --git a/.git/objects/91/74a340c071f953774878649728a87a0448a6de b/.git/objects/91/74a340c071f953774878649728a87a0448a6de new file mode 100644 index 0000000..c3399c0 Binary files /dev/null and b/.git/objects/91/74a340c071f953774878649728a87a0448a6de differ diff --git a/.git/objects/91/c0e58802496af7d4e1f07da04bd34617b86c16 b/.git/objects/91/c0e58802496af7d4e1f07da04bd34617b86c16 new file mode 100644 index 0000000..edae3e5 Binary files /dev/null and b/.git/objects/91/c0e58802496af7d4e1f07da04bd34617b86c16 differ diff --git a/.git/objects/91/c5f476770dd85ad0f76adf29ce999107122f7e b/.git/objects/91/c5f476770dd85ad0f76adf29ce999107122f7e new file mode 100644 index 0000000..7ffcfe9 Binary files /dev/null and b/.git/objects/91/c5f476770dd85ad0f76adf29ce999107122f7e differ diff --git a/.git/objects/91/c83906f61f6b5c0aba6e36353c0f64a5995c58 b/.git/objects/91/c83906f61f6b5c0aba6e36353c0f64a5995c58 new file mode 100644 index 0000000..66e86ad Binary files /dev/null and b/.git/objects/91/c83906f61f6b5c0aba6e36353c0f64a5995c58 differ diff --git a/.git/objects/91/e29d82dc8b1b0e6869e986faaa2c7af27e3d62 b/.git/objects/91/e29d82dc8b1b0e6869e986faaa2c7af27e3d62 new file mode 100644 index 0000000..63ad67b Binary files /dev/null and b/.git/objects/91/e29d82dc8b1b0e6869e986faaa2c7af27e3d62 differ diff --git a/.git/objects/92/0babe3e60392d9b0abc5ee3585c89c61cd3176 b/.git/objects/92/0babe3e60392d9b0abc5ee3585c89c61cd3176 new file mode 100644 index 0000000..126a2ee Binary files /dev/null and b/.git/objects/92/0babe3e60392d9b0abc5ee3585c89c61cd3176 differ diff --git a/.git/objects/92/12633f53e0a66afcc2bc0f179be967adb25b25 b/.git/objects/92/12633f53e0a66afcc2bc0f179be967adb25b25 new file mode 100644 index 0000000..7ef868f Binary files /dev/null and b/.git/objects/92/12633f53e0a66afcc2bc0f179be967adb25b25 differ diff --git a/.git/objects/92/18a808ddf5681e986cbe0dbc4588d21a1f8d78 b/.git/objects/92/18a808ddf5681e986cbe0dbc4588d21a1f8d78 new file mode 100644 index 0000000..727c5af --- /dev/null +++ b/.git/objects/92/18a808ddf5681e986cbe0dbc4588d21a1f8d78 @@ -0,0 +1 @@ +x]J1})Q$3xNgga'Y2YpnoEUQ|Uڶ]8Fgo%Oa *yF !ul]r \ No newline at end of file diff --git a/.git/objects/93/d71f630a49fc57938470c114e545367fefcb4c b/.git/objects/93/d71f630a49fc57938470c114e545367fefcb4c new file mode 100644 index 0000000..4130fda Binary files /dev/null and b/.git/objects/93/d71f630a49fc57938470c114e545367fefcb4c differ diff --git a/.git/objects/93/e117101770c61c6f10386532159da9fdc6b7e3 b/.git/objects/93/e117101770c61c6f10386532159da9fdc6b7e3 new file mode 100644 index 0000000..2153f87 Binary files /dev/null and b/.git/objects/93/e117101770c61c6f10386532159da9fdc6b7e3 differ diff --git a/.git/objects/93/e11ae71d37d82ccaabc0205f5cff3743204af3 b/.git/objects/93/e11ae71d37d82ccaabc0205f5cff3743204af3 new file mode 100644 index 0000000..8e468f7 Binary files /dev/null and b/.git/objects/93/e11ae71d37d82ccaabc0205f5cff3743204af3 differ diff --git a/.git/objects/93/f59469f891dd5ee7cef082e38730e9d7cd219c b/.git/objects/93/f59469f891dd5ee7cef082e38730e9d7cd219c new file mode 100644 index 0000000..67b220d --- /dev/null +++ b/.git/objects/93/f59469f891dd5ee7cef082e38730e9d7cd219c @@ -0,0 +1,3 @@ +x%NKN0eSQٱ' +@,`쌛ڮGЛb{=B )rlzyӨ}Gb7g KV;n@9hr-Vy H,vZ_G2tsvT}xeR)QZB +T.uqai q#jp'֛d?ؕE:rɃ}^^W^+ykG,a \ No newline at end of file diff --git a/.git/objects/94/0f054e7e042216355fc43f2f972e41bb11ec12 b/.git/objects/94/0f054e7e042216355fc43f2f972e41bb11ec12 new file mode 100644 index 0000000..3add421 Binary files /dev/null and b/.git/objects/94/0f054e7e042216355fc43f2f972e41bb11ec12 differ diff --git a/.git/objects/94/0fa2f4192d64599bfbc2fc8ee5a045cecf48cd b/.git/objects/94/0fa2f4192d64599bfbc2fc8ee5a045cecf48cd new file mode 100644 index 0000000..b9e00c2 Binary files /dev/null and b/.git/objects/94/0fa2f4192d64599bfbc2fc8ee5a045cecf48cd differ diff --git a/.git/objects/94/1d025c126ecf48669c8852046122381923d723 b/.git/objects/94/1d025c126ecf48669c8852046122381923d723 new file mode 100644 index 0000000..938a685 Binary files /dev/null and b/.git/objects/94/1d025c126ecf48669c8852046122381923d723 differ diff --git a/.git/objects/94/23e3331ab58411d82ea3950e2871f4ea39ab88 b/.git/objects/94/23e3331ab58411d82ea3950e2871f4ea39ab88 new file mode 100644 index 0000000..eab580a Binary files /dev/null and b/.git/objects/94/23e3331ab58411d82ea3950e2871f4ea39ab88 differ diff --git a/.git/objects/94/47ab3b0da127fa533dd913180c628dd733b92b b/.git/objects/94/47ab3b0da127fa533dd913180c628dd733b92b new file mode 100644 index 0000000..03b3754 Binary files /dev/null and b/.git/objects/94/47ab3b0da127fa533dd913180c628dd733b92b differ diff --git a/.git/objects/94/6f2008718f01c29aa9f79ee020644b59126eb2 b/.git/objects/94/6f2008718f01c29aa9f79ee020644b59126eb2 new file mode 100644 index 0000000..d4491dd Binary files /dev/null and b/.git/objects/94/6f2008718f01c29aa9f79ee020644b59126eb2 differ diff --git a/.git/objects/94/9334bc0434f67d6b9118e14590ad28cebbb565 b/.git/objects/94/9334bc0434f67d6b9118e14590ad28cebbb565 new file mode 100644 index 0000000..df1b2e1 Binary files /dev/null and b/.git/objects/94/9334bc0434f67d6b9118e14590ad28cebbb565 differ diff --git a/.git/objects/94/b5071dca6e800631f9036b4aedbceee686d5ee b/.git/objects/94/b5071dca6e800631f9036b4aedbceee686d5ee new file mode 100644 index 0000000..73e66c6 Binary files /dev/null and b/.git/objects/94/b5071dca6e800631f9036b4aedbceee686d5ee differ diff --git a/.git/objects/94/da5f2e14ecc611db2ef54761f8d1261b3a04c4 b/.git/objects/94/da5f2e14ecc611db2ef54761f8d1261b3a04c4 new file mode 100644 index 0000000..dced703 Binary files /dev/null and b/.git/objects/94/da5f2e14ecc611db2ef54761f8d1261b3a04c4 differ diff --git a/.git/objects/95/09ae901ca1c1fa8d38ffc1e1967c140680d9d6 b/.git/objects/95/09ae901ca1c1fa8d38ffc1e1967c140680d9d6 new file mode 100644 index 0000000..5d8a7fe Binary files /dev/null and b/.git/objects/95/09ae901ca1c1fa8d38ffc1e1967c140680d9d6 differ diff --git a/.git/objects/95/24dac5dacaa69d020af21fd7be1f9822ad8e28 b/.git/objects/95/24dac5dacaa69d020af21fd7be1f9822ad8e28 new file mode 100644 index 0000000..3149208 Binary files /dev/null and b/.git/objects/95/24dac5dacaa69d020af21fd7be1f9822ad8e28 differ diff --git a/.git/objects/95/42a29039f70707e5db01aacc546ae209ae43a5 b/.git/objects/95/42a29039f70707e5db01aacc546ae209ae43a5 new file mode 100644 index 0000000..cb6856c Binary files /dev/null and b/.git/objects/95/42a29039f70707e5db01aacc546ae209ae43a5 differ diff --git a/.git/objects/95/48ff51306a38923f5becdadb9a4614b4b423e8 b/.git/objects/95/48ff51306a38923f5becdadb9a4614b4b423e8 new file mode 100644 index 0000000..b535568 Binary files /dev/null and b/.git/objects/95/48ff51306a38923f5becdadb9a4614b4b423e8 differ diff --git a/.git/objects/95/560854afff19d588f3c10c696193d250ad90d8 b/.git/objects/95/560854afff19d588f3c10c696193d250ad90d8 new file mode 100644 index 0000000..7e3e68f Binary files /dev/null and b/.git/objects/95/560854afff19d588f3c10c696193d250ad90d8 differ diff --git a/.git/objects/95/6e5391def0c3d9225fa969c0760bade43d2ec5 b/.git/objects/95/6e5391def0c3d9225fa969c0760bade43d2ec5 new file mode 100644 index 0000000..5955016 --- /dev/null +++ b/.git/objects/95/6e5391def0c3d9225fa969c0760bade43d2ec5 @@ -0,0 +1 @@ +x%An E)f_5Ju 0Q XͺŊckP LVp5qTJ[NVXѫA {+[P Bz9rdN3VýιB_<x./x($=ՙv't?_s8c]S[8os sb =>p u{ xb;Z¸א3F]*VHqlصv[ \ No newline at end of file diff --git a/.git/objects/95/807fbc3ed6e1e65bd6e80c7e249e8744cd7430 b/.git/objects/95/807fbc3ed6e1e65bd6e80c7e249e8744cd7430 new file mode 100644 index 0000000..b32ce39 Binary files /dev/null and b/.git/objects/95/807fbc3ed6e1e65bd6e80c7e249e8744cd7430 differ diff --git a/.git/objects/95/a38adbdc8d9c0f6647db2720c3722653430061 b/.git/objects/95/a38adbdc8d9c0f6647db2720c3722653430061 new file mode 100644 index 0000000..ff745ad Binary files /dev/null and b/.git/objects/95/a38adbdc8d9c0f6647db2720c3722653430061 differ diff --git a/.git/objects/95/d93a09c2d7ae8a8c2f4f33e462c22ec9130048 b/.git/objects/95/d93a09c2d7ae8a8c2f4f33e462c22ec9130048 new file mode 100644 index 0000000..9c6e964 --- /dev/null +++ b/.git/objects/95/d93a09c2d7ae8a8c2f4f33e462c22ec9130048 @@ -0,0 +1 @@ +xMN0 Y#$_B yC+S*s1|Yy>g}00:C8)N[h"ɛ)[コNmFx,v2"@(q7BZGU.}VA >~z^ocE yc]gxVk%W=$vnp)2ۀi!,(Ѡ'cv?%h' \ No newline at end of file diff --git a/.git/objects/95/e0529d5846f96126b269e974e14da129e300ba b/.git/objects/95/e0529d5846f96126b269e974e14da129e300ba new file mode 100644 index 0000000..fc361f9 Binary files /dev/null and b/.git/objects/95/e0529d5846f96126b269e974e14da129e300ba differ diff --git a/.git/objects/95/e3d93d5d96af523405be59de96f41787033e59 b/.git/objects/95/e3d93d5d96af523405be59de96f41787033e59 new file mode 100644 index 0000000..8f7ee88 Binary files /dev/null and b/.git/objects/95/e3d93d5d96af523405be59de96f41787033e59 differ diff --git a/.git/objects/95/e812faebc4785660c80bf5750b35a5f6301811 b/.git/objects/95/e812faebc4785660c80bf5750b35a5f6301811 new file mode 100644 index 0000000..3bc37b2 Binary files /dev/null and b/.git/objects/95/e812faebc4785660c80bf5750b35a5f6301811 differ diff --git a/.git/objects/96/18891b96fc23885044bceb078f5cb75373c418 b/.git/objects/96/18891b96fc23885044bceb078f5cb75373c418 new file mode 100644 index 0000000..681ffba Binary files /dev/null and b/.git/objects/96/18891b96fc23885044bceb078f5cb75373c418 differ diff --git a/.git/objects/96/283597a052280f3234d95affc5775ad7ccd218 b/.git/objects/96/283597a052280f3234d95affc5775ad7ccd218 new file mode 100644 index 0000000..265e16c Binary files /dev/null and b/.git/objects/96/283597a052280f3234d95affc5775ad7ccd218 differ diff --git a/.git/objects/96/2939a838bdcc71ca22fa49f424cc14245f9351 b/.git/objects/96/2939a838bdcc71ca22fa49f424cc14245f9351 new file mode 100644 index 0000000..4582f80 Binary files /dev/null and b/.git/objects/96/2939a838bdcc71ca22fa49f424cc14245f9351 differ diff --git a/.git/objects/96/8569b3fa17b7dd52adfe61f240001e63998415 b/.git/objects/96/8569b3fa17b7dd52adfe61f240001e63998415 new file mode 100644 index 0000000..14f70d3 --- /dev/null +++ b/.git/objects/96/8569b3fa17b7dd52adfe61f240001e63998415 @@ -0,0 +1,3 @@ +x=N0Fs1BhhxH]ہf\<5ԪNTRA ښFJauZT3%HAÊY8jQ^Cj]EKcW +<>Neg872/|B*l; (2k@!V ¹Yn);| eyu pġJ>x%Abj7uo9wPŵO$ nyi \ No newline at end of file diff --git a/.git/objects/97/70cc95836810748102b04ca2c35541398cf35c b/.git/objects/97/70cc95836810748102b04ca2c35541398cf35c new file mode 100644 index 0000000..1df4011 --- /dev/null +++ b/.git/objects/97/70cc95836810748102b04ca2c35541398cf35c @@ -0,0 +1,2 @@ +x-N0D9+'cTV˅/ج׉Į?ΏUFyJ +HkJfӉ1,y[x{βnQP]1s,Iruڣ"!"#Gm+Rm_V47F>+GɑW8I5 JUo,< )DEeyrX<moP^vJÅ1NR )f( | 6 ѹGk:c \ No newline at end of file diff --git a/.git/objects/97/b21932a884646e12cb35ee323e96df09de21c1 b/.git/objects/97/b21932a884646e12cb35ee323e96df09de21c1 new file mode 100644 index 0000000..872d06e Binary files /dev/null and b/.git/objects/97/b21932a884646e12cb35ee323e96df09de21c1 differ diff --git a/.git/objects/97/e393c668706bdb16bdd8e2ed74bb88028e1efb b/.git/objects/97/e393c668706bdb16bdd8e2ed74bb88028e1efb new file mode 100644 index 0000000..174dc3f Binary files /dev/null and b/.git/objects/97/e393c668706bdb16bdd8e2ed74bb88028e1efb differ diff --git a/.git/objects/98/0b20e7c37b26aef65caae1e7441b5dde81a0bd b/.git/objects/98/0b20e7c37b26aef65caae1e7441b5dde81a0bd new file mode 100644 index 0000000..8752862 Binary files /dev/null and b/.git/objects/98/0b20e7c37b26aef65caae1e7441b5dde81a0bd differ diff --git a/.git/objects/98/18b639461c156fde7675f2a55c207dcae464a3 b/.git/objects/98/18b639461c156fde7675f2a55c207dcae464a3 new file mode 100644 index 0000000..8ac568d Binary files /dev/null and b/.git/objects/98/18b639461c156fde7675f2a55c207dcae464a3 differ diff --git a/.git/objects/98/3726e8507f2646efacf7cb541ec7d5ebefaad6 b/.git/objects/98/3726e8507f2646efacf7cb541ec7d5ebefaad6 new file mode 100644 index 0000000..1690352 Binary files /dev/null and b/.git/objects/98/3726e8507f2646efacf7cb541ec7d5ebefaad6 differ diff --git a/.git/objects/98/7f440612b992cd226c14ae024b5906749d3164 b/.git/objects/98/7f440612b992cd226c14ae024b5906749d3164 new file mode 100644 index 0000000..9d6e880 Binary files /dev/null and b/.git/objects/98/7f440612b992cd226c14ae024b5906749d3164 differ diff --git a/.git/objects/98/83fc0a482cae71a8735b35bb43150b580937fb b/.git/objects/98/83fc0a482cae71a8735b35bb43150b580937fb new file mode 100644 index 0000000..9fab57a Binary files /dev/null and b/.git/objects/98/83fc0a482cae71a8735b35bb43150b580937fb differ diff --git a/.git/objects/99/27ad90db85367de64c7e7e9552236d3c4cef76 b/.git/objects/99/27ad90db85367de64c7e7e9552236d3c4cef76 new file mode 100644 index 0000000..8b06fc6 Binary files /dev/null and b/.git/objects/99/27ad90db85367de64c7e7e9552236d3c4cef76 differ diff --git a/.git/objects/99/362ac9fc6764635a8f6db7710848c73d6e83ee b/.git/objects/99/362ac9fc6764635a8f6db7710848c73d6e83ee new file mode 100644 index 0000000..1817c99 Binary files /dev/null and b/.git/objects/99/362ac9fc6764635a8f6db7710848c73d6e83ee differ diff --git a/.git/objects/99/64749f5a6ace6623ebb323b9b6b0a4425dedfd b/.git/objects/99/64749f5a6ace6623ebb323b9b6b0a4425dedfd new file mode 100644 index 0000000..3cee658 Binary files /dev/null and b/.git/objects/99/64749f5a6ace6623ebb323b9b6b0a4425dedfd differ diff --git a/.git/objects/99/915f89123307c13cda43e32e0d6c4ff57aa4b4 b/.git/objects/99/915f89123307c13cda43e32e0d6c4ff57aa4b4 new file mode 100644 index 0000000..184d50c Binary files /dev/null and b/.git/objects/99/915f89123307c13cda43e32e0d6c4ff57aa4b4 differ diff --git a/.git/objects/99/941e99078ec44da641ca4af7f67ffa38c72538 b/.git/objects/99/941e99078ec44da641ca4af7f67ffa38c72538 new file mode 100644 index 0000000..680e9e3 Binary files /dev/null and b/.git/objects/99/941e99078ec44da641ca4af7f67ffa38c72538 differ diff --git a/.git/objects/99/a8185868928d8b3de78922e09c451a6916239c b/.git/objects/99/a8185868928d8b3de78922e09c451a6916239c new file mode 100644 index 0000000..63f1d86 --- /dev/null +++ b/.git/objects/99/a8185868928d8b3de78922e09c451a6916239c @@ -0,0 +1,5 @@ +xTk0gאMؗIX7k +]e lc Yr!w؉3ݻwOJNW/.fA]yNh}| T&}e06Cs/SW"T\(G/PډBd n*l}w;•iP]Zw W|Ep-4WyWPh dCx-tY"$@QB \Z p)!Ơr.D=mZ6,z` O&t6)x +͇`VjTlSu>P#̿QWB!ual] +P5<Ͳ@'ٱO0ԍqb3P4(/)Z@8EgʟG8ňr<8&i-|r@໋{=n2z {Mc!T,},FFۙ*B￱Kѱ3N{nVځj>׭WCԗ:7 yIǚUб9a:$~-N1r +yA/K \ No newline at end of file diff --git a/.git/objects/99/b1e2274339d45865929f45a686d648743982ec b/.git/objects/99/b1e2274339d45865929f45a686d648743982ec new file mode 100644 index 0000000..ead4e50 Binary files /dev/null and b/.git/objects/99/b1e2274339d45865929f45a686d648743982ec differ diff --git a/.git/objects/99/c9c274e535215256d71a1faecd6d3d52244ee6 b/.git/objects/99/c9c274e535215256d71a1faecd6d3d52244ee6 new file mode 100644 index 0000000..23481bd Binary files /dev/null and b/.git/objects/99/c9c274e535215256d71a1faecd6d3d52244ee6 differ diff --git a/.git/objects/99/f9d5742736191d2d5ef33d34574172e7dc4fcc b/.git/objects/99/f9d5742736191d2d5ef33d34574172e7dc4fcc new file mode 100644 index 0000000..29f8883 Binary files /dev/null and b/.git/objects/99/f9d5742736191d2d5ef33d34574172e7dc4fcc differ diff --git a/.git/objects/9a/1eb672c688882111342dadb7c25802ab9de894 b/.git/objects/9a/1eb672c688882111342dadb7c25802ab9de894 new file mode 100644 index 0000000..0bd67d6 Binary files /dev/null and b/.git/objects/9a/1eb672c688882111342dadb7c25802ab9de894 differ diff --git a/.git/objects/9a/43a0ac095959ab5a6f3e6a34a3b51d0915a57f b/.git/objects/9a/43a0ac095959ab5a6f3e6a34a3b51d0915a57f new file mode 100644 index 0000000..f34e90c Binary files /dev/null and b/.git/objects/9a/43a0ac095959ab5a6f3e6a34a3b51d0915a57f differ diff --git a/.git/objects/9a/4e11ac6e57d5a7269adfb0a64a1553b5b3642d b/.git/objects/9a/4e11ac6e57d5a7269adfb0a64a1553b5b3642d new file mode 100644 index 0000000..1497fa6 Binary files /dev/null and b/.git/objects/9a/4e11ac6e57d5a7269adfb0a64a1553b5b3642d differ diff --git a/.git/objects/9a/75850576430791bbf8ebf58e585986c3cc13a9 b/.git/objects/9a/75850576430791bbf8ebf58e585986c3cc13a9 new file mode 100644 index 0000000..d135158 Binary files /dev/null and b/.git/objects/9a/75850576430791bbf8ebf58e585986c3cc13a9 differ diff --git a/.git/objects/9a/7e633e84075cc74e94dc21fe4bc79e2fac4458 b/.git/objects/9a/7e633e84075cc74e94dc21fe4bc79e2fac4458 new file mode 100644 index 0000000..9fce02f Binary files /dev/null and b/.git/objects/9a/7e633e84075cc74e94dc21fe4bc79e2fac4458 differ diff --git a/.git/objects/9a/c39b46e6ce900d44801e187ab8bd715e97acff b/.git/objects/9a/c39b46e6ce900d44801e187ab8bd715e97acff new file mode 100644 index 0000000..7fbdfe9 Binary files /dev/null and b/.git/objects/9a/c39b46e6ce900d44801e187ab8bd715e97acff differ diff --git a/.git/objects/9a/cdadfc34422bf9e54113876fdcde5c53cbe0c0 b/.git/objects/9a/cdadfc34422bf9e54113876fdcde5c53cbe0c0 new file mode 100644 index 0000000..841974e --- /dev/null +++ b/.git/objects/9a/cdadfc34422bf9e54113876fdcde5c53cbe0c0 @@ -0,0 +1 @@ +x-MN0 Y#4BX\v&4s1ˆ͓%ُҺT/Jf7X"I75Y7W D:9)zSE *^e/3͔m;Gu{,OՒ8xk) euFixJy)#hG\-?N[xƛ! rˆckzX, \ No newline at end of file diff --git a/.git/objects/9a/ebba1896c9b381c2f67b6f5ff4e18ac40db28b b/.git/objects/9a/ebba1896c9b381c2f67b6f5ff4e18ac40db28b new file mode 100644 index 0000000..7f67ac7 Binary files /dev/null and b/.git/objects/9a/ebba1896c9b381c2f67b6f5ff4e18ac40db28b differ diff --git a/.git/objects/9a/f0994fbbebcfcd672e30cadf9381b8d0c5752f b/.git/objects/9a/f0994fbbebcfcd672e30cadf9381b8d0c5752f new file mode 100644 index 0000000..58ff066 Binary files /dev/null and b/.git/objects/9a/f0994fbbebcfcd672e30cadf9381b8d0c5752f differ diff --git a/.git/objects/9a/f5a29e51cc95bc11a3e96f63b2c6ee21e6165c b/.git/objects/9a/f5a29e51cc95bc11a3e96f63b2c6ee21e6165c new file mode 100644 index 0000000..39a53e1 Binary files /dev/null and b/.git/objects/9a/f5a29e51cc95bc11a3e96f63b2c6ee21e6165c differ diff --git a/.git/objects/9b/0e8fb5d0e2c6581487009c5ebf625a1291d46d b/.git/objects/9b/0e8fb5d0e2c6581487009c5ebf625a1291d46d new file mode 100644 index 0000000..5782e47 Binary files /dev/null and b/.git/objects/9b/0e8fb5d0e2c6581487009c5ebf625a1291d46d differ diff --git a/.git/objects/9b/80de6524d7da5f6b490acb737bfdd5daa2d262 b/.git/objects/9b/80de6524d7da5f6b490acb737bfdd5daa2d262 new file mode 100644 index 0000000..df84f5e Binary files /dev/null and b/.git/objects/9b/80de6524d7da5f6b490acb737bfdd5daa2d262 differ diff --git a/.git/objects/9b/882b3ac314a889c5f5d045327636988011d61a b/.git/objects/9b/882b3ac314a889c5f5d045327636988011d61a new file mode 100644 index 0000000..b13853c Binary files /dev/null and b/.git/objects/9b/882b3ac314a889c5f5d045327636988011d61a differ diff --git a/.git/objects/9b/8a9681b56aa0a8556e976c26afa58e466c64f2 b/.git/objects/9b/8a9681b56aa0a8556e976c26afa58e466c64f2 new file mode 100644 index 0000000..883d590 Binary files /dev/null and b/.git/objects/9b/8a9681b56aa0a8556e976c26afa58e466c64f2 differ diff --git a/.git/objects/9b/92c2221c679eddd1c00a2c83f6406d137c7b50 b/.git/objects/9b/92c2221c679eddd1c00a2c83f6406d137c7b50 new file mode 100644 index 0000000..614a6ad --- /dev/null +++ b/.git/objects/9b/92c2221c679eddd1c00a2c83f6406d137c7b50 @@ -0,0 +1,4 @@ +x5J0])RK #J\'J ):o3~:3Hm8vYzV +!7~ԺZyt3& + z6JqDFJ`d[vn< }a)ₗL?)PtM=b. +@*nsҜ9عOq<4nV w/5##rD8͔q ~}SE[ \ No newline at end of file diff --git a/.git/objects/9b/9d3378aa45140c8da3e9128c68cae5fee3343c b/.git/objects/9b/9d3378aa45140c8da3e9128c68cae5fee3343c new file mode 100644 index 0000000..fc51d59 --- /dev/null +++ b/.git/objects/9b/9d3378aa45140c8da3e9128c68cae5fee3343c @@ -0,0 +1 @@ +xKN0DYGBt !`'hLFψ{.Jqlw[𒱦1}IC>B54:>1]a5^BlI.TmӺB?LO2ڗ~iLjZnZgCXaG3tx/Tj#WPC8^2V*mcm\g \ No newline at end of file diff --git a/.git/objects/9b/ab41517220ddf5ba2ec5726d59e75ffe641c75 b/.git/objects/9b/ab41517220ddf5ba2ec5726d59e75ffe641c75 new file mode 100644 index 0000000..d624f4f Binary files /dev/null and b/.git/objects/9b/ab41517220ddf5ba2ec5726d59e75ffe641c75 differ diff --git a/.git/objects/9c/38fa8e0e9953647190d868c47b03ffbbfbe02c b/.git/objects/9c/38fa8e0e9953647190d868c47b03ffbbfbe02c new file mode 100644 index 0000000..09f9645 Binary files /dev/null and b/.git/objects/9c/38fa8e0e9953647190d868c47b03ffbbfbe02c differ diff --git a/.git/objects/9c/3f1286cb44416cbad3487ce8950cb8c42fa7df b/.git/objects/9c/3f1286cb44416cbad3487ce8950cb8c42fa7df new file mode 100644 index 0000000..2911215 Binary files /dev/null and b/.git/objects/9c/3f1286cb44416cbad3487ce8950cb8c42fa7df differ diff --git a/.git/objects/9c/4d0fcff3982c95c0431398c794f12f31da435f b/.git/objects/9c/4d0fcff3982c95c0431398c794f12f31da435f new file mode 100644 index 0000000..1ef5dd4 Binary files /dev/null and b/.git/objects/9c/4d0fcff3982c95c0431398c794f12f31da435f differ diff --git a/.git/objects/9c/6b2b6555b01d711f26c9a22dd1829aed29e83b b/.git/objects/9c/6b2b6555b01d711f26c9a22dd1829aed29e83b new file mode 100644 index 0000000..a2db73a Binary files /dev/null and b/.git/objects/9c/6b2b6555b01d711f26c9a22dd1829aed29e83b differ diff --git a/.git/objects/9c/906bd94bf11f1becc6bbc77fa71e95c4754a96 b/.git/objects/9c/906bd94bf11f1becc6bbc77fa71e95c4754a96 new file mode 100644 index 0000000..50b2c55 Binary files /dev/null and b/.git/objects/9c/906bd94bf11f1becc6bbc77fa71e95c4754a96 differ diff --git a/.git/objects/9c/99f88590f1b819bab63ac7cd90c530ffabd23b b/.git/objects/9c/99f88590f1b819bab63ac7cd90c530ffabd23b new file mode 100644 index 0000000..d92a679 Binary files /dev/null and b/.git/objects/9c/99f88590f1b819bab63ac7cd90c530ffabd23b differ diff --git a/.git/objects/9c/c12c492ddcaebf24c95542688a1d2d65cc27a8 b/.git/objects/9c/c12c492ddcaebf24c95542688a1d2d65cc27a8 new file mode 100644 index 0000000..cd7f4e1 Binary files /dev/null and b/.git/objects/9c/c12c492ddcaebf24c95542688a1d2d65cc27a8 differ diff --git a/.git/objects/9c/e98cb44ebc35fea0d1b72660f1626870e45d2c b/.git/objects/9c/e98cb44ebc35fea0d1b72660f1626870e45d2c new file mode 100644 index 0000000..cb139f7 Binary files /dev/null and b/.git/objects/9c/e98cb44ebc35fea0d1b72660f1626870e45d2c differ diff --git a/.git/objects/9d/453e18e4573d347eab4358464e983076ed6147 b/.git/objects/9d/453e18e4573d347eab4358464e983076ed6147 new file mode 100644 index 0000000..73ed519 Binary files /dev/null and b/.git/objects/9d/453e18e4573d347eab4358464e983076ed6147 differ diff --git a/.git/objects/9d/576eec3f6beba9859602166dfdf5b964543393 b/.git/objects/9d/576eec3f6beba9859602166dfdf5b964543393 new file mode 100644 index 0000000..b8b891a Binary files /dev/null and b/.git/objects/9d/576eec3f6beba9859602166dfdf5b964543393 differ diff --git a/.git/objects/9d/5882d8008df54680183d656a092b76fb693895 b/.git/objects/9d/5882d8008df54680183d656a092b76fb693895 new file mode 100644 index 0000000..886aebe Binary files /dev/null and b/.git/objects/9d/5882d8008df54680183d656a092b76fb693895 differ diff --git a/.git/objects/9d/723dd6f2faa02b434975936ef5f81a5501b629 b/.git/objects/9d/723dd6f2faa02b434975936ef5f81a5501b629 new file mode 100644 index 0000000..cf57750 Binary files /dev/null and b/.git/objects/9d/723dd6f2faa02b434975936ef5f81a5501b629 differ diff --git a/.git/objects/9d/85f8b1e1e86202ab31934a2159d0bafc4ffa13 b/.git/objects/9d/85f8b1e1e86202ab31934a2159d0bafc4ffa13 new file mode 100644 index 0000000..2bd58dc Binary files /dev/null and b/.git/objects/9d/85f8b1e1e86202ab31934a2159d0bafc4ffa13 differ diff --git a/.git/objects/9d/9755348de2c9d55cbe784b8d96f0e7b8d925a6 b/.git/objects/9d/9755348de2c9d55cbe784b8d96f0e7b8d925a6 new file mode 100644 index 0000000..e3a345d Binary files /dev/null and b/.git/objects/9d/9755348de2c9d55cbe784b8d96f0e7b8d925a6 differ diff --git a/.git/objects/9d/a0fca2274ce96d57d891a177ad34ea40351727 b/.git/objects/9d/a0fca2274ce96d57d891a177ad34ea40351727 new file mode 100644 index 0000000..33db163 Binary files /dev/null and b/.git/objects/9d/a0fca2274ce96d57d891a177ad34ea40351727 differ diff --git a/.git/objects/9d/b2c4b701a780463e2f39ce1048238ddeb6bfda b/.git/objects/9d/b2c4b701a780463e2f39ce1048238ddeb6bfda new file mode 100644 index 0000000..c0ae0f2 Binary files /dev/null and b/.git/objects/9d/b2c4b701a780463e2f39ce1048238ddeb6bfda differ diff --git a/.git/objects/9d/c45f619dc9c97551404f5365a9ce13912a3237 b/.git/objects/9d/c45f619dc9c97551404f5365a9ce13912a3237 new file mode 100644 index 0000000..bc46518 Binary files /dev/null and b/.git/objects/9d/c45f619dc9c97551404f5365a9ce13912a3237 differ diff --git a/.git/objects/9d/e276a892105323af0bffdaf8a2a79584a516f0 b/.git/objects/9d/e276a892105323af0bffdaf8a2a79584a516f0 new file mode 100644 index 0000000..9505f95 Binary files /dev/null and b/.git/objects/9d/e276a892105323af0bffdaf8a2a79584a516f0 differ diff --git a/.git/objects/9d/f1f63bca62ea0d287809401339f543598794d8 b/.git/objects/9d/f1f63bca62ea0d287809401339f543598794d8 new file mode 100644 index 0000000..8debf84 Binary files /dev/null and b/.git/objects/9d/f1f63bca62ea0d287809401339f543598794d8 differ diff --git a/.git/objects/9e/02bba95ffd2fe663c2447ea29a2b0723679d51 b/.git/objects/9e/02bba95ffd2fe663c2447ea29a2b0723679d51 new file mode 100644 index 0000000..f2bef80 Binary files /dev/null and b/.git/objects/9e/02bba95ffd2fe663c2447ea29a2b0723679d51 differ diff --git a/.git/objects/9e/492bcf771f7108d8ec9a68dded9d8ae58e20cf b/.git/objects/9e/492bcf771f7108d8ec9a68dded9d8ae58e20cf new file mode 100644 index 0000000..f0a0d26 Binary files /dev/null and b/.git/objects/9e/492bcf771f7108d8ec9a68dded9d8ae58e20cf differ diff --git a/.git/objects/9e/54a6d05c65e6c0ede4b55e9a0efdcd414a1c5d b/.git/objects/9e/54a6d05c65e6c0ede4b55e9a0efdcd414a1c5d new file mode 100644 index 0000000..691f5c0 Binary files /dev/null and b/.git/objects/9e/54a6d05c65e6c0ede4b55e9a0efdcd414a1c5d differ diff --git a/.git/objects/9e/9ae665fb320d4d5bf7a07533260ee1b8dc9b77 b/.git/objects/9e/9ae665fb320d4d5bf7a07533260ee1b8dc9b77 new file mode 100644 index 0000000..b509513 Binary files /dev/null and b/.git/objects/9e/9ae665fb320d4d5bf7a07533260ee1b8dc9b77 differ diff --git a/.git/objects/9e/d113f6dc22bb6cbb03c7b97f91e8de7e69b104 b/.git/objects/9e/d113f6dc22bb6cbb03c7b97f91e8de7e69b104 new file mode 100644 index 0000000..688c4b9 --- /dev/null +++ b/.git/objects/9e/d113f6dc22bb6cbb03c7b97f91e8de7e69b104 @@ -0,0 +1,3 @@ +xMN0Yo_ /IP$ ^&Rb[ s1ΌqqۖZAZ ꜗT={U7ZQ +M$ +xc4Z?NQ:%7t)s0|0qŕn;΁wxsDOn.n "j]*翈͐ GxR b_ƿ%!PJ,1/ؤh \ No newline at end of file diff --git a/.git/objects/9f/52eca642bb3a1814b92260575290844c5b056d b/.git/objects/9f/52eca642bb3a1814b92260575290844c5b056d new file mode 100644 index 0000000..00d35e3 --- /dev/null +++ b/.git/objects/9f/52eca642bb3a1814b92260575290844c5b056d @@ -0,0 +1,3 @@ +xAN E7hb<6iRvgݘܜ{DzsTUfpCvՃ7 1x +h +^(6JTV>z알 b@ݕ:&AGJ_#WxDzйsןyM) ?J>cAHEkKT'; " LHk|ލ}~g4 \ No newline at end of file diff --git a/.git/objects/9f/9a4ecf13d0bcac6380a489f5f70559a3e71d12 b/.git/objects/9f/9a4ecf13d0bcac6380a489f5f70559a3e71d12 new file mode 100644 index 0000000..b47c6f1 Binary files /dev/null and b/.git/objects/9f/9a4ecf13d0bcac6380a489f5f70559a3e71d12 differ diff --git a/.git/objects/9f/c646c47c2c67c9b1457a11eb7ffff8a30fa8bf b/.git/objects/9f/c646c47c2c67c9b1457a11eb7ffff8a30fa8bf new file mode 100644 index 0000000..6c314e2 Binary files /dev/null and b/.git/objects/9f/c646c47c2c67c9b1457a11eb7ffff8a30fa8bf differ diff --git a/.git/objects/9f/e2ab3de70bc9c37fd10c4c8cd7aeca489c8e15 b/.git/objects/9f/e2ab3de70bc9c37fd10c4c8cd7aeca489c8e15 new file mode 100644 index 0000000..2bf0cb3 Binary files /dev/null and b/.git/objects/9f/e2ab3de70bc9c37fd10c4c8cd7aeca489c8e15 differ diff --git a/.git/objects/a0/08fd745b5ccc54c87540851c3b1edc50d1c07b b/.git/objects/a0/08fd745b5ccc54c87540851c3b1edc50d1c07b new file mode 100644 index 0000000..934c609 Binary files /dev/null and b/.git/objects/a0/08fd745b5ccc54c87540851c3b1edc50d1c07b differ diff --git a/.git/objects/a0/33333864b6a8ddc8b77340bd0641aac1244336 b/.git/objects/a0/33333864b6a8ddc8b77340bd0641aac1244336 new file mode 100644 index 0000000..2639a96 Binary files /dev/null and b/.git/objects/a0/33333864b6a8ddc8b77340bd0641aac1244336 differ diff --git a/.git/objects/a0/36637d3e7854514d87d07884fae75aefcec265 b/.git/objects/a0/36637d3e7854514d87d07884fae75aefcec265 new file mode 100644 index 0000000..defc340 Binary files /dev/null and b/.git/objects/a0/36637d3e7854514d87d07884fae75aefcec265 differ diff --git a/.git/objects/a0/772748f61f2e9c18564a0ec1ad7938f8119b91 b/.git/objects/a0/772748f61f2e9c18564a0ec1ad7938f8119b91 new file mode 100644 index 0000000..652c433 Binary files /dev/null and b/.git/objects/a0/772748f61f2e9c18564a0ec1ad7938f8119b91 differ diff --git a/.git/objects/a0/83c9eb0e576fb0a5330b0894891e0e134afd5e b/.git/objects/a0/83c9eb0e576fb0a5330b0894891e0e134afd5e new file mode 100644 index 0000000..ccee850 --- /dev/null +++ b/.git/objects/a0/83c9eb0e576fb0a5330b0894891e0e134afd5e @@ -0,0 +1 @@ +xMJ1]o7 A ] ^'/ D({1v_EQPBݍFhsSdbF[$=Vh;6*tdw^%k4'gL5j+}aeN~[8hR!|!዁{.9gcW#3<+I0Br{)yUL/ϩib \ No newline at end of file diff --git a/.git/objects/a0/84ec499165433375f52a573c67add2ba7cbf3e b/.git/objects/a0/84ec499165433375f52a573c67add2ba7cbf3e new file mode 100644 index 0000000..66d0d12 --- /dev/null +++ b/.git/objects/a0/84ec499165433375f52a573c67add2ba7cbf3e @@ -0,0 +1,3 @@ +x5MN0YGTc'؎TVa &Ic)+ǡfc{Elݳ3+gnBfr켵RT sA4k8c&$vbGeQ; WR=}?%Gj.Js|G~GԈ]s8K rGĉ=npCozx¡ͻ33T +0D +xAn/\W? \ No newline at end of file diff --git a/.git/objects/a0/d7cadd747688e819afb124753125ea8d22f163 b/.git/objects/a0/d7cadd747688e819afb124753125ea8d22f163 new file mode 100644 index 0000000..9a994d7 Binary files /dev/null and b/.git/objects/a0/d7cadd747688e819afb124753125ea8d22f163 differ diff --git a/.git/objects/a1/0c2e9167cdabb5cc5231637a96b92995266c9b b/.git/objects/a1/0c2e9167cdabb5cc5231637a96b92995266c9b new file mode 100644 index 0000000..96b9b6e Binary files /dev/null and b/.git/objects/a1/0c2e9167cdabb5cc5231637a96b92995266c9b differ diff --git a/.git/objects/a1/284e878c9baaf238515f601041f0ecbf2c9173 b/.git/objects/a1/284e878c9baaf238515f601041f0ecbf2c9173 new file mode 100644 index 0000000..7eabf0e Binary files /dev/null and b/.git/objects/a1/284e878c9baaf238515f601041f0ecbf2c9173 differ diff --git a/.git/objects/a1/36de1ff7b6b1872534158f46cf18e2a6aa98b4 b/.git/objects/a1/36de1ff7b6b1872534158f46cf18e2a6aa98b4 new file mode 100644 index 0000000..20316ba Binary files /dev/null and b/.git/objects/a1/36de1ff7b6b1872534158f46cf18e2a6aa98b4 differ diff --git a/.git/objects/a1/410d38c6ee74e02d28699e7b8ced0a5846071f b/.git/objects/a1/410d38c6ee74e02d28699e7b8ced0a5846071f new file mode 100644 index 0000000..5b14fcf --- /dev/null +++ b/.git/objects/a1/410d38c6ee74e02d28699e7b8ced0a5846071f @@ -0,0 +1,2 @@ +x%On0왯{ȆUT%깽 { HE6zjnyi˲L>m խcB`Z{ӻBT+% HXhPu }%uo|N^fg"g8SQ/c@7 tPigU+UJ npy_N:8xFc/ +K55J*H(o䈳P~~?c \ No newline at end of file diff --git a/.git/objects/a1/5bd62b7e76e01bd44ea34b25c5bd1f93d6f507 b/.git/objects/a1/5bd62b7e76e01bd44ea34b25c5bd1f93d6f507 new file mode 100644 index 0000000..c61ab4f --- /dev/null +++ b/.git/objects/a1/5bd62b7e76e01bd44ea34b25c5bd1f93d6f507 @@ -0,0 +1,2 @@ +x%N09)BE\*xnv8w^ nFRs4dfF*4ZI=W!5L/fͅ2wHnPZHt` Q8R;tVi/#gx]Zryt_&j%y:xk] + Qh}' )DSԝ)+|;Ğ-ҶW Tśwr;T UQ \ No newline at end of file diff --git a/.git/objects/a1/a7f327c74667bb8938e45b2c1e6563a1023ae9 b/.git/objects/a1/a7f327c74667bb8938e45b2c1e6563a1023ae9 new file mode 100644 index 0000000..b1acd17 Binary files /dev/null and b/.git/objects/a1/a7f327c74667bb8938e45b2c1e6563a1023ae9 differ diff --git a/.git/objects/a1/d4b425d04485e981b8f32e1cad433c1cbed646 b/.git/objects/a1/d4b425d04485e981b8f32e1cad433c1cbed646 new file mode 100644 index 0000000..502e593 Binary files /dev/null and b/.git/objects/a1/d4b425d04485e981b8f32e1cad433c1cbed646 differ diff --git a/.git/objects/a1/d7c2328db2c5f7c4901b5c897fb14bfd16e4b2 b/.git/objects/a1/d7c2328db2c5f7c4901b5c897fb14bfd16e4b2 new file mode 100644 index 0000000..fa62fea Binary files /dev/null and b/.git/objects/a1/d7c2328db2c5f7c4901b5c897fb14bfd16e4b2 differ diff --git a/.git/objects/a1/e34f329977498ae62b67f7c90eba601c042b16 b/.git/objects/a1/e34f329977498ae62b67f7c90eba601c042b16 new file mode 100644 index 0000000..1bfddc8 Binary files /dev/null and b/.git/objects/a1/e34f329977498ae62b67f7c90eba601c042b16 differ diff --git a/.git/objects/a1/e58edf2862f5d7189b8706526d311614558d68 b/.git/objects/a1/e58edf2862f5d7189b8706526d311614558d68 new file mode 100644 index 0000000..d2f191c Binary files /dev/null and b/.git/objects/a1/e58edf2862f5d7189b8706526d311614558d68 differ diff --git a/.git/objects/a2/2de14c459365ad5760e6b3772b8d61010c41f1 b/.git/objects/a2/2de14c459365ad5760e6b3772b8d61010c41f1 new file mode 100644 index 0000000..d123a93 Binary files /dev/null and b/.git/objects/a2/2de14c459365ad5760e6b3772b8d61010c41f1 differ diff --git a/.git/objects/a2/2fdc92c50e4cf193775836a03f670d094cd72c b/.git/objects/a2/2fdc92c50e4cf193775836a03f670d094cd72c new file mode 100644 index 0000000..f2726d4 Binary files /dev/null and b/.git/objects/a2/2fdc92c50e4cf193775836a03f670d094cd72c differ diff --git a/.git/objects/a2/3e72c7cb7a9730ba5bae5cf038a2e90cb9d5e5 b/.git/objects/a2/3e72c7cb7a9730ba5bae5cf038a2e90cb9d5e5 new file mode 100644 index 0000000..502e801 --- /dev/null +++ b/.git/objects/a2/3e72c7cb7a9730ba5bae5cf038a2e90cb9d5e5 @@ -0,0 +1,3 @@ +xKN0DYG|lg FHݙXJ27c5RzE<r7%؎=wSFq(Ұh7L i5 ,$uLv}2. 'Y1$xLx=Epa +ޭӼˡu:UR}?PFeCl[7X %I!#7!Da` +'>j \ No newline at end of file diff --git a/.git/objects/a2/58ffec29e894c25cb6d8e41846102a7880474f b/.git/objects/a2/58ffec29e894c25cb6d8e41846102a7880474f new file mode 100644 index 0000000..351df32 Binary files /dev/null and b/.git/objects/a2/58ffec29e894c25cb6d8e41846102a7880474f differ diff --git a/.git/objects/a2/644ce3372098243a2fc9e3eeb1cc8c5d74e623 b/.git/objects/a2/644ce3372098243a2fc9e3eeb1cc8c5d74e623 new file mode 100644 index 0000000..b182ed9 Binary files /dev/null and b/.git/objects/a2/644ce3372098243a2fc9e3eeb1cc8c5d74e623 differ diff --git a/.git/objects/a2/7085fe0c2bd6d92c605fa9a492fa38db460bfa b/.git/objects/a2/7085fe0c2bd6d92c605fa9a492fa38db460bfa new file mode 100644 index 0000000..ac4e8c6 Binary files /dev/null and b/.git/objects/a2/7085fe0c2bd6d92c605fa9a492fa38db460bfa differ diff --git a/.git/objects/a2/cedc2edcf178e18053f690df685ff37450ba88 b/.git/objects/a2/cedc2edcf178e18053f690df685ff37450ba88 new file mode 100644 index 0000000..034de1e --- /dev/null +++ b/.git/objects/a2/cedc2edcf178e18053f690df685ff37450ba88 @@ -0,0 +1 @@ +x;N1D!$$mw,͸9Ç )JOyJSoD䘕2CP$5;G|g#砦olT;dGaRYQZ[2tH6'fA^ WcMD^SߟViW/ g6z΀PWj{:d \ No newline at end of file diff --git a/.git/objects/a2/d413bfd5f9713955885866aced68d8b27f35ee b/.git/objects/a2/d413bfd5f9713955885866aced68d8b27f35ee new file mode 100644 index 0000000..7561886 Binary files /dev/null and b/.git/objects/a2/d413bfd5f9713955885866aced68d8b27f35ee differ diff --git a/.git/objects/a3/01d5bbba60270d92c62fd10bacec59b11747db b/.git/objects/a3/01d5bbba60270d92c62fd10bacec59b11747db new file mode 100644 index 0000000..f7ccaf5 Binary files /dev/null and b/.git/objects/a3/01d5bbba60270d92c62fd10bacec59b11747db differ diff --git a/.git/objects/a3/031b6e218d88765a47bed1bdb37e307f9132df b/.git/objects/a3/031b6e218d88765a47bed1bdb37e307f9132df new file mode 100644 index 0000000..0ab48de --- /dev/null +++ b/.git/objects/a3/031b6e218d88765a47bed1bdb37e307f9132df @@ -0,0 +1 @@ +xOKN0 dSx )mHla \}-js1rvfR}51^YU1: Iv># 4D N&םj64$fُ=2io0E-ߜVx[l|94Oz7]|*r+erw#E"rpklm-2}+g>i ug+p, nj^W=?rh \ No newline at end of file diff --git a/.git/objects/a3/1fb267449e87d6c1abea1c8483ed95cb32bf97 b/.git/objects/a3/1fb267449e87d6c1abea1c8483ed95cb32bf97 new file mode 100644 index 0000000..8937c9f Binary files /dev/null and b/.git/objects/a3/1fb267449e87d6c1abea1c8483ed95cb32bf97 differ diff --git a/.git/objects/a3/3055d72d0c74c612116e46cb2f9363bf6c944e b/.git/objects/a3/3055d72d0c74c612116e46cb2f9363bf6c944e new file mode 100644 index 0000000..080a3c3 Binary files /dev/null and b/.git/objects/a3/3055d72d0c74c612116e46cb2f9363bf6c944e differ diff --git a/.git/objects/a3/56c6e8666579fdb9cb5dde22bbf6d191d222d8 b/.git/objects/a3/56c6e8666579fdb9cb5dde22bbf6d191d222d8 new file mode 100644 index 0000000..002cd9a Binary files /dev/null and b/.git/objects/a3/56c6e8666579fdb9cb5dde22bbf6d191d222d8 differ diff --git a/.git/objects/a3/84873f2661260a698b54abda520d849b97faef b/.git/objects/a3/84873f2661260a698b54abda520d849b97faef new file mode 100644 index 0000000..0485967 Binary files /dev/null and b/.git/objects/a3/84873f2661260a698b54abda520d849b97faef differ diff --git a/.git/objects/a3/de51b163df2156e48508cb3e9410dbc5255d96 b/.git/objects/a3/de51b163df2156e48508cb3e9410dbc5255d96 new file mode 100644 index 0000000..347053b Binary files /dev/null and b/.git/objects/a3/de51b163df2156e48508cb3e9410dbc5255d96 differ diff --git a/.git/objects/a4/01aa3f0b140cd633cc6c3e146c67d4afe7c303 b/.git/objects/a4/01aa3f0b140cd633cc6c3e146c67d4afe7c303 new file mode 100644 index 0000000..3524988 Binary files /dev/null and b/.git/objects/a4/01aa3f0b140cd633cc6c3e146c67d4afe7c303 differ diff --git a/.git/objects/a4/0646a6c7dfeab89a78051fa695d9618fdefb61 b/.git/objects/a4/0646a6c7dfeab89a78051fa695d9618fdefb61 new file mode 100644 index 0000000..3b33ea2 Binary files /dev/null and b/.git/objects/a4/0646a6c7dfeab89a78051fa695d9618fdefb61 differ diff --git a/.git/objects/a4/1592c5fecf45776f931eca12cf75633a0c1e53 b/.git/objects/a4/1592c5fecf45776f931eca12cf75633a0c1e53 new file mode 100644 index 0000000..640741a Binary files /dev/null and b/.git/objects/a4/1592c5fecf45776f931eca12cf75633a0c1e53 differ diff --git a/.git/objects/a4/66143fe3bce6b1d88c43f5433044f9e19388bc b/.git/objects/a4/66143fe3bce6b1d88c43f5433044f9e19388bc new file mode 100644 index 0000000..a0e12d2 Binary files /dev/null and b/.git/objects/a4/66143fe3bce6b1d88c43f5433044f9e19388bc differ diff --git a/.git/objects/a4/720d9e4b4922d82b948d16148a2789fb0d56d3 b/.git/objects/a4/720d9e4b4922d82b948d16148a2789fb0d56d3 new file mode 100644 index 0000000..44b6739 --- /dev/null +++ b/.git/objects/a4/720d9e4b4922d82b948d16148a2789fb0d56d3 @@ -0,0 +1,2 @@ +x%MN0 Y#$$m*ЌXÆ;&MhbDV{oU%1ÄaTnMJJ!ͣS +Dl']1qhHyXHɬI/ l1||cYym+qs Škn]ڝ5mb:c#3\a < }A͜2Ğ C{%\`g[nj] \ No newline at end of file diff --git a/.git/objects/a4/8843991c2a3a20fcfa13a8b272f05b87ad997c b/.git/objects/a4/8843991c2a3a20fcfa13a8b272f05b87ad997c new file mode 100644 index 0000000..88f141a Binary files /dev/null and b/.git/objects/a4/8843991c2a3a20fcfa13a8b272f05b87ad997c differ diff --git a/.git/objects/a4/8b37523f8aaad7bb38275bc5c2f6884bb7081c b/.git/objects/a4/8b37523f8aaad7bb38275bc5c2f6884bb7081c new file mode 100644 index 0000000..eae45f9 Binary files /dev/null and b/.git/objects/a4/8b37523f8aaad7bb38275bc5c2f6884bb7081c differ diff --git a/.git/objects/a4/9e37376bbda6dc68cc131883406fec9e387afb b/.git/objects/a4/9e37376bbda6dc68cc131883406fec9e387afb new file mode 100644 index 0000000..5f72321 Binary files /dev/null and b/.git/objects/a4/9e37376bbda6dc68cc131883406fec9e387afb differ diff --git a/.git/objects/a4/b7ce65e1e8f3d0a69a5e05a40b4cf02ce8d338 b/.git/objects/a4/b7ce65e1e8f3d0a69a5e05a40b4cf02ce8d338 new file mode 100644 index 0000000..83b08ee Binary files /dev/null and b/.git/objects/a4/b7ce65e1e8f3d0a69a5e05a40b4cf02ce8d338 differ diff --git a/.git/objects/a4/baf1c92c59796f920022f8fd771076fac4a8e5 b/.git/objects/a4/baf1c92c59796f920022f8fd771076fac4a8e5 new file mode 100644 index 0000000..53b14f2 Binary files /dev/null and b/.git/objects/a4/baf1c92c59796f920022f8fd771076fac4a8e5 differ diff --git a/.git/objects/a4/e0cbedf5271c09d3ef40cbb3a047689db53e33 b/.git/objects/a4/e0cbedf5271c09d3ef40cbb3a047689db53e33 new file mode 100644 index 0000000..532c369 Binary files /dev/null and b/.git/objects/a4/e0cbedf5271c09d3ef40cbb3a047689db53e33 differ diff --git a/.git/objects/a5/046f58b32190891039a9e428ca85cd525da4fa b/.git/objects/a5/046f58b32190891039a9e428ca85cd525da4fa new file mode 100644 index 0000000..0f73b43 Binary files /dev/null and b/.git/objects/a5/046f58b32190891039a9e428ca85cd525da4fa differ diff --git a/.git/objects/a5/14ad20affe0c7751dcc695cb9eee35896c3dbb b/.git/objects/a5/14ad20affe0c7751dcc695cb9eee35896c3dbb new file mode 100644 index 0000000..13ccd6b Binary files /dev/null and b/.git/objects/a5/14ad20affe0c7751dcc695cb9eee35896c3dbb differ diff --git a/.git/objects/a5/14ff44ec931a95d8bdf11a4def2aafd3ce6aa0 b/.git/objects/a5/14ff44ec931a95d8bdf11a4def2aafd3ce6aa0 new file mode 100644 index 0000000..3c19779 Binary files /dev/null and b/.git/objects/a5/14ff44ec931a95d8bdf11a4def2aafd3ce6aa0 differ diff --git a/.git/objects/a5/1cdef5676b6ce39da2f457bd947dc1856527f9 b/.git/objects/a5/1cdef5676b6ce39da2f457bd947dc1856527f9 new file mode 100644 index 0000000..2779988 Binary files /dev/null and b/.git/objects/a5/1cdef5676b6ce39da2f457bd947dc1856527f9 differ diff --git a/.git/objects/a5/43d7365ecabfe4a0496accb9f5dd0ddcbdf7a4 b/.git/objects/a5/43d7365ecabfe4a0496accb9f5dd0ddcbdf7a4 new file mode 100644 index 0000000..b2efcc2 Binary files /dev/null and b/.git/objects/a5/43d7365ecabfe4a0496accb9f5dd0ddcbdf7a4 differ diff --git a/.git/objects/a5/6e88f93fc22e81bbe2346881ee34fd1c1fee3d b/.git/objects/a5/6e88f93fc22e81bbe2346881ee34fd1c1fee3d new file mode 100644 index 0000000..e041f5b Binary files /dev/null and b/.git/objects/a5/6e88f93fc22e81bbe2346881ee34fd1c1fee3d differ diff --git a/.git/objects/a5/7d236392c96ebd038db66f120d69d2ffc038f4 b/.git/objects/a5/7d236392c96ebd038db66f120d69d2ffc038f4 new file mode 100644 index 0000000..f31135f --- /dev/null +++ b/.git/objects/a5/7d236392c96ebd038db66f120d69d2ffc038f4 @@ -0,0 +1,2 @@ +x5j0{S4ϒBH)'XHZ#Mf* + ͎ kB 2N;P9iGc}9lk:m,+(Tu}I/IV mܷ S;xwX'H¿ms4/{=t?Zie \ No newline at end of file diff --git a/.git/objects/a5/e32c43557caf7e15fca14a097db752a604676e b/.git/objects/a5/e32c43557caf7e15fca14a097db752a604676e new file mode 100644 index 0000000..d0b0f34 Binary files /dev/null and b/.git/objects/a5/e32c43557caf7e15fca14a097db752a604676e differ diff --git a/.git/objects/a5/e7c71ac0cf6d2bf76da3c8fa831614e06e4f23 b/.git/objects/a5/e7c71ac0cf6d2bf76da3c8fa831614e06e4f23 new file mode 100644 index 0000000..d58d6fc Binary files /dev/null and b/.git/objects/a5/e7c71ac0cf6d2bf76da3c8fa831614e06e4f23 differ diff --git a/.git/objects/a6/5caa576a970318d720c0bb73cd01ff4020c8d8 b/.git/objects/a6/5caa576a970318d720c0bb73cd01ff4020c8d8 new file mode 100644 index 0000000..2c1a19e Binary files /dev/null and b/.git/objects/a6/5caa576a970318d720c0bb73cd01ff4020c8d8 differ diff --git a/.git/objects/a6/8129d779f8151deacbcedb20ef5b9046d44d7e b/.git/objects/a6/8129d779f8151deacbcedb20ef5b9046d44d7e new file mode 100644 index 0000000..096abdb Binary files /dev/null and b/.git/objects/a6/8129d779f8151deacbcedb20ef5b9046d44d7e differ diff --git a/.git/objects/a6/95cdaab7a131b060b725b5b434ec2782e93ffe b/.git/objects/a6/95cdaab7a131b060b725b5b434ec2782e93ffe new file mode 100644 index 0000000..c9844d5 Binary files /dev/null and b/.git/objects/a6/95cdaab7a131b060b725b5b434ec2782e93ffe differ diff --git a/.git/objects/a6/a62a22994e644788f5a87030f8d737959b1d9c b/.git/objects/a6/a62a22994e644788f5a87030f8d737959b1d9c new file mode 100644 index 0000000..3ef2bcb --- /dev/null +++ b/.git/objects/a6/a62a22994e644788f5a87030f8d737959b1d9c @@ -0,0 +1,2 @@ +x%AN0EYGTv2kBEq=N\%ve@oƞݗOu zZa zAѣ6J#HRY P@QbP{g*tCU iK:X6ޓ\eoJ EUNSW86Ɂn;g +)q<^:XD n#-uu;ǽF O7 yOPAI}S 3puoK9ٷNJز!0ZIwؼST#hlp꼣 h(؆5O#/x|i9gI<]qH~9›BL3 $Z2k~u]{ \ No newline at end of file diff --git a/.git/objects/aa/5522508f708209703eea58778faa66ee99d9c0 b/.git/objects/aa/5522508f708209703eea58778faa66ee99d9c0 new file mode 100644 index 0000000..02294f9 Binary files /dev/null and b/.git/objects/aa/5522508f708209703eea58778faa66ee99d9c0 differ diff --git a/.git/objects/aa/b1065284c330c74d0925eba899b46f46c01120 b/.git/objects/aa/b1065284c330c74d0925eba899b46f46c01120 new file mode 100644 index 0000000..22cbec6 Binary files /dev/null and b/.git/objects/aa/b1065284c330c74d0925eba899b46f46c01120 differ diff --git a/.git/objects/aa/bb11884df1742efb49e2bb62738fd3bea81740 b/.git/objects/aa/bb11884df1742efb49e2bb62738fd3bea81740 new file mode 100644 index 0000000..e9428c2 Binary files /dev/null and b/.git/objects/aa/bb11884df1742efb49e2bb62738fd3bea81740 differ diff --git a/.git/objects/aa/feb71e0dab78f71e252f6ef0d1ed3fb6b6c629 b/.git/objects/aa/feb71e0dab78f71e252f6ef0d1ed3fb6b6c629 new file mode 100644 index 0000000..5af40c9 Binary files /dev/null and b/.git/objects/aa/feb71e0dab78f71e252f6ef0d1ed3fb6b6c629 differ diff --git a/.git/objects/ab/0385d0aa41728aa4f98ff3658c3bd2d752cfe6 b/.git/objects/ab/0385d0aa41728aa4f98ff3658c3bd2d752cfe6 new file mode 100644 index 0000000..e93ae69 Binary files /dev/null and b/.git/objects/ab/0385d0aa41728aa4f98ff3658c3bd2d752cfe6 differ diff --git a/.git/objects/ab/12c5e4098886ac37b1a4fb690f9faf060ed377 b/.git/objects/ab/12c5e4098886ac37b1a4fb690f9faf060ed377 new file mode 100644 index 0000000..81cb043 Binary files /dev/null and b/.git/objects/ab/12c5e4098886ac37b1a4fb690f9faf060ed377 differ diff --git a/.git/objects/ab/4ac1c4d20f3fde12be53f512c5c3516dfe4414 b/.git/objects/ab/4ac1c4d20f3fde12be53f512c5c3516dfe4414 new file mode 100644 index 0000000..4fc6f45 Binary files /dev/null and b/.git/objects/ab/4ac1c4d20f3fde12be53f512c5c3516dfe4414 differ diff --git a/.git/objects/ab/a27b0a2e71899fe48a5bea8d1596bd802cc30a b/.git/objects/ab/a27b0a2e71899fe48a5bea8d1596bd802cc30a new file mode 100644 index 0000000..90ad49c Binary files /dev/null and b/.git/objects/ab/a27b0a2e71899fe48a5bea8d1596bd802cc30a differ diff --git a/.git/objects/ab/c8ac5e036dceac7a7442dca044ade2933fb987 b/.git/objects/ab/c8ac5e036dceac7a7442dca044ade2933fb987 new file mode 100644 index 0000000..a55c926 Binary files /dev/null and b/.git/objects/ab/c8ac5e036dceac7a7442dca044ade2933fb987 differ diff --git a/.git/objects/ab/e33cfe7d3b7fcf44669668279e55dca11198c8 b/.git/objects/ab/e33cfe7d3b7fcf44669668279e55dca11198c8 new file mode 100644 index 0000000..87c7ba1 --- /dev/null +++ b/.git/objects/ab/e33cfe7d3b7fcf44669668279e55dca11198c8 @@ -0,0 +1,2 @@ +x%MN0 FY#i b=l8:mPTLoƞOm6_@$"`2FY2ڊꝝqF'XsD2ce*CRơ*'"j4+0L۸)w +u{. -B $<2XSzw=oK.1d뾵_WҴNvBwT՛h>ɖ )=C h- ίw\r \a \ No newline at end of file diff --git a/.git/objects/ab/f8e54675172639d26615483db84be5c89fa3b7 b/.git/objects/ab/f8e54675172639d26615483db84be5c89fa3b7 new file mode 100644 index 0000000..d490c83 Binary files /dev/null and b/.git/objects/ab/f8e54675172639d26615483db84be5c89fa3b7 differ diff --git a/.git/objects/ac/060ecbecdfe6474e1943326a2e64f77f45e56b b/.git/objects/ac/060ecbecdfe6474e1943326a2e64f77f45e56b new file mode 100644 index 0000000..780f7b4 Binary files /dev/null and b/.git/objects/ac/060ecbecdfe6474e1943326a2e64f77f45e56b differ diff --git a/.git/objects/ac/1f1f4d43fbe0ec5b399c6a68bb52b1afae5575 b/.git/objects/ac/1f1f4d43fbe0ec5b399c6a68bb52b1afae5575 new file mode 100644 index 0000000..1d52f97 Binary files /dev/null and b/.git/objects/ac/1f1f4d43fbe0ec5b399c6a68bb52b1afae5575 differ diff --git a/.git/objects/ac/6cfa0e23318f0f961da07f65b5a0a565b4a7b9 b/.git/objects/ac/6cfa0e23318f0f961da07f65b5a0a565b4a7b9 new file mode 100644 index 0000000..9625edd Binary files /dev/null and b/.git/objects/ac/6cfa0e23318f0f961da07f65b5a0a565b4a7b9 differ diff --git a/.git/objects/ac/7d81c93005fbe424067c26237053b9827f0329 b/.git/objects/ac/7d81c93005fbe424067c26237053b9827f0329 new file mode 100644 index 0000000..f5a5e36 Binary files /dev/null and b/.git/objects/ac/7d81c93005fbe424067c26237053b9827f0329 differ diff --git a/.git/objects/ac/86b2a597e7356813d57e45c9ba8207694d1513 b/.git/objects/ac/86b2a597e7356813d57e45c9ba8207694d1513 new file mode 100644 index 0000000..1fcea2b Binary files /dev/null and b/.git/objects/ac/86b2a597e7356813d57e45c9ba8207694d1513 differ diff --git a/.git/objects/ac/9b791dbe9caf76b885f7b91ee110df8d35262f b/.git/objects/ac/9b791dbe9caf76b885f7b91ee110df8d35262f new file mode 100644 index 0000000..b0688e6 Binary files /dev/null and b/.git/objects/ac/9b791dbe9caf76b885f7b91ee110df8d35262f differ diff --git a/.git/objects/ac/adef265070a152f9055488a34a341cf113928a b/.git/objects/ac/adef265070a152f9055488a34a341cf113928a new file mode 100644 index 0000000..dfba17f Binary files /dev/null and b/.git/objects/ac/adef265070a152f9055488a34a341cf113928a differ diff --git a/.git/objects/ac/ccbed63a212e5a15cc61e2d44dd084a3a9c374 b/.git/objects/ac/ccbed63a212e5a15cc61e2d44dd084a3a9c374 new file mode 100644 index 0000000..c7f9a01 Binary files /dev/null and b/.git/objects/ac/ccbed63a212e5a15cc61e2d44dd084a3a9c374 differ diff --git a/.git/objects/ac/d3fdb5b802ff7278d7c945e81833caf9add6fd b/.git/objects/ac/d3fdb5b802ff7278d7c945e81833caf9add6fd new file mode 100644 index 0000000..e729f45 Binary files /dev/null and b/.git/objects/ac/d3fdb5b802ff7278d7c945e81833caf9add6fd differ diff --git a/.git/objects/ac/dac5aad79caff4a1264032593a68739cb79271 b/.git/objects/ac/dac5aad79caff4a1264032593a68739cb79271 new file mode 100644 index 0000000..cb10816 Binary files /dev/null and b/.git/objects/ac/dac5aad79caff4a1264032593a68739cb79271 differ diff --git a/.git/objects/ac/dfdf4eb856dcab65ed4777540c45f8c4e0035a b/.git/objects/ac/dfdf4eb856dcab65ed4777540c45f8c4e0035a new file mode 100644 index 0000000..1855032 Binary files /dev/null and b/.git/objects/ac/dfdf4eb856dcab65ed4777540c45f8c4e0035a differ diff --git a/.git/objects/ac/f2764db89faaed72f48727384b8581e184415b b/.git/objects/ac/f2764db89faaed72f48727384b8581e184415b new file mode 100644 index 0000000..71fcb10 Binary files /dev/null and b/.git/objects/ac/f2764db89faaed72f48727384b8581e184415b differ diff --git a/.git/objects/ad/2836ffb0c099acb03c7e2934da0f77967aa7fa b/.git/objects/ad/2836ffb0c099acb03c7e2934da0f77967aa7fa new file mode 100644 index 0000000..0f539b2 Binary files /dev/null and b/.git/objects/ad/2836ffb0c099acb03c7e2934da0f77967aa7fa differ diff --git a/.git/objects/ad/35018dec32b4262ed2cd92da756c062b96fb8a b/.git/objects/ad/35018dec32b4262ed2cd92da756c062b96fb8a new file mode 100644 index 0000000..1b4902c Binary files /dev/null and b/.git/objects/ad/35018dec32b4262ed2cd92da756c062b96fb8a differ diff --git a/.git/objects/ad/3d1a8b2850b7f1ee59d997938ae23da0a920bc b/.git/objects/ad/3d1a8b2850b7f1ee59d997938ae23da0a920bc new file mode 100644 index 0000000..9efa32d Binary files /dev/null and b/.git/objects/ad/3d1a8b2850b7f1ee59d997938ae23da0a920bc differ diff --git a/.git/objects/ad/561ce690e346c42acc1818bcc88fd742cbc685 b/.git/objects/ad/561ce690e346c42acc1818bcc88fd742cbc685 new file mode 100644 index 0000000..08e889c Binary files /dev/null and b/.git/objects/ad/561ce690e346c42acc1818bcc88fd742cbc685 differ diff --git a/.git/objects/ad/73b6445f9072893eb8387b019ac290699522c1 b/.git/objects/ad/73b6445f9072893eb8387b019ac290699522c1 new file mode 100644 index 0000000..189c1ce --- /dev/null +++ b/.git/objects/ad/73b6445f9072893eb8387b019ac290699522c1 @@ -0,0 +1 @@ +x-N;N0)GD)ZDE 'ǛH9ތޟJJseC0 c%@L)/Mp6H%)[rnFbT#GCl5a0wTxY9pʂ3|Pm鰔o= R:-SB w;z^:o^3(=sVI+I#޽/_ 2Pq /\c$` \ No newline at end of file diff --git a/.git/objects/ad/74d98c26ddf6105a8a33279b102182cf721825 b/.git/objects/ad/74d98c26ddf6105a8a33279b102182cf721825 new file mode 100644 index 0000000..ffdb760 Binary files /dev/null and b/.git/objects/ad/74d98c26ddf6105a8a33279b102182cf721825 differ diff --git a/.git/objects/ad/799bd6c978b9b6ca1490f535da3bb4c5d73c79 b/.git/objects/ad/799bd6c978b9b6ca1490f535da3bb4c5d73c79 new file mode 100644 index 0000000..40ed302 Binary files /dev/null and b/.git/objects/ad/799bd6c978b9b6ca1490f535da3bb4c5d73c79 differ diff --git a/.git/objects/ad/9634f986a60cb0d220a15b1b3917f9462855ee b/.git/objects/ad/9634f986a60cb0d220a15b1b3917f9462855ee new file mode 100644 index 0000000..4dedfb6 Binary files /dev/null and b/.git/objects/ad/9634f986a60cb0d220a15b1b3917f9462855ee differ diff --git a/.git/objects/ae/0284d07b1a9ce828f9511d42ca2efae7db82a0 b/.git/objects/ae/0284d07b1a9ce828f9511d42ca2efae7db82a0 new file mode 100644 index 0000000..e9d106f --- /dev/null +++ b/.git/objects/ae/0284d07b1a9ce828f9511d42ca2efae7db82a0 @@ -0,0 +1,3 @@ +x1N0EsWBc;BKC 'Ǜ{3z. n@\mm`P=*#b1qb*1$Z-YsU  I0 QѸ)1yTxȍr ++ w]D=E>)%lϠ88Bzڽ[8i;#%| +7tz{]7Y"TI_/f \ No newline at end of file diff --git a/.git/objects/ae/0bc3e5eee635ceb40216018830e022954903d5 b/.git/objects/ae/0bc3e5eee635ceb40216018830e022954903d5 new file mode 100644 index 0000000..6413ed6 Binary files /dev/null and b/.git/objects/ae/0bc3e5eee635ceb40216018830e022954903d5 differ diff --git a/.git/objects/ae/4032da7c66bfda910c2556cd3296bc33262b97 b/.git/objects/ae/4032da7c66bfda910c2556cd3296bc33262b97 new file mode 100644 index 0000000..5cede02 Binary files /dev/null and b/.git/objects/ae/4032da7c66bfda910c2556cd3296bc33262b97 differ diff --git a/.git/objects/ae/48bf2e3a4b9ae0b6410bec16f03204dda91f64 b/.git/objects/ae/48bf2e3a4b9ae0b6410bec16f03204dda91f64 new file mode 100644 index 0000000..cae0e46 Binary files /dev/null and b/.git/objects/ae/48bf2e3a4b9ae0b6410bec16f03204dda91f64 differ diff --git a/.git/objects/ae/62e5e9d1616086ccaffb27c54f4ebe724e4e8c b/.git/objects/ae/62e5e9d1616086ccaffb27c54f4ebe724e4e8c new file mode 100644 index 0000000..5bd7b35 Binary files /dev/null and b/.git/objects/ae/62e5e9d1616086ccaffb27c54f4ebe724e4e8c differ diff --git a/.git/objects/ae/97e45ea5f93fc2b667a797ceb07dce67277dca b/.git/objects/ae/97e45ea5f93fc2b667a797ceb07dce67277dca new file mode 100644 index 0000000..6113bfc Binary files /dev/null and b/.git/objects/ae/97e45ea5f93fc2b667a797ceb07dce67277dca differ diff --git a/.git/objects/ae/e69c1735f014b4a16ec54014b0f3ce6088faa3 b/.git/objects/ae/e69c1735f014b4a16ec54014b0f3ce6088faa3 new file mode 100644 index 0000000..32c2168 --- /dev/null +++ b/.git/objects/ae/e69c1735f014b4a16ec54014b0f3ce6088faa3 @@ -0,0 +1 @@ +x%=N0sץ@"j(&Rl/tFsKM-D Rs&"X0RIywBSAYiF\CKB$ i^\q/LxY|^Qh#Tg[%*ӑs%sIAU!w<9^LQZl@kWN7XLUR\9I%4xN:Ox B]qEUGŠq@"HysB7JxbMH1dbrzi |~8Oor~6_ͼVf(@%KY ?2'iB52Uk&)sb.n6@iɣ&è#A M+;|~u}fbg:.=M?:i; gĈbFلIn3jL xΑdz3dY!5 /= ,5u!m3ThK:pl&yYv r 6VRdu`d-ndlS$=%jS:mk;ڜdqc2 hPLgWq laO/EZzo&e;i5 e@OCb:Z8 Fc&]2Gtcm4d:tzoB|Mv֌2 +AĶSi)`MX_8#_!)tFJ+nP**xZ!=r0􆸳V4ECTsF[B!hoKy;0_eA#5D2FƖ(eE"G+o֏^6V?^\PQiN@/\oj!< :^ݭ)nVFHJ!T}it=}-= +pm c^!܁fGz&O +''C>)$,6_RZæ(v,ۚxfv/o٪GE[Q,[JX1;| aZ>yT *d@/ZN l@&2rbZ)luEI3Qˇƃp44"*fHEJ屹+֋ ++Dwl.l* x7֫?i`Q$FQOk:Liϋ +Y-$ ǃ*_{\M;؋ߒ<Kb1xѰ;٘LFYKv} @b G~?X| \ No newline at end of file diff --git a/.git/objects/b0/731d0ebccf5ae9d2bd8c67349708efcce9d0b1 b/.git/objects/b0/731d0ebccf5ae9d2bd8c67349708efcce9d0b1 new file mode 100644 index 0000000..198c52d Binary files /dev/null and b/.git/objects/b0/731d0ebccf5ae9d2bd8c67349708efcce9d0b1 differ diff --git a/.git/objects/b0/74048c57b9da424e37701d16a4f973f682a975 b/.git/objects/b0/74048c57b9da424e37701d16a4f973f682a975 new file mode 100644 index 0000000..ece44cd Binary files /dev/null and b/.git/objects/b0/74048c57b9da424e37701d16a4f973f682a975 differ diff --git a/.git/objects/b0/7a5b2d0478dce04d57eb793fd2bcb6e37e04ef b/.git/objects/b0/7a5b2d0478dce04d57eb793fd2bcb6e37e04ef new file mode 100644 index 0000000..1bf93ba Binary files /dev/null and b/.git/objects/b0/7a5b2d0478dce04d57eb793fd2bcb6e37e04ef differ diff --git a/.git/objects/b0/930bbbc8cd9c8e36ada1918a6422245cba3e87 b/.git/objects/b0/930bbbc8cd9c8e36ada1918a6422245cba3e87 new file mode 100644 index 0000000..48f2073 Binary files /dev/null and b/.git/objects/b0/930bbbc8cd9c8e36ada1918a6422245cba3e87 differ diff --git a/.git/objects/b0/aa6c80cc39c1d1209502c7d27359f5b6cd6448 b/.git/objects/b0/aa6c80cc39c1d1209502c7d27359f5b6cd6448 new file mode 100644 index 0000000..332358d Binary files /dev/null and b/.git/objects/b0/aa6c80cc39c1d1209502c7d27359f5b6cd6448 differ diff --git a/.git/objects/b0/c6ca2c17a39476ec75bbe954144b5c0aaaaeb2 b/.git/objects/b0/c6ca2c17a39476ec75bbe954144b5c0aaaaeb2 new file mode 100644 index 0000000..69a8309 Binary files /dev/null and b/.git/objects/b0/c6ca2c17a39476ec75bbe954144b5c0aaaaeb2 differ diff --git a/.git/objects/b0/f41adffb4a5ccfee3029e0f335ad7ead06508c b/.git/objects/b0/f41adffb4a5ccfee3029e0f335ad7ead06508c new file mode 100644 index 0000000..999178a Binary files /dev/null and b/.git/objects/b0/f41adffb4a5ccfee3029e0f335ad7ead06508c differ diff --git a/.git/objects/b1/0f27836d5b11611c8250461845203d5dc40b72 b/.git/objects/b1/0f27836d5b11611c8250461845203d5dc40b72 new file mode 100644 index 0000000..4f2d299 Binary files /dev/null and b/.git/objects/b1/0f27836d5b11611c8250461845203d5dc40b72 differ diff --git a/.git/objects/b1/211c4662ab097348009b3c9e0df64fdff732aa b/.git/objects/b1/211c4662ab097348009b3c9e0df64fdff732aa new file mode 100644 index 0000000..e84013d Binary files /dev/null and b/.git/objects/b1/211c4662ab097348009b3c9e0df64fdff732aa differ diff --git a/.git/objects/b1/280ab97f094d0acf1e60f4082aa54f32e22717 b/.git/objects/b1/280ab97f094d0acf1e60f4082aa54f32e22717 new file mode 100644 index 0000000..4fb5a7c Binary files /dev/null and b/.git/objects/b1/280ab97f094d0acf1e60f4082aa54f32e22717 differ diff --git a/.git/objects/b1/5a0bfbe5602d004652c9df13431ac46e362311 b/.git/objects/b1/5a0bfbe5602d004652c9df13431ac46e362311 new file mode 100644 index 0000000..657b6fd Binary files /dev/null and b/.git/objects/b1/5a0bfbe5602d004652c9df13431ac46e362311 differ diff --git a/.git/objects/b1/5e8cf7e00590f155a449e1836d3cbcbb0690a4 b/.git/objects/b1/5e8cf7e00590f155a449e1836d3cbcbb0690a4 new file mode 100644 index 0000000..e7a602f Binary files /dev/null and b/.git/objects/b1/5e8cf7e00590f155a449e1836d3cbcbb0690a4 differ diff --git a/.git/objects/b1/bceae8125d4f3ea0b7e93e626e7acbf1db3be8 b/.git/objects/b1/bceae8125d4f3ea0b7e93e626e7acbf1db3be8 new file mode 100644 index 0000000..8f7b025 Binary files /dev/null and b/.git/objects/b1/bceae8125d4f3ea0b7e93e626e7acbf1db3be8 differ diff --git a/.git/objects/b1/d750651b8f1cb046a65fb999d813f6dee2487e b/.git/objects/b1/d750651b8f1cb046a65fb999d813f6dee2487e new file mode 100644 index 0000000..5d8b5de Binary files /dev/null and b/.git/objects/b1/d750651b8f1cb046a65fb999d813f6dee2487e differ diff --git a/.git/objects/b1/db516c86be0696c415d9088223766252b34355 b/.git/objects/b1/db516c86be0696c415d9088223766252b34355 new file mode 100644 index 0000000..4d6336d Binary files /dev/null and b/.git/objects/b1/db516c86be0696c415d9088223766252b34355 differ diff --git a/.git/objects/b1/e4401d56d0ced9219e7f46d309d1f11128747a b/.git/objects/b1/e4401d56d0ced9219e7f46d309d1f11128747a new file mode 100644 index 0000000..4908849 Binary files /dev/null and b/.git/objects/b1/e4401d56d0ced9219e7f46d309d1f11128747a differ diff --git a/.git/objects/b2/3b82f8cd8a04aadc009c30106b6093847bac11 b/.git/objects/b2/3b82f8cd8a04aadc009c30106b6093847bac11 new file mode 100644 index 0000000..66a7852 --- /dev/null +++ b/.git/objects/b2/3b82f8cd8a04aadc009c30106b6093847bac11 @@ -0,0 +1,4 @@ +x}RMK1m+EOJA +e'6Mj2;] +|̛^RY_Ajctu.~*`&RH)C !`1V8rPv0{0 j˦G<ZPq SmEѣ(?ct(=e RQj'YI34YMT:-*Z𯶕0.6 +tOQQ_C(PfqBhSESM-f6?jn:f+o5OwƲ }cP>Έŝ̘М[w]0L5;B>G[„W9-y  :z ҷ5ؾǡ \ No newline at end of file diff --git a/.git/objects/b2/3f005cca4f039a6b17d976b630b1fdc9007b26 b/.git/objects/b2/3f005cca4f039a6b17d976b630b1fdc9007b26 new file mode 100644 index 0000000..d418dee Binary files /dev/null and b/.git/objects/b2/3f005cca4f039a6b17d976b630b1fdc9007b26 differ diff --git a/.git/objects/b2/55de5f38a0c65b6ed8cb7908c745b0afd3a51e b/.git/objects/b2/55de5f38a0c65b6ed8cb7908c745b0afd3a51e new file mode 100644 index 0000000..975bd5c Binary files /dev/null and b/.git/objects/b2/55de5f38a0c65b6ed8cb7908c745b0afd3a51e differ diff --git a/.git/objects/b2/59934c0e3e985c1ea785e9b4ace102b3d7203b b/.git/objects/b2/59934c0e3e985c1ea785e9b4ace102b3d7203b new file mode 100644 index 0000000..e55f578 Binary files /dev/null and b/.git/objects/b2/59934c0e3e985c1ea785e9b4ace102b3d7203b differ diff --git a/.git/objects/b2/60a1c403175c845324d331b73f12c947d19c2d b/.git/objects/b2/60a1c403175c845324d331b73f12c947d19c2d new file mode 100644 index 0000000..b0563bc Binary files /dev/null and b/.git/objects/b2/60a1c403175c845324d331b73f12c947d19c2d differ diff --git a/.git/objects/b2/6b086952d5e890f3ae174d3096c9b971026d35 b/.git/objects/b2/6b086952d5e890f3ae174d3096c9b971026d35 new file mode 100644 index 0000000..c2076eb Binary files /dev/null and b/.git/objects/b2/6b086952d5e890f3ae174d3096c9b971026d35 differ diff --git a/.git/objects/b2/6be595335fe476bc72358fa9bf9ff753555b74 b/.git/objects/b2/6be595335fe476bc72358fa9bf9ff753555b74 new file mode 100644 index 0000000..7b20b3b --- /dev/null +++ b/.git/objects/b2/6be595335fe476bc72358fa9bf9ff753555b74 @@ -0,0 +1,2 @@ +x-In0 E)/jhTEMO@S YF bUG))Ef0Wn5HN)Ԑ6,m$VE[ib>U,7R_dOU[ZeBI(pKcp +{ܿcy̕p!{ITRWUm1N+CÁpysmJ?tZT"LƋ_=_d- CjL +K~+ϙ (f \ No newline at end of file diff --git a/.git/objects/b2/adeab95a2f949fde144e76fc218675ea3a6061 b/.git/objects/b2/adeab95a2f949fde144e76fc218675ea3a6061 new file mode 100644 index 0000000..1a8223e --- /dev/null +++ b/.git/objects/b2/adeab95a2f949fde144e76fc218675ea3a6061 @@ -0,0 +1,5 @@ +xn D{Wj #EUK`mؒcc%fތf1.O0$DVOzo$i-yPFZݝ + +RFt4CgXv9Mse+')78SK/u!9-4 +',]svlˍ/.u_NG]N +^n=TW*U[ \ No newline at end of file diff --git a/.git/objects/b2/c17988533c7eec52cc59fbdf1856f09bbe8f91 b/.git/objects/b2/c17988533c7eec52cc59fbdf1856f09bbe8f91 new file mode 100644 index 0000000..2d24b56 Binary files /dev/null and b/.git/objects/b2/c17988533c7eec52cc59fbdf1856f09bbe8f91 differ diff --git a/.git/objects/b2/cc871f0928e6379c1dd25dc7ad824509c572ed b/.git/objects/b2/cc871f0928e6379c1dd25dc7ad824509c572ed new file mode 100644 index 0000000..92e61e3 --- /dev/null +++ b/.git/objects/b2/cc871f0928e6379c1dd25dc7ad824509c572ed @@ -0,0 +1 @@ +xNKN0dS%,ZĶTUEqg9 J1{.UqV3|}^׹R"0C"]q4A6$%MѾw_̲fa0*t"P(hw5#W$p'׫ٮfR^H++Ug'9nu^fQyJ ߟh=kh:*[N{9>F +ulkxd:{.7nvbKީ'6z97B4W \ No newline at end of file diff --git a/.git/objects/b4/0a46178aeef6417c9987608ff52afb5f4bd07f b/.git/objects/b4/0a46178aeef6417c9987608ff52afb5f4bd07f new file mode 100644 index 0000000..38f899f Binary files /dev/null and b/.git/objects/b4/0a46178aeef6417c9987608ff52afb5f4bd07f differ diff --git a/.git/objects/b4/5f1b9f680e2db0cf528ed294e2d98ac91bb2b8 b/.git/objects/b4/5f1b9f680e2db0cf528ed294e2d98ac91bb2b8 new file mode 100644 index 0000000..24431ef Binary files /dev/null and b/.git/objects/b4/5f1b9f680e2db0cf528ed294e2d98ac91bb2b8 differ diff --git a/.git/objects/b4/8221cdd4d1238e5974f50039fc266da7fbedca b/.git/objects/b4/8221cdd4d1238e5974f50039fc266da7fbedca new file mode 100644 index 0000000..0cd21a1 --- /dev/null +++ b/.git/objects/b4/8221cdd4d1238e5974f50039fc266da7fbedca @@ -0,0 +1,2 @@ +x-N E]+0b&f+/xGKR`cwν&+܈hP`!n ǍlF0]0S`53$HK8vhPzR#3bhe:2|R.>g 35D`HK4c \ No newline at end of file diff --git a/.git/objects/b4/98a80ce17b8e224907f82338f0b488cfd76f16 b/.git/objects/b4/98a80ce17b8e224907f82338f0b488cfd76f16 new file mode 100644 index 0000000..b0e670d Binary files /dev/null and b/.git/objects/b4/98a80ce17b8e224907f82338f0b488cfd76f16 differ diff --git a/.git/objects/b4/aa50ecf9162272b4996aef92573499c8df86af b/.git/objects/b4/aa50ecf9162272b4996aef92573499c8df86af new file mode 100644 index 0000000..b45aa20 Binary files /dev/null and b/.git/objects/b4/aa50ecf9162272b4996aef92573499c8df86af differ diff --git a/.git/objects/b4/b3cd94812fc3c23de67f796b433fe28b8c43a9 b/.git/objects/b4/b3cd94812fc3c23de67f796b433fe28b8c43a9 new file mode 100644 index 0000000..d6ab14a Binary files /dev/null and b/.git/objects/b4/b3cd94812fc3c23de67f796b433fe28b8c43a9 differ diff --git a/.git/objects/b4/bae2f9fe749ee8288307ec0876d7e33048681d b/.git/objects/b4/bae2f9fe749ee8288307ec0876d7e33048681d new file mode 100644 index 0000000..ce649f4 --- /dev/null +++ b/.git/objects/b4/bae2f9fe749ee8288307ec0876d7e33048681d @@ -0,0 +1,2 @@ +xMN0`9,A?qb*` &xR-s1,Dlf3o7y̠{ȉVhQMG|Iۮw*IW-(f;(gD-Z)ldCi+Ma }ϻȑ UmrVxJz {9O| u^R=JXWXt+ϨE_;U]f%11?}a \ No newline at end of file diff --git a/.git/objects/b6/362764471639b339266e9435f6262f1e7d3998 b/.git/objects/b6/362764471639b339266e9435f6262f1e7d3998 new file mode 100644 index 0000000..d79e16c Binary files /dev/null and b/.git/objects/b6/362764471639b339266e9435f6262f1e7d3998 differ diff --git a/.git/objects/b6/578cfa933af3ea6184db8e98a44b6f5b869419 b/.git/objects/b6/578cfa933af3ea6184db8e98a44b6f5b869419 new file mode 100644 index 0000000..9100c59 Binary files /dev/null and b/.git/objects/b6/578cfa933af3ea6184db8e98a44b6f5b869419 differ diff --git a/.git/objects/b6/6f103c769f830dbd7521c457a8ab260e958af2 b/.git/objects/b6/6f103c769f830dbd7521c457a8ab260e958af2 new file mode 100644 index 0000000..5c3af6e Binary files /dev/null and b/.git/objects/b6/6f103c769f830dbd7521c457a8ab260e958af2 differ diff --git a/.git/objects/b6/d2c560e7ac88828d1b11a92bb46f0d06f817b9 b/.git/objects/b6/d2c560e7ac88828d1b11a92bb46f0d06f817b9 new file mode 100644 index 0000000..25481ef Binary files /dev/null and b/.git/objects/b6/d2c560e7ac88828d1b11a92bb46f0d06f817b9 differ diff --git a/.git/objects/b6/ed1bf416d0b91362384824e15e01e2da6685ea b/.git/objects/b6/ed1bf416d0b91362384824e15e01e2da6685ea new file mode 100644 index 0000000..cfe882d Binary files /dev/null and b/.git/objects/b6/ed1bf416d0b91362384824e15e01e2da6685ea differ diff --git a/.git/objects/b6/f1f2219243a740492f4eb2e75a6e8501a3f574 b/.git/objects/b6/f1f2219243a740492f4eb2e75a6e8501a3f574 new file mode 100644 index 0000000..a1be06e --- /dev/null +++ b/.git/objects/b6/f1f2219243a740492f4eb2e75a6e8501a3f574 @@ -0,0 +1,2 @@ +x-MN0 Y#F4 A!q7u@Tnf`nƞ{1Zu7 +EkZcq0~oS}gGjVdJhMZշ}v)9jC5̙qOL1<nmpLs;H鴒 +%DK4sy#.XÎܴ9m7#_Np"o_?O!MpA/jPK8m 9U B1sl*F#mn \ No newline at end of file diff --git a/.git/objects/b6/f403930702d756d5960411602e6d89be45ed05 b/.git/objects/b6/f403930702d756d5960411602e6d89be45ed05 new file mode 100644 index 0000000..bcac4cc Binary files /dev/null and b/.git/objects/b6/f403930702d756d5960411602e6d89be45ed05 differ diff --git a/.git/objects/b7/189e4f5973266a71426b82b816270931c4d403 b/.git/objects/b7/189e4f5973266a71426b82b816270931c4d403 new file mode 100644 index 0000000..f8ff166 Binary files /dev/null and b/.git/objects/b7/189e4f5973266a71426b82b816270931c4d403 differ diff --git a/.git/objects/b7/2dfb7179fd818e249439d9e511b893a98df8c3 b/.git/objects/b7/2dfb7179fd818e249439d9e511b893a98df8c3 new file mode 100644 index 0000000..9205624 Binary files /dev/null and b/.git/objects/b7/2dfb7179fd818e249439d9e511b893a98df8c3 differ diff --git a/.git/objects/b7/53fa7e907a1ad3d4624f1bf1415ff6d0e69da5 b/.git/objects/b7/53fa7e907a1ad3d4624f1bf1415ff6d0e69da5 new file mode 100644 index 0000000..ffd630d Binary files /dev/null and b/.git/objects/b7/53fa7e907a1ad3d4624f1bf1415ff6d0e69da5 differ diff --git a/.git/objects/b7/5c879ab994ad940aa3030f65f25dc95f86959f b/.git/objects/b7/5c879ab994ad940aa3030f65f25dc95f86959f new file mode 100644 index 0000000..796f0c3 Binary files /dev/null and b/.git/objects/b7/5c879ab994ad940aa3030f65f25dc95f86959f differ diff --git a/.git/objects/b7/835cdfa1f33b87d6c5fe3261011a139b2d2d81 b/.git/objects/b7/835cdfa1f33b87d6c5fe3261011a139b2d2d81 new file mode 100644 index 0000000..30b334d Binary files /dev/null and b/.git/objects/b7/835cdfa1f33b87d6c5fe3261011a139b2d2d81 differ diff --git a/.git/objects/b7/ab47de93de94110909fd75f6c038c3aecacab5 b/.git/objects/b7/ab47de93de94110909fd75f6c038c3aecacab5 new file mode 100644 index 0000000..23a7671 Binary files /dev/null and b/.git/objects/b7/ab47de93de94110909fd75f6c038c3aecacab5 differ diff --git a/.git/objects/b7/b5ba8e1aacc934e06a5497380eca96d376922b b/.git/objects/b7/b5ba8e1aacc934e06a5497380eca96d376922b new file mode 100644 index 0000000..67c602c Binary files /dev/null and b/.git/objects/b7/b5ba8e1aacc934e06a5497380eca96d376922b differ diff --git a/.git/objects/b7/c1ca037b4cbba376ae2bbadff84a4477fd5ef6 b/.git/objects/b7/c1ca037b4cbba376ae2bbadff84a4477fd5ef6 new file mode 100644 index 0000000..63eb99d Binary files /dev/null and b/.git/objects/b7/c1ca037b4cbba376ae2bbadff84a4477fd5ef6 differ diff --git a/.git/objects/b7/f8ed56cd24f284b869f0324c1b842dd001e1ab b/.git/objects/b7/f8ed56cd24f284b869f0324c1b842dd001e1ab new file mode 100644 index 0000000..47b2e06 Binary files /dev/null and b/.git/objects/b7/f8ed56cd24f284b869f0324c1b842dd001e1ab differ diff --git a/.git/objects/b7/ff9ef401b127c51e9ebcf2f9e5b80ef6258964 b/.git/objects/b7/ff9ef401b127c51e9ebcf2f9e5b80ef6258964 new file mode 100644 index 0000000..5c1e961 Binary files /dev/null and b/.git/objects/b7/ff9ef401b127c51e9ebcf2f9e5b80ef6258964 differ diff --git a/.git/objects/b8/04c9b7c12384d327461c4282cf12004a54b99c b/.git/objects/b8/04c9b7c12384d327461c4282cf12004a54b99c new file mode 100644 index 0000000..e554b72 --- /dev/null +++ b/.git/objects/b8/04c9b7c12384d327461c4282cf12004a54b99c @@ -0,0 +1,4 @@ +x=N0Ds(?q !i8&&9w3z.8ћYʾU`!5O0RX5yvk:m(4X +zf51D +qybx HVlk'e +i)]U@=}jR"|_wft;J ߭{m4h4-|oly)m M:cj?iiK \ No newline at end of file diff --git a/.git/objects/b8/1c53d779fa3ce4eccfd70dd03ad6badf6932ee b/.git/objects/b8/1c53d779fa3ce4eccfd70dd03ad6badf6932ee new file mode 100644 index 0000000..dc74fd9 Binary files /dev/null and b/.git/objects/b8/1c53d779fa3ce4eccfd70dd03ad6badf6932ee differ diff --git a/.git/objects/b8/4c92e8959e6951d978b874374b8e0fa78fbe63 b/.git/objects/b8/4c92e8959e6951d978b874374b8e0fa78fbe63 new file mode 100644 index 0000000..02ec897 Binary files /dev/null and b/.git/objects/b8/4c92e8959e6951d978b874374b8e0fa78fbe63 differ diff --git a/.git/objects/b8/86d4a6abbfac0b0dda03a8297dea15a4d2a420 b/.git/objects/b8/86d4a6abbfac0b0dda03a8297dea15a4d2a420 new file mode 100644 index 0000000..3b3aa83 Binary files /dev/null and b/.git/objects/b8/86d4a6abbfac0b0dda03a8297dea15a4d2a420 differ diff --git a/.git/objects/b8/8727b96a13744257858a82583842c07dbaa4a8 b/.git/objects/b8/8727b96a13744257858a82583842c07dbaa4a8 new file mode 100644 index 0000000..2e278df Binary files /dev/null and b/.git/objects/b8/8727b96a13744257858a82583842c07dbaa4a8 differ diff --git a/.git/objects/b8/9bd8988917b3040df2e2ba582fad0b477cf7ab b/.git/objects/b8/9bd8988917b3040df2e2ba582fad0b477cf7ab new file mode 100644 index 0000000..f4e2efb --- /dev/null +++ b/.git/objects/b8/9bd8988917b3040df2e2ba582fad0b477cf7ab @@ -0,0 +1,4 @@ +x1N0Es)AH`;ؖVJ +h8M؛s1 (7.\EI bۡlFPk< +CĊPZmZ̞ ƒޠIZn;i2 R9B^R }xBmP)p-MMwmGlm8+Ot״\^ +hn?89xygp ̹j \ No newline at end of file diff --git a/.git/objects/b8/ac180e11b97701d3976401cc85f043255802cb b/.git/objects/b8/ac180e11b97701d3976401cc85f043255802cb new file mode 100644 index 0000000..a3d52b6 Binary files /dev/null and b/.git/objects/b8/ac180e11b97701d3976401cc85f043255802cb differ diff --git a/.git/objects/b8/bc19c13a2be54097db2e26322d5ae0a1a4d381 b/.git/objects/b8/bc19c13a2be54097db2e26322d5ae0a1a4d381 new file mode 100644 index 0000000..572853f Binary files /dev/null and b/.git/objects/b8/bc19c13a2be54097db2e26322d5ae0a1a4d381 differ diff --git a/.git/objects/b8/be6a22ce6e76489a745877fcc8c160143ac776 b/.git/objects/b8/be6a22ce6e76489a745877fcc8c160143ac776 new file mode 100644 index 0000000..97d2083 --- /dev/null +++ b/.git/objects/b8/be6a22ce6e76489a745877fcc8c160143ac776 @@ -0,0 +1,6 @@ +xMN0YU aÆLI)#ms1,Oy] + +C-0b:Q@ӣ4 FHQ + +(<}pŠEތ4ƣ}G: QB||;W$ͽԙv^s.g*=0a4<2X][\sb#_ғ?|ln+}h?r[Á0R [w \ No newline at end of file diff --git a/.git/objects/b9/6b68921bc29b106a954e26665828a1708cd197 b/.git/objects/b9/6b68921bc29b106a954e26665828a1708cd197 new file mode 100644 index 0000000..5c2b6c0 Binary files /dev/null and b/.git/objects/b9/6b68921bc29b106a954e26665828a1708cd197 differ diff --git a/.git/objects/b9/6e936ff846b3e20d5853d79efe7dedf1f73226 b/.git/objects/b9/6e936ff846b3e20d5853d79efe7dedf1f73226 new file mode 100644 index 0000000..69eeb21 Binary files /dev/null and b/.git/objects/b9/6e936ff846b3e20d5853d79efe7dedf1f73226 differ diff --git a/.git/objects/b9/81149030279a524381eb3d4e903e924b9d615b b/.git/objects/b9/81149030279a524381eb3d4e903e924b9d615b new file mode 100644 index 0000000..ea0782b Binary files /dev/null and b/.git/objects/b9/81149030279a524381eb3d4e903e924b9d615b differ diff --git a/.git/objects/b9/8b6c879ab87580a19276eac7e53bf18ebb6632 b/.git/objects/b9/8b6c879ab87580a19276eac7e53bf18ebb6632 new file mode 100644 index 0000000..e110b7d Binary files /dev/null and b/.git/objects/b9/8b6c879ab87580a19276eac7e53bf18ebb6632 differ diff --git a/.git/objects/b9/b20ff4c107a24946b174015bc2d3f4db1adc85 b/.git/objects/b9/b20ff4c107a24946b174015bc2d3f4db1adc85 new file mode 100644 index 0000000..ff45694 --- /dev/null +++ b/.git/objects/b9/b20ff4c107a24946b174015bc2d3f4db1adc85 @@ -0,0 +1 @@ +x%Ak {ίCEMbXžZCo3IF]Դl}']P|#hs6C`(u׷ JFTQKUb$`k4uYBCC&t'Q$kl؏5!+#|b KW49 RI!tٶXo9e9o!Nhܿ8ᲺhXTExɅoG)D}X3?ޡ''E2%96i +6}6QYr|2PB΂tM-J]|lMvxўteLL+XKhqL#:8Ev} ]A;  P*]Jֵ̅IKoP j \ No newline at end of file diff --git a/.git/objects/bd/842538f0715ab73b27fb131c27f7e8ed86d015 b/.git/objects/bd/842538f0715ab73b27fb131c27f7e8ed86d015 new file mode 100644 index 0000000..c4395ff Binary files /dev/null and b/.git/objects/bd/842538f0715ab73b27fb131c27f7e8ed86d015 differ diff --git a/.git/objects/bd/deeaa6136d99c36425561299604defd681b427 b/.git/objects/bd/deeaa6136d99c36425561299604defd681b427 new file mode 100644 index 0000000..a475fb2 Binary files /dev/null and b/.git/objects/bd/deeaa6136d99c36425561299604defd681b427 differ diff --git a/.git/objects/bd/e0e779d614e0a9b2231ed4eb09bff33f109450 b/.git/objects/bd/e0e779d614e0a9b2231ed4eb09bff33f109450 new file mode 100644 index 0000000..974f30f Binary files /dev/null and b/.git/objects/bd/e0e779d614e0a9b2231ed4eb09bff33f109450 differ diff --git a/.git/objects/bd/e15a67d30c8013295fa1a97377a44c1d1b6846 b/.git/objects/bd/e15a67d30c8013295fa1a97377a44c1d1b6846 new file mode 100644 index 0000000..30ab813 Binary files /dev/null and b/.git/objects/bd/e15a67d30c8013295fa1a97377a44c1d1b6846 differ diff --git a/.git/objects/be/0b458b4ef4a6df730a6e5dc49883690a8804f6 b/.git/objects/be/0b458b4ef4a6df730a6e5dc49883690a8804f6 new file mode 100644 index 0000000..4d11aab Binary files /dev/null and b/.git/objects/be/0b458b4ef4a6df730a6e5dc49883690a8804f6 differ diff --git a/.git/objects/be/51d9ba28cf52f6fd7d7a8f00eea9ffff1c470e b/.git/objects/be/51d9ba28cf52f6fd7d7a8f00eea9ffff1c470e new file mode 100644 index 0000000..c36e18c Binary files /dev/null and b/.git/objects/be/51d9ba28cf52f6fd7d7a8f00eea9ffff1c470e differ diff --git a/.git/objects/be/6230ea2fa594d76db7c2a5385947e7e97fd764 b/.git/objects/be/6230ea2fa594d76db7c2a5385947e7e97fd764 new file mode 100644 index 0000000..580e4d4 Binary files /dev/null and b/.git/objects/be/6230ea2fa594d76db7c2a5385947e7e97fd764 differ diff --git a/.git/objects/be/6a19f95ef5d6d7403e2b74485670cd5c5ddc0e b/.git/objects/be/6a19f95ef5d6d7403e2b74485670cd5c5ddc0e new file mode 100644 index 0000000..7189a4a Binary files /dev/null and b/.git/objects/be/6a19f95ef5d6d7403e2b74485670cd5c5ddc0e differ diff --git a/.git/objects/be/905e25490bae97d88852f80c1f6f476401b984 b/.git/objects/be/905e25490bae97d88852f80c1f6f476401b984 new file mode 100644 index 0000000..21faf27 Binary files /dev/null and b/.git/objects/be/905e25490bae97d88852f80c1f6f476401b984 differ diff --git a/.git/objects/be/ba629efb6b424968a2883868442e1a38643a1f b/.git/objects/be/ba629efb6b424968a2883868442e1a38643a1f new file mode 100644 index 0000000..808d370 Binary files /dev/null and b/.git/objects/be/ba629efb6b424968a2883868442e1a38643a1f differ diff --git a/.git/objects/bf/1382a0c17db34b9144a99be32af88dc0c6eb21 b/.git/objects/bf/1382a0c17db34b9144a99be32af88dc0c6eb21 new file mode 100644 index 0000000..62f4b82 Binary files /dev/null and b/.git/objects/bf/1382a0c17db34b9144a99be32af88dc0c6eb21 differ diff --git a/.git/objects/bf/2000a17eed4735eb16668b3cbfe0308b1640d4 b/.git/objects/bf/2000a17eed4735eb16668b3cbfe0308b1640d4 new file mode 100644 index 0000000..b8d5bbf Binary files /dev/null and b/.git/objects/bf/2000a17eed4735eb16668b3cbfe0308b1640d4 differ diff --git a/.git/objects/bf/5dbe74540a5d11ba1fb89693b38cbbec83eb0c b/.git/objects/bf/5dbe74540a5d11ba1fb89693b38cbbec83eb0c new file mode 100644 index 0000000..5683294 Binary files /dev/null and b/.git/objects/bf/5dbe74540a5d11ba1fb89693b38cbbec83eb0c differ diff --git a/.git/objects/bf/630cd7d42a884e8de0543d6bd720872ac97aeb b/.git/objects/bf/630cd7d42a884e8de0543d6bd720872ac97aeb new file mode 100644 index 0000000..aecfd33 Binary files /dev/null and b/.git/objects/bf/630cd7d42a884e8de0543d6bd720872ac97aeb differ diff --git a/.git/objects/bf/6f8df3791da021433efecfea4e3f43c72dc33e b/.git/objects/bf/6f8df3791da021433efecfea4e3f43c72dc33e new file mode 100644 index 0000000..efdf688 Binary files /dev/null and b/.git/objects/bf/6f8df3791da021433efecfea4e3f43c72dc33e differ diff --git a/.git/objects/bf/7823c2415e89dffed6fae5a657cecf1e58875f b/.git/objects/bf/7823c2415e89dffed6fae5a657cecf1e58875f new file mode 100644 index 0000000..3508dc6 Binary files /dev/null and b/.git/objects/bf/7823c2415e89dffed6fae5a657cecf1e58875f differ diff --git a/.git/objects/bf/9de64c8bcf79e9af82ba7a394dc13ace7ff249 b/.git/objects/bf/9de64c8bcf79e9af82ba7a394dc13ace7ff249 new file mode 100644 index 0000000..d50ec3c Binary files /dev/null and b/.git/objects/bf/9de64c8bcf79e9af82ba7a394dc13ace7ff249 differ diff --git a/.git/objects/bf/bb26fa0203ed282655c9f49b855de8930b9009 b/.git/objects/bf/bb26fa0203ed282655c9f49b855de8930b9009 new file mode 100644 index 0000000..0d25809 Binary files /dev/null and b/.git/objects/bf/bb26fa0203ed282655c9f49b855de8930b9009 differ diff --git a/.git/objects/bf/e64b9af8a1180602e6fd08762021857aee565a b/.git/objects/bf/e64b9af8a1180602e6fd08762021857aee565a new file mode 100644 index 0000000..a734a01 Binary files /dev/null and b/.git/objects/bf/e64b9af8a1180602e6fd08762021857aee565a differ diff --git a/.git/objects/c0/09863461221e85f67945d3af807ec17dea06f0 b/.git/objects/c0/09863461221e85f67945d3af807ec17dea06f0 new file mode 100644 index 0000000..3e7f04e --- /dev/null +++ b/.git/objects/c0/09863461221e85f67945d3af807ec17dea06f0 @@ -0,0 +1 @@ +x5MN0YoS۱TVa ^"#s1LfqyYbZ9w9/} F݊R˴Jx˱7UYf8i9XýNe+&Oޢ36JUmpDScN3pno+ce*q\FLpr]qޗ\]91 [mXiyr(wb\(@T>aKI68uJ{LANݻb)6l;%1/''(+AͲf֤޼)OE I.rQ3I۬[mFWjﵳ.B[uOR(ztҴN3]+H38=P31Ŕ̲T4a\CjXZf֗5Q i ASLڙ>mqM*t6 nkGh oK` abR-hel^AaA_)}4 tqV^~McYyNaZ-vw"ʊ~gO@8[gXõf!X_t`5 \ No newline at end of file diff --git a/.git/objects/c0/a182c902bfc4d0a3e0b1c3b6e684376fbbb617 b/.git/objects/c0/a182c902bfc4d0a3e0b1c3b6e684376fbbb617 new file mode 100644 index 0000000..e412d66 Binary files /dev/null and b/.git/objects/c0/a182c902bfc4d0a3e0b1c3b6e684376fbbb617 differ diff --git a/.git/objects/c0/b61d3c8f62c5817688677fab2437a3cd3b945d b/.git/objects/c0/b61d3c8f62c5817688677fab2437a3cd3b945d new file mode 100644 index 0000000..b735350 Binary files /dev/null and b/.git/objects/c0/b61d3c8f62c5817688677fab2437a3cd3b945d differ diff --git a/.git/objects/c0/c59475ecdb05f4c772b0a28a05785c27673270 b/.git/objects/c0/c59475ecdb05f4c772b0a28a05785c27673270 new file mode 100644 index 0000000..8f21988 Binary files /dev/null and b/.git/objects/c0/c59475ecdb05f4c772b0a28a05785c27673270 differ diff --git a/.git/objects/c0/c6bc12c27c1e1f989e7e4bb40f964b8fccdeaa b/.git/objects/c0/c6bc12c27c1e1f989e7e4bb40f964b8fccdeaa new file mode 100644 index 0000000..e9a780e Binary files /dev/null and b/.git/objects/c0/c6bc12c27c1e1f989e7e4bb40f964b8fccdeaa differ diff --git a/.git/objects/c0/facf9c734490be6e8fa5bf096de9c43b94bffe b/.git/objects/c0/facf9c734490be6e8fa5bf096de9c43b94bffe new file mode 100644 index 0000000..e23b275 Binary files /dev/null and b/.git/objects/c0/facf9c734490be6e8fa5bf096de9c43b94bffe differ diff --git a/.git/objects/c1/15d9a2fa7e10c04c8657a2d489d526e01a2fb1 b/.git/objects/c1/15d9a2fa7e10c04c8657a2d489d526e01a2fb1 new file mode 100644 index 0000000..2fac31e Binary files /dev/null and b/.git/objects/c1/15d9a2fa7e10c04c8657a2d489d526e01a2fb1 differ diff --git a/.git/objects/c1/358f93688fdf07eed6d9d6abbc07d5985eabbf b/.git/objects/c1/358f93688fdf07eed6d9d6abbc07d5985eabbf new file mode 100644 index 0000000..c7942ec Binary files /dev/null and b/.git/objects/c1/358f93688fdf07eed6d9d6abbc07d5985eabbf differ diff --git a/.git/objects/c1/547067bbc4302d46eea028d35524498548bf6b b/.git/objects/c1/547067bbc4302d46eea028d35524498548bf6b new file mode 100644 index 0000000..e6f1432 Binary files /dev/null and b/.git/objects/c1/547067bbc4302d46eea028d35524498548bf6b differ diff --git a/.git/objects/c1/6c6fcc313316b3c48a188743d06385491296b0 b/.git/objects/c1/6c6fcc313316b3c48a188743d06385491296b0 new file mode 100644 index 0000000..352befe Binary files /dev/null and b/.git/objects/c1/6c6fcc313316b3c48a188743d06385491296b0 differ diff --git a/.git/objects/c1/7fdcb50376a2c9de167194a2bfa8f2e40ed669 b/.git/objects/c1/7fdcb50376a2c9de167194a2bfa8f2e40ed669 new file mode 100644 index 0000000..573cb20 Binary files /dev/null and b/.git/objects/c1/7fdcb50376a2c9de167194a2bfa8f2e40ed669 differ diff --git a/.git/objects/c1/9874f2db3de05d43a349c122e1edbbf18d89c3 b/.git/objects/c1/9874f2db3de05d43a349c122e1edbbf18d89c3 new file mode 100644 index 0000000..0d38627 Binary files /dev/null and b/.git/objects/c1/9874f2db3de05d43a349c122e1edbbf18d89c3 differ diff --git a/.git/objects/c1/d8bdad8f1d146677f4c98b3e8dd4adba91164b b/.git/objects/c1/d8bdad8f1d146677f4c98b3e8dd4adba91164b new file mode 100644 index 0000000..66ac0b4 Binary files /dev/null and b/.git/objects/c1/d8bdad8f1d146677f4c98b3e8dd4adba91164b differ diff --git a/.git/objects/c1/db7e60531a0ddb4a98a414546b4093f75af27e b/.git/objects/c1/db7e60531a0ddb4a98a414546b4093f75af27e new file mode 100644 index 0000000..3e4977f Binary files /dev/null and b/.git/objects/c1/db7e60531a0ddb4a98a414546b4093f75af27e differ diff --git a/.git/objects/c1/f4abf9b9c7c167ed1a86ee588b6168a2179a2b b/.git/objects/c1/f4abf9b9c7c167ed1a86ee588b6168a2179a2b new file mode 100644 index 0000000..27f2c06 Binary files /dev/null and b/.git/objects/c1/f4abf9b9c7c167ed1a86ee588b6168a2179a2b differ diff --git a/.git/objects/c1/faa70a9b4d0b0cec26efda24db798c0db92109 b/.git/objects/c1/faa70a9b4d0b0cec26efda24db798c0db92109 new file mode 100644 index 0000000..b68e14e Binary files /dev/null and b/.git/objects/c1/faa70a9b4d0b0cec26efda24db798c0db92109 differ diff --git a/.git/objects/c1/fb05bcaef57ef2666ccfa1177d5d8d0b64d646 b/.git/objects/c1/fb05bcaef57ef2666ccfa1177d5d8d0b64d646 new file mode 100644 index 0000000..eeaa673 Binary files /dev/null and b/.git/objects/c1/fb05bcaef57ef2666ccfa1177d5d8d0b64d646 differ diff --git a/.git/objects/c2/180a98859e70d7c131021899e2d493037a71f2 b/.git/objects/c2/180a98859e70d7c131021899e2d493037a71f2 new file mode 100644 index 0000000..c0b011f Binary files /dev/null and b/.git/objects/c2/180a98859e70d7c131021899e2d493037a71f2 differ diff --git a/.git/objects/c2/275474bf2926c1c1083eb0d510a8110ffb6707 b/.git/objects/c2/275474bf2926c1c1083eb0d510a8110ffb6707 new file mode 100644 index 0000000..0dd73ba Binary files /dev/null and b/.git/objects/c2/275474bf2926c1c1083eb0d510a8110ffb6707 differ diff --git a/.git/objects/c2/2eedbb7c9446b23b06e85bb964b9d92f4447b3 b/.git/objects/c2/2eedbb7c9446b23b06e85bb964b9d92f4447b3 new file mode 100644 index 0000000..52cdcea Binary files /dev/null and b/.git/objects/c2/2eedbb7c9446b23b06e85bb964b9d92f4447b3 differ diff --git a/.git/objects/c2/588dfade8a6e932239a1f6f98e8671605fc380 b/.git/objects/c2/588dfade8a6e932239a1f6f98e8671605fc380 new file mode 100644 index 0000000..463ccce Binary files /dev/null and b/.git/objects/c2/588dfade8a6e932239a1f6f98e8671605fc380 differ diff --git a/.git/objects/c2/7e7f5dfd7c9ff9763cd0fde5086da856cf442b b/.git/objects/c2/7e7f5dfd7c9ff9763cd0fde5086da856cf442b new file mode 100644 index 0000000..fddbaf2 Binary files /dev/null and b/.git/objects/c2/7e7f5dfd7c9ff9763cd0fde5086da856cf442b differ diff --git a/.git/objects/c2/93db6d518d049fde5c328c268a03c693f5dbd2 b/.git/objects/c2/93db6d518d049fde5c328c268a03c693f5dbd2 new file mode 100644 index 0000000..6bd6959 --- /dev/null +++ b/.git/objects/c2/93db6d518d049fde5c328c268a03c693f5dbd2 @@ -0,0 +1,3 @@ +x-IN0EYGDV 5b N`;$RbGCbX]꿧 +y] +LZ!PT SΩ<1Z(nYIgʣsQhf\謏6F-kѹN˂_. X}yq >~K]ou©ErtcNg &RFx$m[|$=Ȕk'X'835WrdeCձtI^{QyxI홖 +-PuEi9@-wr`n78'/,&?oj5*{rB?jms2-I-. J-.)8w<nش(`i[T)(4f^?-Yw9ã{f,"+;C Iy=>`cl\Te˗X-qG~9* K] \ No newline at end of file diff --git a/.git/objects/c5/093663651cb297b88e74ceca2b16d245f4110f b/.git/objects/c5/093663651cb297b88e74ceca2b16d245f4110f new file mode 100644 index 0000000..e0e4b28 Binary files /dev/null and b/.git/objects/c5/093663651cb297b88e74ceca2b16d245f4110f differ diff --git a/.git/objects/c5/21ee588842006e4e8ae4532f861287154e42a2 b/.git/objects/c5/21ee588842006e4e8ae4532f861287154e42a2 new file mode 100644 index 0000000..5ed0519 Binary files /dev/null and b/.git/objects/c5/21ee588842006e4e8ae4532f861287154e42a2 differ diff --git a/.git/objects/c5/2b8b5dc72acfe06a1b35ced8818a3fc0ee6671 b/.git/objects/c5/2b8b5dc72acfe06a1b35ced8818a3fc0ee6671 new file mode 100644 index 0000000..eed6ba9 Binary files /dev/null and b/.git/objects/c5/2b8b5dc72acfe06a1b35ced8818a3fc0ee6671 differ diff --git a/.git/objects/c5/2d36af40006c5a0bd08688b8ca6ab0ee59f407 b/.git/objects/c5/2d36af40006c5a0bd08688b8ca6ab0ee59f407 new file mode 100644 index 0000000..86edf43 Binary files /dev/null and b/.git/objects/c5/2d36af40006c5a0bd08688b8ca6ab0ee59f407 differ diff --git a/.git/objects/c5/47b5532d3819a8d235a9077324f94ba6d20e2f b/.git/objects/c5/47b5532d3819a8d235a9077324f94ba6d20e2f new file mode 100644 index 0000000..a3bd1fa Binary files /dev/null and b/.git/objects/c5/47b5532d3819a8d235a9077324f94ba6d20e2f differ diff --git a/.git/objects/c5/6b4a81547f7c53fc4ca16c6a07f1d3e67572a5 b/.git/objects/c5/6b4a81547f7c53fc4ca16c6a07f1d3e67572a5 new file mode 100644 index 0000000..bf37de3 Binary files /dev/null and b/.git/objects/c5/6b4a81547f7c53fc4ca16c6a07f1d3e67572a5 differ diff --git a/.git/objects/c5/a437ea6c23eb0aa7cfa2c653295a7fba8d69b0 b/.git/objects/c5/a437ea6c23eb0aa7cfa2c653295a7fba8d69b0 new file mode 100644 index 0000000..75905a4 Binary files /dev/null and b/.git/objects/c5/a437ea6c23eb0aa7cfa2c653295a7fba8d69b0 differ diff --git a/.git/objects/c5/ad1ee3a5f8fe65a95e41acee4b51b8fa9640ee b/.git/objects/c5/ad1ee3a5f8fe65a95e41acee4b51b8fa9640ee new file mode 100644 index 0000000..b4a1200 Binary files /dev/null and b/.git/objects/c5/ad1ee3a5f8fe65a95e41acee4b51b8fa9640ee differ diff --git a/.git/objects/c5/ef52b1d82e20574fcca8d4b4aacd7ccf2fd2c6 b/.git/objects/c5/ef52b1d82e20574fcca8d4b4aacd7ccf2fd2c6 new file mode 100644 index 0000000..9a46306 Binary files /dev/null and b/.git/objects/c5/ef52b1d82e20574fcca8d4b4aacd7ccf2fd2c6 differ diff --git a/.git/objects/c6/37aa3d2f6ebd9ddaafded80c04150751e4d812 b/.git/objects/c6/37aa3d2f6ebd9ddaafded80c04150751e4d812 new file mode 100644 index 0000000..90b049c Binary files /dev/null and b/.git/objects/c6/37aa3d2f6ebd9ddaafded80c04150751e4d812 differ diff --git a/.git/objects/c6/3c70ac72dd9748e7f66c39d015e921328bc6f6 b/.git/objects/c6/3c70ac72dd9748e7f66c39d015e921328bc6f6 new file mode 100644 index 0000000..816d5bb Binary files /dev/null and b/.git/objects/c6/3c70ac72dd9748e7f66c39d015e921328bc6f6 differ diff --git a/.git/objects/c6/72b89c945370781a66f584a4dd3026ba93d267 b/.git/objects/c6/72b89c945370781a66f584a4dd3026ba93d267 new file mode 100644 index 0000000..064d312 Binary files /dev/null and b/.git/objects/c6/72b89c945370781a66f584a4dd3026ba93d267 differ diff --git a/.git/objects/c6/74e8277a0e6e9fae037dc54d2b087a7fe527fe b/.git/objects/c6/74e8277a0e6e9fae037dc54d2b087a7fe527fe new file mode 100644 index 0000000..b4a3dff Binary files /dev/null and b/.git/objects/c6/74e8277a0e6e9fae037dc54d2b087a7fe527fe differ diff --git a/.git/objects/c6/91d72a915875287daf50a733dd2a0ea1c1bfa0 b/.git/objects/c6/91d72a915875287daf50a733dd2a0ea1c1bfa0 new file mode 100644 index 0000000..bcb3041 Binary files /dev/null and b/.git/objects/c6/91d72a915875287daf50a733dd2a0ea1c1bfa0 differ diff --git a/.git/objects/c6/a0bad9808e1af45e3f555d7a68c80d18cfa771 b/.git/objects/c6/a0bad9808e1af45e3f555d7a68c80d18cfa771 new file mode 100644 index 0000000..c08f3c1 Binary files /dev/null and b/.git/objects/c6/a0bad9808e1af45e3f555d7a68c80d18cfa771 differ diff --git a/.git/objects/c6/a12ad646bea6eac7f614e26745bf3d6c83db1f b/.git/objects/c6/a12ad646bea6eac7f614e26745bf3d6c83db1f new file mode 100644 index 0000000..16d17fe Binary files /dev/null and b/.git/objects/c6/a12ad646bea6eac7f614e26745bf3d6c83db1f differ diff --git a/.git/objects/c6/dac4c6a330b7401ab522eccbd7a34bacab6697 b/.git/objects/c6/dac4c6a330b7401ab522eccbd7a34bacab6697 new file mode 100644 index 0000000..8d7a89b Binary files /dev/null and b/.git/objects/c6/dac4c6a330b7401ab522eccbd7a34bacab6697 differ diff --git a/.git/objects/c6/e3cc1007896eec427479f2389e0c60cc73d2b7 b/.git/objects/c6/e3cc1007896eec427479f2389e0c60cc73d2b7 new file mode 100644 index 0000000..f606393 --- /dev/null +++ b/.git/objects/c6/e3cc1007896eec427479f2389e0c60cc73d2b7 @@ -0,0 +1,2 @@ +x%N;N0)G<1zBQC nbɱ#'!f\ h4?K7P24hZ'vJ73RGfǶ%vՂuT5̺ WoS@޼Kϕ"H+\mDyqi~dvBJ B Q˔ +)?rðϗcz #<+ӱʏ\He׍8SOU_~ \ No newline at end of file diff --git a/.git/objects/c6/f0a071a1078d07d3c971c70a62741059fc0d81 b/.git/objects/c6/f0a071a1078d07d3c971c70a62741059fc0d81 new file mode 100644 index 0000000..cbb8e53 Binary files /dev/null and b/.git/objects/c6/f0a071a1078d07d3c971c70a62741059fc0d81 differ diff --git a/.git/objects/c7/1456d159643e84cd1d8a7a0dcd729dd195539a b/.git/objects/c7/1456d159643e84cd1d8a7a0dcd729dd195539a new file mode 100644 index 0000000..1c20fa8 --- /dev/null +++ b/.git/objects/c7/1456d159643e84cd1d8a7a0dcd729dd195539a @@ -0,0 +1,2 @@ +x-Kj0)f_j4zq%] R4YXEj~|c UO91Dzi"Zc XZ+z]9 JC"mkIKk;FdVJ3FA-O1e; >3+IW8QqyD@c {m +jg!;)>b).qy[﫯mֈ‹Х^8>#;T|||wY \ No newline at end of file diff --git a/.git/objects/c7/49c53f3cd9b4591668cfec35c4aa4ee4741ba4 b/.git/objects/c7/49c53f3cd9b4591668cfec35c4aa4ee4741ba4 new file mode 100644 index 0000000..76d4006 Binary files /dev/null and b/.git/objects/c7/49c53f3cd9b4591668cfec35c4aa4ee4741ba4 differ diff --git a/.git/objects/c7/5f42bd8c58d2c5bbf258ad953facfa2d338dc6 b/.git/objects/c7/5f42bd8c58d2c5bbf258ad953facfa2d338dc6 new file mode 100644 index 0000000..d053718 Binary files /dev/null and b/.git/objects/c7/5f42bd8c58d2c5bbf258ad953facfa2d338dc6 differ diff --git a/.git/objects/c7/bdd32b9f2098d2a48ec6f1f13877e4b6e1e003 b/.git/objects/c7/bdd32b9f2098d2a48ec6f1f13877e4b6e1e003 new file mode 100644 index 0000000..14547fa Binary files /dev/null and b/.git/objects/c7/bdd32b9f2098d2a48ec6f1f13877e4b6e1e003 differ diff --git a/.git/objects/c7/da357a4c5b2cf94879f062c311dc39c98e9616 b/.git/objects/c7/da357a4c5b2cf94879f062c311dc39c98e9616 new file mode 100644 index 0000000..57cf189 Binary files /dev/null and b/.git/objects/c7/da357a4c5b2cf94879f062c311dc39c98e9616 differ diff --git a/.git/objects/c7/ffc1bd91a0954f1bce1f8524ed74da7989fedc b/.git/objects/c7/ffc1bd91a0954f1bce1f8524ed74da7989fedc new file mode 100644 index 0000000..f07bfdf Binary files /dev/null and b/.git/objects/c7/ffc1bd91a0954f1bce1f8524ed74da7989fedc differ diff --git a/.git/objects/c8/4491e1079c6fb1d012b754e78b0993f19c3fbd b/.git/objects/c8/4491e1079c6fb1d012b754e78b0993f19c3fbd new file mode 100644 index 0000000..adde186 Binary files /dev/null and b/.git/objects/c8/4491e1079c6fb1d012b754e78b0993f19c3fbd differ diff --git a/.git/objects/c8/751c13b0d45343d9a29e2206b8e2ae113c6647 b/.git/objects/c8/751c13b0d45343d9a29e2206b8e2ae113c6647 new file mode 100644 index 0000000..37f6e47 Binary files /dev/null and b/.git/objects/c8/751c13b0d45343d9a29e2206b8e2ae113c6647 differ diff --git a/.git/objects/c8/b93843d7191b666984eea89496116527044549 b/.git/objects/c8/b93843d7191b666984eea89496116527044549 new file mode 100644 index 0000000..bcd7644 Binary files /dev/null and b/.git/objects/c8/b93843d7191b666984eea89496116527044549 differ diff --git a/.git/objects/c8/bdd765e9390ea33aea0d52e1d8219a4906846f b/.git/objects/c8/bdd765e9390ea33aea0d52e1d8219a4906846f new file mode 100644 index 0000000..3984b09 --- /dev/null +++ b/.git/objects/c8/bdd765e9390ea33aea0d52e1d8219a4906846f @@ -0,0 +1 @@ +xN ])fobB Qwn\ Ss!ܞ|90Jsd-j?I!m &#cRЈhJj+e*F3aFZt(Q zBG1R~H^X6nfjp{ -=R(|~ RigSVPB ]wkqhR %l ~;:\%|RguPqk \ No newline at end of file diff --git a/.git/objects/c8/c3a53c7b4e325ad7fb9b71bf196da69d7431c1 b/.git/objects/c8/c3a53c7b4e325ad7fb9b71bf196da69d7431c1 new file mode 100644 index 0000000..1adfc90 Binary files /dev/null and b/.git/objects/c8/c3a53c7b4e325ad7fb9b71bf196da69d7431c1 differ diff --git a/.git/objects/c8/cbcc085c46ee9a784ed4f0d66a8b496c80575e b/.git/objects/c8/cbcc085c46ee9a784ed4f0d66a8b496c80575e new file mode 100644 index 0000000..3ef3568 Binary files /dev/null and b/.git/objects/c8/cbcc085c46ee9a784ed4f0d66a8b496c80575e differ diff --git a/.git/objects/c8/d7246a7d42904060033fe4496055a554382f68 b/.git/objects/c8/d7246a7d42904060033fe4496055a554382f68 new file mode 100644 index 0000000..1ce4549 Binary files /dev/null and b/.git/objects/c8/d7246a7d42904060033fe4496055a554382f68 differ diff --git a/.git/objects/c8/dcdbdbd3c1000d938fe07ec349a2a2f6478d66 b/.git/objects/c8/dcdbdbd3c1000d938fe07ec349a2a2f6478d66 new file mode 100644 index 0000000..b982396 Binary files /dev/null and b/.git/objects/c8/dcdbdbd3c1000d938fe07ec349a2a2f6478d66 differ diff --git a/.git/objects/c9/0d271886c0d535e77513be4c97cc33f0d2c27b b/.git/objects/c9/0d271886c0d535e77513be4c97cc33f0d2c27b new file mode 100644 index 0000000..0e91c4f Binary files /dev/null and b/.git/objects/c9/0d271886c0d535e77513be4c97cc33f0d2c27b differ diff --git a/.git/objects/c9/2f7b1e28ef0113295822326b2fd9f471592d9c b/.git/objects/c9/2f7b1e28ef0113295822326b2fd9f471592d9c new file mode 100644 index 0000000..a56e42d Binary files /dev/null and b/.git/objects/c9/2f7b1e28ef0113295822326b2fd9f471592d9c differ diff --git a/.git/objects/c9/4b8053a33c890e9a29d02b4158ddeac6004bac b/.git/objects/c9/4b8053a33c890e9a29d02b4158ddeac6004bac new file mode 100644 index 0000000..e4f7f28 Binary files /dev/null and b/.git/objects/c9/4b8053a33c890e9a29d02b4158ddeac6004bac differ diff --git a/.git/objects/c9/5da59dd1823947a1e0a18e74cef0ec36d6d1d4 b/.git/objects/c9/5da59dd1823947a1e0a18e74cef0ec36d6d1d4 new file mode 100644 index 0000000..91118e2 --- /dev/null +++ b/.git/objects/c9/5da59dd1823947a1e0a18e74cef0ec36d6d1d4 @@ -0,0 +1,2 @@ +x-N09)֩ĨB8 OĎG7΋nFq UrRcvhm0+SdWBICmj!4 1ʐqTWӈ]koCA[b_D';]H{zʃ{%vp+9/`79byyҸ%yM\~.cvNjxP +kzYzXe)>] \ No newline at end of file diff --git a/.git/objects/c9/6449676d1339ec46bdb8fe50ac6a5bccc1cddf b/.git/objects/c9/6449676d1339ec46bdb8fe50ac6a5bccc1cddf new file mode 100644 index 0000000..7cd1b27 Binary files /dev/null and b/.git/objects/c9/6449676d1339ec46bdb8fe50ac6a5bccc1cddf differ diff --git a/.git/objects/c9/7295ec21000c688b131e491456f1f830a0ffda b/.git/objects/c9/7295ec21000c688b131e491456f1f830a0ffda new file mode 100644 index 0000000..35b0a68 Binary files /dev/null and b/.git/objects/c9/7295ec21000c688b131e491456f1f830a0ffda differ diff --git a/.git/objects/c9/ae56ffa97033b5b6452ce60ff5f550c92d6691 b/.git/objects/c9/ae56ffa97033b5b6452ce60ff5f550c92d6691 new file mode 100644 index 0000000..cb01929 Binary files /dev/null and b/.git/objects/c9/ae56ffa97033b5b6452ce60ff5f550c92d6691 differ diff --git a/.git/objects/c9/d0b394c3b3bf0b4cc666ed2a56dbb8f12a5ae2 b/.git/objects/c9/d0b394c3b3bf0b4cc666ed2a56dbb8f12a5ae2 new file mode 100644 index 0000000..a44a686 Binary files /dev/null and b/.git/objects/c9/d0b394c3b3bf0b4cc666ed2a56dbb8f12a5ae2 differ diff --git a/.git/objects/c9/e68a6d361c561e3a5052153c94bf16d952cd5e b/.git/objects/c9/e68a6d361c561e3a5052153c94bf16d952cd5e new file mode 100644 index 0000000..823cead Binary files /dev/null and b/.git/objects/c9/e68a6d361c561e3a5052153c94bf16d952cd5e differ diff --git a/.git/objects/c9/e86283c4ef460a988aa584f5e7c029f6b36e2d b/.git/objects/c9/e86283c4ef460a988aa584f5e7c029f6b36e2d new file mode 100644 index 0000000..d45c7e2 Binary files /dev/null and b/.git/objects/c9/e86283c4ef460a988aa584f5e7c029f6b36e2d differ diff --git a/.git/objects/ca/0e99e51f1966c9668e91534eed77a7deb0a2fd b/.git/objects/ca/0e99e51f1966c9668e91534eed77a7deb0a2fd new file mode 100644 index 0000000..ad0f04c Binary files /dev/null and b/.git/objects/ca/0e99e51f1966c9668e91534eed77a7deb0a2fd differ diff --git a/.git/objects/ca/2316cef4074769d3bf29accaf026cd69bf3e17 b/.git/objects/ca/2316cef4074769d3bf29accaf026cd69bf3e17 new file mode 100644 index 0000000..f324310 Binary files /dev/null and b/.git/objects/ca/2316cef4074769d3bf29accaf026cd69bf3e17 differ diff --git a/.git/objects/ca/23e5314c9c7895e7d8cfe5e28be3bd47809b87 b/.git/objects/ca/23e5314c9c7895e7d8cfe5e28be3bd47809b87 new file mode 100644 index 0000000..3e6fe10 Binary files /dev/null and b/.git/objects/ca/23e5314c9c7895e7d8cfe5e28be3bd47809b87 differ diff --git a/.git/objects/ca/296707efac16d432b9ebfe4a2fdb21fd738244 b/.git/objects/ca/296707efac16d432b9ebfe4a2fdb21fd738244 new file mode 100644 index 0000000..cc11f73 Binary files /dev/null and b/.git/objects/ca/296707efac16d432b9ebfe4a2fdb21fd738244 differ diff --git a/.git/objects/ca/32b07b1f675451ed2868848b79e0aea2111e26 b/.git/objects/ca/32b07b1f675451ed2868848b79e0aea2111e26 new file mode 100644 index 0000000..effbbf3 Binary files /dev/null and b/.git/objects/ca/32b07b1f675451ed2868848b79e0aea2111e26 differ diff --git a/.git/objects/ca/4bd86110a29d16126ba708e235c600106dbc37 b/.git/objects/ca/4bd86110a29d16126ba708e235c600106dbc37 new file mode 100644 index 0000000..e2d99db Binary files /dev/null and b/.git/objects/ca/4bd86110a29d16126ba708e235c600106dbc37 differ diff --git a/.git/objects/ca/903bb0e088aba55e765c312454344ec5de5a9e b/.git/objects/ca/903bb0e088aba55e765c312454344ec5de5a9e new file mode 100644 index 0000000..5b981ad Binary files /dev/null and b/.git/objects/ca/903bb0e088aba55e765c312454344ec5de5a9e differ diff --git a/.git/objects/ca/d36e4f7d14686f000439ab417962ecf34d87bd b/.git/objects/ca/d36e4f7d14686f000439ab417962ecf34d87bd new file mode 100644 index 0000000..f79a4f6 Binary files /dev/null and b/.git/objects/ca/d36e4f7d14686f000439ab417962ecf34d87bd differ diff --git a/.git/objects/ca/e674f5a2e65eeff8f6e36bfafa72dbb08ad11a b/.git/objects/ca/e674f5a2e65eeff8f6e36bfafa72dbb08ad11a new file mode 100644 index 0000000..e51a14e Binary files /dev/null and b/.git/objects/ca/e674f5a2e65eeff8f6e36bfafa72dbb08ad11a differ diff --git a/.git/objects/ca/e6d5204288a9bb9e1442f9bd8038f3d657209d b/.git/objects/ca/e6d5204288a9bb9e1442f9bd8038f3d657209d new file mode 100644 index 0000000..a56c95a Binary files /dev/null and b/.git/objects/ca/e6d5204288a9bb9e1442f9bd8038f3d657209d differ diff --git a/.git/objects/ca/f65e386963c13707107a3b6566653eda3b56f1 b/.git/objects/ca/f65e386963c13707107a3b6566653eda3b56f1 new file mode 100644 index 0000000..e8034b5 --- /dev/null +++ b/.git/objects/ca/f65e386963c13707107a3b6566653eda3b56f1 @@ -0,0 +1 @@ +xNN0fS܎7qRUba,0^sc)+Q雱bX>}&/ Q> aR㨝 :I~drAXF+%;*Y7j3W me N PÛ=sϿ8Þz,3]b&@B#³B4KypBf}#-ޮe=z=ƛӲlSLPۇl}U\ \ No newline at end of file diff --git a/.git/objects/ca/fb40f0fae73e09f5315ed2306837c9db19c4de b/.git/objects/ca/fb40f0fae73e09f5315ed2306837c9db19c4de new file mode 100644 index 0000000..7c1dd54 Binary files /dev/null and b/.git/objects/ca/fb40f0fae73e09f5315ed2306837c9db19c4de differ diff --git a/.git/objects/cb/e69cf3c95f4a84ebb49296ca9c467211c75aac b/.git/objects/cb/e69cf3c95f4a84ebb49296ca9c467211c75aac new file mode 100644 index 0000000..0a77631 Binary files /dev/null and b/.git/objects/cb/e69cf3c95f4a84ebb49296ca9c467211c75aac differ diff --git a/.git/objects/cc/03e179374b6d8a2421865c9a3534b770ae7c83 b/.git/objects/cc/03e179374b6d8a2421865c9a3534b770ae7c83 new file mode 100644 index 0000000..48df49b --- /dev/null +++ b/.git/objects/cc/03e179374b6d8a2421865c9a3534b770ae7c83 @@ -0,0 +1,3 @@ +x-KN0YGD~6NU"Lic) +{./}c@h%uDHNs=Jû Iq3ᤳ4i1 B q+^$2/ }cp۸-Sߟ( {.3-/x۸>\6F! <2X]|dK]}=zs5jOLz۶xp q\lk}n|[r +_*9h'O 'g \ No newline at end of file diff --git a/.git/objects/cc/337beb5a42e060a575537c7f354359ba76b838 b/.git/objects/cc/337beb5a42e060a575537c7f354359ba76b838 new file mode 100644 index 0000000..67e0ca6 Binary files /dev/null and b/.git/objects/cc/337beb5a42e060a575537c7f354359ba76b838 differ diff --git a/.git/objects/cc/bc842d5ca1f1b4cc1adb8c849f4b505aafe52a b/.git/objects/cc/bc842d5ca1f1b4cc1adb8c849f4b505aafe52a new file mode 100644 index 0000000..3360b01 --- /dev/null +++ b/.git/objects/cc/bc842d5ca1f1b4cc1adb8c849f4b505aafe52a @@ -0,0 +1,3 @@ +x%N0DY+َR*Cqq1t73\Dp +|0h/Mt|0 +6iDd!P$6[psAj!%'k7^u1F%2]߷p)Lzn9]ȅhJQ%x[RK--Rj c! \ No newline at end of file diff --git a/.git/objects/cd/9a2177bd5a960d5e9002e73012c92c2fb33773 b/.git/objects/cd/9a2177bd5a960d5e9002e73012c92c2fb33773 new file mode 100644 index 0000000..8019410 Binary files /dev/null and b/.git/objects/cd/9a2177bd5a960d5e9002e73012c92c2fb33773 differ diff --git a/.git/objects/cd/d17598933f9570d3036e6337eae35c89590492 b/.git/objects/cd/d17598933f9570d3036e6337eae35c89590492 new file mode 100644 index 0000000..ec795f7 Binary files /dev/null and b/.git/objects/cd/d17598933f9570d3036e6337eae35c89590492 differ diff --git a/.git/objects/cd/ee3a77e9b263c7cc276460ec487dce3ed47dcf b/.git/objects/cd/ee3a77e9b263c7cc276460ec487dce3ed47dcf new file mode 100644 index 0000000..9ecdf01 --- /dev/null +++ b/.git/objects/cd/ee3a77e9b263c7cc276460ec487dce3ed47dcf @@ -0,0 +1 @@ +x-n0D{+^FD=~b%1cEQoyiCF/%3aWH,Br}60j̱ӦELbЬa:۶h+cp +GɑW8ё^QIn)>j3ѷ6 V;c+||';?Ņm%64{7s^CkiWa \ No newline at end of file diff --git a/.git/objects/cd/fb1bf3415ac6b69e3017723986283d665be3ef b/.git/objects/cd/fb1bf3415ac6b69e3017723986283d665be3ef new file mode 100644 index 0000000..e9bca9a Binary files /dev/null and b/.git/objects/cd/fb1bf3415ac6b69e3017723986283d665be3ef differ diff --git a/.git/objects/ce/3848a293c532d4a801c38becb1c91292501687 b/.git/objects/ce/3848a293c532d4a801c38becb1c91292501687 new file mode 100644 index 0000000..a06ad31 Binary files /dev/null and b/.git/objects/ce/3848a293c532d4a801c38becb1c91292501687 differ diff --git a/.git/objects/ce/5a2f236337fec652738942ce9a94734896f271 b/.git/objects/ce/5a2f236337fec652738942ce9a94734896f271 new file mode 100644 index 0000000..6acb4a6 Binary files /dev/null and b/.git/objects/ce/5a2f236337fec652738942ce9a94734896f271 differ diff --git a/.git/objects/ce/816b372c88ff2cdffb3e441975feb18300d14a b/.git/objects/ce/816b372c88ff2cdffb3e441975feb18300d14a new file mode 100644 index 0000000..8ed15ec Binary files /dev/null and b/.git/objects/ce/816b372c88ff2cdffb3e441975feb18300d14a differ diff --git a/.git/objects/ce/93240cbb586a94929c05b86b1cf43650696c7a b/.git/objects/ce/93240cbb586a94929c05b86b1cf43650696c7a new file mode 100644 index 0000000..8f8d21e Binary files /dev/null and b/.git/objects/ce/93240cbb586a94929c05b86b1cf43650696c7a differ diff --git a/.git/objects/ce/c6fac2e02f5c565522288e6ebaae9d65a72a72 b/.git/objects/ce/c6fac2e02f5c565522288e6ebaae9d65a72a72 new file mode 100644 index 0000000..4a18fee Binary files /dev/null and b/.git/objects/ce/c6fac2e02f5c565522288e6ebaae9d65a72a72 differ diff --git a/.git/objects/ce/d9b16cae17a38dac5d82aff4466e7794dd7c84 b/.git/objects/ce/d9b16cae17a38dac5d82aff4466e7794dd7c84 new file mode 100644 index 0000000..b145350 --- /dev/null +++ b/.git/objects/ce/d9b16cae17a38dac5d82aff4466e7794dd7c84 @@ -0,0 +1,3 @@ +x5Mj0)f_j$9IJB'K#[`KAIs{Bw\޶XA}kP F +'jv ʻFSUPZAkU`2 +~Ys~&pF3 p;$^&R%˜lu2Yz +Q-4?Ij8?8|d[) p 8ۓDQ)oz+zYL*Q!s|͕bC{"s!xlIW4|PP5˓[Kl?9/A[o7; \ No newline at end of file diff --git a/.git/objects/d4/3cb56dd65d174b8567eba286836dddfbc763c7 b/.git/objects/d4/3cb56dd65d174b8567eba286836dddfbc763c7 new file mode 100644 index 0000000..8479da1 --- /dev/null +++ b/.git/objects/d4/3cb56dd65d174b8567eba286836dddfbc763c7 @@ -0,0 +1,3 @@ +x1N0Ds푐u BJNIvH.H3OO3*8»ZDZ@)0 jLQu +aZ  ΢z vN˅~~_R \ No newline at end of file diff --git a/.git/objects/d4/4ad0d14f59cd41cd246f3b8711e9a97cfa19e4 b/.git/objects/d4/4ad0d14f59cd41cd246f3b8711e9a97cfa19e4 new file mode 100644 index 0000000..5e06492 Binary files /dev/null and b/.git/objects/d4/4ad0d14f59cd41cd246f3b8711e9a97cfa19e4 differ diff --git a/.git/objects/d4/6f2a43298b9fc0b75267851370e817295765e7 b/.git/objects/d4/6f2a43298b9fc0b75267851370e817295765e7 new file mode 100644 index 0000000..1c0f395 Binary files /dev/null and b/.git/objects/d4/6f2a43298b9fc0b75267851370e817295765e7 differ diff --git a/.git/objects/d4/74576dbd37fe880e8608c0007ec16effee4b3e b/.git/objects/d4/74576dbd37fe880e8608c0007ec16effee4b3e new file mode 100644 index 0000000..0f32856 Binary files /dev/null and b/.git/objects/d4/74576dbd37fe880e8608c0007ec16effee4b3e differ diff --git a/.git/objects/d4/7ae4defd4055810e1ee4e03f280ab9e138291c b/.git/objects/d4/7ae4defd4055810e1ee4e03f280ab9e138291c new file mode 100644 index 0000000..04af601 Binary files /dev/null and b/.git/objects/d4/7ae4defd4055810e1ee4e03f280ab9e138291c differ diff --git a/.git/objects/d4/7f99e8242b80b7a60b875aaf75c8fe4b42c1f0 b/.git/objects/d4/7f99e8242b80b7a60b875aaf75c8fe4b42c1f0 new file mode 100644 index 0000000..d03bcb0 Binary files /dev/null and b/.git/objects/d4/7f99e8242b80b7a60b875aaf75c8fe4b42c1f0 differ diff --git a/.git/objects/d4/8d52bb5c610d2f3412c0c7b0220c49d598586b b/.git/objects/d4/8d52bb5c610d2f3412c0c7b0220c49d598586b new file mode 100644 index 0000000..19568fc Binary files /dev/null and b/.git/objects/d4/8d52bb5c610d2f3412c0c7b0220c49d598586b differ diff --git a/.git/objects/d4/903daad8ac2c75ff7ec86fff88ae6d7a7d2d11 b/.git/objects/d4/903daad8ac2c75ff7ec86fff88ae6d7a7d2d11 new file mode 100644 index 0000000..2f0ab1f Binary files /dev/null and b/.git/objects/d4/903daad8ac2c75ff7ec86fff88ae6d7a7d2d11 differ diff --git a/.git/objects/d4/a0ee9b667965137505bcb7123c9eb426177d93 b/.git/objects/d4/a0ee9b667965137505bcb7123c9eb426177d93 new file mode 100644 index 0000000..c24850b Binary files /dev/null and b/.git/objects/d4/a0ee9b667965137505bcb7123c9eb426177d93 differ diff --git a/.git/objects/d4/c09ee6f3b87cc14d15ce8eacbc99f7851dd68b b/.git/objects/d4/c09ee6f3b87cc14d15ce8eacbc99f7851dd68b new file mode 100644 index 0000000..6d81ddc --- /dev/null +++ b/.git/objects/d4/c09ee6f3b87cc14d15ce8eacbc99f7851dd68b @@ -0,0 +1,2 @@ +x-Mj0)޾Dz Bw'X`IAir{00.I>BKBvԌB35u|AfihBLi"!Ƶ]L^a4wZxO4ؽFw<.oQ)wITh{zn+{1OȟZh P=MptOF] +LPs$Rr!ڰ&U \ No newline at end of file diff --git a/.git/objects/d4/d4b0351086c411c3a617a10ab9b6a2d22b9cc3 b/.git/objects/d4/d4b0351086c411c3a617a10ab9b6a2d22b9cc3 new file mode 100644 index 0000000..59a9f96 Binary files /dev/null and b/.git/objects/d4/d4b0351086c411c3a617a10ab9b6a2d22b9cc3 differ diff --git a/.git/objects/d4/fac2341542c000baa4df2638efc1d804bad590 b/.git/objects/d4/fac2341542c000baa4df2638efc1d804bad590 new file mode 100644 index 0000000..3e44030 Binary files /dev/null and b/.git/objects/d4/fac2341542c000baa4df2638efc1d804bad590 differ diff --git a/.git/objects/d4/ff420139b4e357c906f0f74a722e83a64d40d4 b/.git/objects/d4/ff420139b4e357c906f0f74a722e83a64d40d4 new file mode 100644 index 0000000..bbcf2fe Binary files /dev/null and b/.git/objects/d4/ff420139b4e357c906f0f74a722e83a64d40d4 differ diff --git a/.git/objects/d5/06efd8b952e222885c29128ca2ac925b30763b b/.git/objects/d5/06efd8b952e222885c29128ca2ac925b30763b new file mode 100644 index 0000000..3954300 Binary files /dev/null and b/.git/objects/d5/06efd8b952e222885c29128ca2ac925b30763b differ diff --git a/.git/objects/d5/0fe6f58e526ae843cdee31391e0a86f5effe3e b/.git/objects/d5/0fe6f58e526ae843cdee31391e0a86f5effe3e new file mode 100644 index 0000000..57a2cac Binary files /dev/null and b/.git/objects/d5/0fe6f58e526ae843cdee31391e0a86f5effe3e differ diff --git a/.git/objects/d5/10b0dabd5f62b5ce60dbff3387137cc852ceb1 b/.git/objects/d5/10b0dabd5f62b5ce60dbff3387137cc852ceb1 new file mode 100644 index 0000000..7675055 Binary files /dev/null and b/.git/objects/d5/10b0dabd5f62b5ce60dbff3387137cc852ceb1 differ diff --git a/.git/objects/d5/850a7a6800b56fd21b42007017835b2a329601 b/.git/objects/d5/850a7a6800b56fd21b42007017835b2a329601 new file mode 100644 index 0000000..c859507 Binary files /dev/null and b/.git/objects/d5/850a7a6800b56fd21b42007017835b2a329601 differ diff --git a/.git/objects/d5/ae22eadc9ee9e7ba283de815a9b0111ba77d96 b/.git/objects/d5/ae22eadc9ee9e7ba283de815a9b0111ba77d96 new file mode 100644 index 0000000..daf7d62 Binary files /dev/null and b/.git/objects/d5/ae22eadc9ee9e7ba283de815a9b0111ba77d96 differ diff --git a/.git/objects/d5/b029fc613cf880c815450e9bfdde326617a3a4 b/.git/objects/d5/b029fc613cf880c815450e9bfdde326617a3a4 new file mode 100644 index 0000000..677e8c4 --- /dev/null +++ b/.git/objects/d5/b029fc613cf880c815450e9bfdde326617a3a4 @@ -0,0 +1,3 @@ +x-=n0SsGAVFfO`g`62Fn>ҍ4>e* y*:`yTxC\ZǥAqB j3NSӡӜ)e5L9ÜiqE/o^Ɣ}o{54cߟq8I +vHh}Zހč #w?c6Ly.~9>֩~ #J ? +7,c\`}X21š[ \ No newline at end of file diff --git a/.git/objects/d5/bcd65a74fe5671205da21eb6baf7b56b98f8d8 b/.git/objects/d5/bcd65a74fe5671205da21eb6baf7b56b98f8d8 new file mode 100644 index 0000000..68b63e5 --- /dev/null +++ b/.git/objects/d5/bcd65a74fe5671205da21eb6baf7b56b98f8d8 @@ -0,0 +1,2 @@ +x%NMN0v)Rc$21ՅQZҖ̽φmsnord9 OfBdf8~0hTmSdaġ;-aT'BTo +GhVy V"?r7gJ>~g*%/HhZ۰=(E#Z,bU;%!l?p<5}Rl n/.Ѱ2H);?ۻ`ZK \ No newline at end of file diff --git a/.git/objects/d5/cf2375dde5435917b901d472f11d4b7682671a b/.git/objects/d5/cf2375dde5435917b901d472f11d4b7682671a new file mode 100644 index 0000000..f7dbcde Binary files /dev/null and b/.git/objects/d5/cf2375dde5435917b901d472f11d4b7682671a differ diff --git a/.git/objects/d6/01419e1f9232c708ef6f8bce459cc4ebe7aba5 b/.git/objects/d6/01419e1f9232c708ef6f8bce459cc4ebe7aba5 new file mode 100644 index 0000000..8db86b7 Binary files /dev/null and b/.git/objects/d6/01419e1f9232c708ef6f8bce459cc4ebe7aba5 differ diff --git a/.git/objects/d6/28eae0eb466b6f0ebe912eae90925209706ef9 b/.git/objects/d6/28eae0eb466b6f0ebe912eae90925209706ef9 new file mode 100644 index 0000000..8ffe595 Binary files /dev/null and b/.git/objects/d6/28eae0eb466b6f0ebe912eae90925209706ef9 differ diff --git a/.git/objects/d6/3e75da53371d49a8f2808315c00c9ed78e8267 b/.git/objects/d6/3e75da53371d49a8f2808315c00c9ed78e8267 new file mode 100644 index 0000000..ebe4688 Binary files /dev/null and b/.git/objects/d6/3e75da53371d49a8f2808315c00c9ed78e8267 differ diff --git a/.git/objects/d6/49d212f926a52624fb1a255c1dddbd9cdf4931 b/.git/objects/d6/49d212f926a52624fb1a255c1dddbd9cdf4931 new file mode 100644 index 0000000..0b45f76 Binary files /dev/null and b/.git/objects/d6/49d212f926a52624fb1a255c1dddbd9cdf4931 differ diff --git a/.git/objects/d6/601b8b6dc791840ccdda2c84dca5abb2492f15 b/.git/objects/d6/601b8b6dc791840ccdda2c84dca5abb2492f15 new file mode 100644 index 0000000..b6497b4 Binary files /dev/null and b/.git/objects/d6/601b8b6dc791840ccdda2c84dca5abb2492f15 differ diff --git a/.git/objects/d6/63ed85b0d0c278a01a2121867aa223814c8deb b/.git/objects/d6/63ed85b0d0c278a01a2121867aa223814c8deb new file mode 100644 index 0000000..68a5c0c Binary files /dev/null and b/.git/objects/d6/63ed85b0d0c278a01a2121867aa223814c8deb differ diff --git a/.git/objects/d6/8552c1fc3fadbf2546df8a46c8f30493d20d3d b/.git/objects/d6/8552c1fc3fadbf2546df8a46c8f30493d20d3d new file mode 100644 index 0000000..9e573ab Binary files /dev/null and b/.git/objects/d6/8552c1fc3fadbf2546df8a46c8f30493d20d3d differ diff --git a/.git/objects/d6/9e0ee0abbe02ed51a189ef40f6f07fa03c0388 b/.git/objects/d6/9e0ee0abbe02ed51a189ef40f6f07fa03c0388 new file mode 100644 index 0000000..e185920 Binary files /dev/null and b/.git/objects/d6/9e0ee0abbe02ed51a189ef40f6f07fa03c0388 differ diff --git a/.git/objects/d6/c916aa461599d8962a0355cee004a3fae73c10 b/.git/objects/d6/c916aa461599d8962a0355cee004a3fae73c10 new file mode 100644 index 0000000..8ef02ea Binary files /dev/null and b/.git/objects/d6/c916aa461599d8962a0355cee004a3fae73c10 differ diff --git a/.git/objects/d6/ef8743e1c4b80f0bce7cea90bb43c6076f7dff b/.git/objects/d6/ef8743e1c4b80f0bce7cea90bb43c6076f7dff new file mode 100644 index 0000000..3050094 Binary files /dev/null and b/.git/objects/d6/ef8743e1c4b80f0bce7cea90bb43c6076f7dff differ diff --git a/.git/objects/d7/32abe34f7c94772b4c41e5fa4c1393b2a835b2 b/.git/objects/d7/32abe34f7c94772b4c41e5fa4c1393b2a835b2 new file mode 100644 index 0000000..07c8f5b Binary files /dev/null and b/.git/objects/d7/32abe34f7c94772b4c41e5fa4c1393b2a835b2 differ diff --git a/.git/objects/d7/59c2cc56d98b7d1d4208be9731d05db46d4430 b/.git/objects/d7/59c2cc56d98b7d1d4208be9731d05db46d4430 new file mode 100644 index 0000000..ab2b0d8 Binary files /dev/null and b/.git/objects/d7/59c2cc56d98b7d1d4208be9731d05db46d4430 differ diff --git a/.git/objects/d7/5ee9362387ce816ea795c53a3aff6a6818cbbf b/.git/objects/d7/5ee9362387ce816ea795c53a3aff6a6818cbbf new file mode 100644 index 0000000..63d3af3 Binary files /dev/null and b/.git/objects/d7/5ee9362387ce816ea795c53a3aff6a6818cbbf differ diff --git a/.git/objects/d7/68d802d973d05982a92e3c8be5e05a95dd01cb b/.git/objects/d7/68d802d973d05982a92e3c8be5e05a95dd01cb new file mode 100644 index 0000000..63b78c6 Binary files /dev/null and b/.git/objects/d7/68d802d973d05982a92e3c8be5e05a95dd01cb differ diff --git a/.git/objects/d7/bcdc23ec12d5a36a0341875020aaa317eb56dd b/.git/objects/d7/bcdc23ec12d5a36a0341875020aaa317eb56dd new file mode 100644 index 0000000..e8c58d1 Binary files /dev/null and b/.git/objects/d7/bcdc23ec12d5a36a0341875020aaa317eb56dd differ diff --git a/.git/objects/d7/cc4f60a20e120305e8e5ebbc6c0ed853c321cc b/.git/objects/d7/cc4f60a20e120305e8e5ebbc6c0ed853c321cc new file mode 100644 index 0000000..260a8be Binary files /dev/null and b/.git/objects/d7/cc4f60a20e120305e8e5ebbc6c0ed853c321cc differ diff --git a/.git/objects/d7/fc82c72fbd3c0aae035a2e84de499b8c58cc37 b/.git/objects/d7/fc82c72fbd3c0aae035a2e84de499b8c58cc37 new file mode 100644 index 0000000..884ac1a --- /dev/null +++ b/.git/objects/d7/fc82c72fbd3c0aae035a2e84de499b8c58cc37 @@ -0,0 +1 @@ +x5MN0YoTcUĺl8ܦjv({.[f4ƥy*j&GbAfaN('G;j=hBpw fW8)Rp`` wCz/2O.R(wT`mR%g2 3Xnk+z;.=FغfZ:o˴!\#ޥH0d e]*a# \ No newline at end of file diff --git a/.git/objects/d7/feabc98565028d3162b7b8af66a1ed93c01ac4 b/.git/objects/d7/feabc98565028d3162b7b8af66a1ed93c01ac4 new file mode 100644 index 0000000..c81abd5 Binary files /dev/null and b/.git/objects/d7/feabc98565028d3162b7b8af66a1ed93c01ac4 differ diff --git a/.git/objects/d8/17ffa77a3bb5b74e15611b1e409b06778c7b6d b/.git/objects/d8/17ffa77a3bb5b74e15611b1e409b06778c7b6d new file mode 100644 index 0000000..48699cf --- /dev/null +++ b/.git/objects/d8/17ffa77a3bb5b74e15611b1e409b06778c7b6d @@ -0,0 +1,2 @@ +xAN0EYQcuBl87Vuތ=PX6s( +He6ңuK7Chpa~}s̱` +qsu¡VF"7t*c2 Gxȑxv +tyz A[l$/s[Fiu]ٛQv(klpR|).Nә$:í o \ No newline at end of file diff --git a/.git/objects/d8/7cc9c8693a2ba1c19fea1ed5cdb85e1b28a70d b/.git/objects/d8/7cc9c8693a2ba1c19fea1ed5cdb85e1b28a70d new file mode 100644 index 0000000..efce95a Binary files /dev/null and b/.git/objects/d8/7cc9c8693a2ba1c19fea1ed5cdb85e1b28a70d differ diff --git a/.git/objects/d8/88f05a33caab41cacb0ed82c81240101733b28 b/.git/objects/d8/88f05a33caab41cacb0ed82c81240101733b28 new file mode 100644 index 0000000..23fa03b Binary files /dev/null and b/.git/objects/d8/88f05a33caab41cacb0ed82c81240101733b28 differ diff --git a/.git/objects/d8/9243297b1513e5cf6f3019b9fe3264b29c9651 b/.git/objects/d8/9243297b1513e5cf6f3019b9fe3264b29c9651 new file mode 100644 index 0000000..1969383 Binary files /dev/null and b/.git/objects/d8/9243297b1513e5cf6f3019b9fe3264b29c9651 differ diff --git a/.git/objects/d8/a7fc4bd8ab73bfbdf6e6b2f98b6b3ba66224a8 b/.git/objects/d8/a7fc4bd8ab73bfbdf6e6b2f98b6b3ba66224a8 new file mode 100644 index 0000000..e88bd9e Binary files /dev/null and b/.git/objects/d8/a7fc4bd8ab73bfbdf6e6b2f98b6b3ba66224a8 differ diff --git a/.git/objects/d8/ad2e292b34ff5fea557fa024acbdf4af59a623 b/.git/objects/d8/ad2e292b34ff5fea557fa024acbdf4af59a623 new file mode 100644 index 0000000..aa2dca5 Binary files /dev/null and b/.git/objects/d8/ad2e292b34ff5fea557fa024acbdf4af59a623 differ diff --git a/.git/objects/d8/b13d8dae3da131149abd597719986aa2f0eee0 b/.git/objects/d8/b13d8dae3da131149abd597719986aa2f0eee0 new file mode 100644 index 0000000..b1be2b0 Binary files /dev/null and b/.git/objects/d8/b13d8dae3da131149abd597719986aa2f0eee0 differ diff --git a/.git/objects/d8/c67b4740e636ff0f7c5e9d380c6a481d1c120e b/.git/objects/d8/c67b4740e636ff0f7c5e9d380c6a481d1c120e new file mode 100644 index 0000000..9d62380 Binary files /dev/null and b/.git/objects/d8/c67b4740e636ff0f7c5e9d380c6a481d1c120e differ diff --git a/.git/objects/d9/0ce3d8ef159a3e119d77e769b6f1a0c37faa6c b/.git/objects/d9/0ce3d8ef159a3e119d77e769b6f1a0c37faa6c new file mode 100644 index 0000000..e688533 --- /dev/null +++ b/.git/objects/d9/0ce3d8ef159a3e119d77e769b6f1a0c37faa6c @@ -0,0 +1,2 @@ +x-AN0 EY#FI A!qqڠ6 ܌=#Be?}J +tb+mroYwZX'`^X182o0s,`:ORmkaơkY$9ex^ ҂#|;nOe湞$S 4TE+DCޥys.p~ Tśd?#N-a3P\ն= ji%ILhB \ No newline at end of file diff --git a/.git/objects/d9/100bd15306646df80baff3726230d07c811267 b/.git/objects/d9/100bd15306646df80baff3726230d07c811267 new file mode 100644 index 0000000..f697d28 Binary files /dev/null and b/.git/objects/d9/100bd15306646df80baff3726230d07c811267 differ diff --git a/.git/objects/d9/28b84318ceb1f9decfb51587b3f9bb0d02d090 b/.git/objects/d9/28b84318ceb1f9decfb51587b3f9bb0d02d090 new file mode 100644 index 0000000..5145039 Binary files /dev/null and b/.git/objects/d9/28b84318ceb1f9decfb51587b3f9bb0d02d090 differ diff --git a/.git/objects/d9/5dcc18a45cfcbaa20c6ab361f03e30d690aafd b/.git/objects/d9/5dcc18a45cfcbaa20c6ab361f03e30d690aafd new file mode 100644 index 0000000..612889f Binary files /dev/null and b/.git/objects/d9/5dcc18a45cfcbaa20c6ab361f03e30d690aafd differ diff --git a/.git/objects/d9/8e38e3059bab7c8d5eee20a7bf1248892e71ba b/.git/objects/d9/8e38e3059bab7c8d5eee20a7bf1248892e71ba new file mode 100644 index 0000000..9a6d460 --- /dev/null +++ b/.git/objects/d9/8e38e3059bab7c8d5eee20a7bf1248892e71ba @@ -0,0 +1 @@ +x%N D]+Bb^3u.-I {L̜ش,a>-WRVfDpB֝͊b;Ƶ".^:Z=zȴ4= ۔2{lTi+K.'Lppg9y%?\f<0Қ#{ T!RCrB1$ FjL?#ԆmVHmwBup \ No newline at end of file diff --git a/.git/objects/d9/ee99907ece71c5477992dc0b4304b6f52f3ca5 b/.git/objects/d9/ee99907ece71c5477992dc0b4304b6f52f3ca5 new file mode 100644 index 0000000..3c5e33d Binary files /dev/null and b/.git/objects/d9/ee99907ece71c5477992dc0b4304b6f52f3ca5 differ diff --git a/.git/objects/da/0ab3abe8bca731579a75d1ca8a37264d3896c9 b/.git/objects/da/0ab3abe8bca731579a75d1ca8a37264d3896c9 new file mode 100644 index 0000000..76d59a1 Binary files /dev/null and b/.git/objects/da/0ab3abe8bca731579a75d1ca8a37264d3896c9 differ diff --git a/.git/objects/da/2bab30633ec76f9ccef1ee2050f69488a51539 b/.git/objects/da/2bab30633ec76f9ccef1ee2050f69488a51539 new file mode 100644 index 0000000..45b6b1f Binary files /dev/null and b/.git/objects/da/2bab30633ec76f9ccef1ee2050f69488a51539 differ diff --git a/.git/objects/da/3c08d4d870d3e630c2501c9e2564766a7a78c6 b/.git/objects/da/3c08d4d870d3e630c2501c9e2564766a7a78c6 new file mode 100644 index 0000000..278b295 Binary files /dev/null and b/.git/objects/da/3c08d4d870d3e630c2501c9e2564766a7a78c6 differ diff --git a/.git/objects/da/471d1ad8f79d52f113c323650db29d6501a7e5 b/.git/objects/da/471d1ad8f79d52f113c323650db29d6501a7e5 new file mode 100644 index 0000000..2478ccf Binary files /dev/null and b/.git/objects/da/471d1ad8f79d52f113c323650db29d6501a7e5 differ diff --git a/.git/objects/da/4b3f638db157c5fc3de077c4e4ed5d60d43819 b/.git/objects/da/4b3f638db157c5fc3de077c4e4ed5d60d43819 new file mode 100644 index 0000000..3955e1d Binary files /dev/null and b/.git/objects/da/4b3f638db157c5fc3de077c4e4ed5d60d43819 differ diff --git a/.git/objects/da/56f474298bca9d802289d4fa7c9fc190f54673 b/.git/objects/da/56f474298bca9d802289d4fa7c9fc190f54673 new file mode 100644 index 0000000..eea367c Binary files /dev/null and b/.git/objects/da/56f474298bca9d802289d4fa7c9fc190f54673 differ diff --git a/.git/objects/da/957e46a29ed3512972f0f9ebd2b8267c0d776c b/.git/objects/da/957e46a29ed3512972f0f9ebd2b8267c0d776c new file mode 100644 index 0000000..b583308 Binary files /dev/null and b/.git/objects/da/957e46a29ed3512972f0f9ebd2b8267c0d776c differ diff --git a/.git/objects/da/97299eeb09464411ab72d3024ad983912eaced b/.git/objects/da/97299eeb09464411ab72d3024ad983912eaced new file mode 100644 index 0000000..070cc8e Binary files /dev/null and b/.git/objects/da/97299eeb09464411ab72d3024ad983912eaced differ diff --git a/.git/objects/da/a6c06c9a4bb52c8436a6f17c57c378e3868c88 b/.git/objects/da/a6c06c9a4bb52c8436a6f17c57c378e3868c88 new file mode 100644 index 0000000..b68b020 Binary files /dev/null and b/.git/objects/da/a6c06c9a4bb52c8436a6f17c57c378e3868c88 differ diff --git a/.git/objects/da/ab5be0d328e0b5571bc41bf2a10b7e2b896021 b/.git/objects/da/ab5be0d328e0b5571bc41bf2a10b7e2b896021 new file mode 100644 index 0000000..57f87f8 Binary files /dev/null and b/.git/objects/da/ab5be0d328e0b5571bc41bf2a10b7e2b896021 differ diff --git a/.git/objects/da/b0bd801edc0940a686e3c8fd70866c18a986b5 b/.git/objects/da/b0bd801edc0940a686e3c8fd70866c18a986b5 new file mode 100644 index 0000000..8593665 Binary files /dev/null and b/.git/objects/da/b0bd801edc0940a686e3c8fd70866c18a986b5 differ diff --git a/.git/objects/db/237ddc11907fc494dcb08db8a06fbadd9a891d b/.git/objects/db/237ddc11907fc494dcb08db8a06fbadd9a891d new file mode 100644 index 0000000..e3c019f Binary files /dev/null and b/.git/objects/db/237ddc11907fc494dcb08db8a06fbadd9a891d differ diff --git a/.git/objects/db/28d33b0ddf73b761f9fc1e3f44bf6a8e310318 b/.git/objects/db/28d33b0ddf73b761f9fc1e3f44bf6a8e310318 new file mode 100644 index 0000000..c54a7eb Binary files /dev/null and b/.git/objects/db/28d33b0ddf73b761f9fc1e3f44bf6a8e310318 differ diff --git a/.git/objects/db/2a234cc5cf45056bb040a0e0192592abb4672e b/.git/objects/db/2a234cc5cf45056bb040a0e0192592abb4672e new file mode 100644 index 0000000..72359d2 Binary files /dev/null and b/.git/objects/db/2a234cc5cf45056bb040a0e0192592abb4672e differ diff --git a/.git/objects/db/3dd012cdd7fe468372d50c85a191c81bfec94b b/.git/objects/db/3dd012cdd7fe468372d50c85a191c81bfec94b new file mode 100644 index 0000000..e683fe0 Binary files /dev/null and b/.git/objects/db/3dd012cdd7fe468372d50c85a191c81bfec94b differ diff --git a/.git/objects/db/44abb41960da68951e1660adaff3ff78b18487 b/.git/objects/db/44abb41960da68951e1660adaff3ff78b18487 new file mode 100644 index 0000000..23cadb7 Binary files /dev/null and b/.git/objects/db/44abb41960da68951e1660adaff3ff78b18487 differ diff --git a/.git/objects/db/6d9b5723c4c0e3bd4adaab1cc9a0c7086dfb8c b/.git/objects/db/6d9b5723c4c0e3bd4adaab1cc9a0c7086dfb8c new file mode 100644 index 0000000..fd0ea37 --- /dev/null +++ b/.git/objects/db/6d9b5723c4c0e3bd4adaab1cc9a0c7086dfb8c @@ -0,0 +1 @@ +xP;N0)^A-%PpƛF^#ׄk#VYk8Dzj#R*ъYlijp`>yog[J .GTzYCqEߟq{'-XDR|܆?Yi)NWTv7Įw첻kZMr* Df \ No newline at end of file diff --git a/.git/objects/db/7d45c7479d10532fab6976a5d45df725e6b99c b/.git/objects/db/7d45c7479d10532fab6976a5d45df725e6b99c new file mode 100644 index 0000000..94df759 Binary files /dev/null and b/.git/objects/db/7d45c7479d10532fab6976a5d45df725e6b99c differ diff --git a/.git/objects/db/87518ddcc1d8ea458421bfb7672e5a32af06c4 b/.git/objects/db/87518ddcc1d8ea458421bfb7672e5a32af06c4 new file mode 100644 index 0000000..5507ace Binary files /dev/null and b/.git/objects/db/87518ddcc1d8ea458421bfb7672e5a32af06c4 differ diff --git a/.git/objects/db/8e475ecd6307d82c6ca6a95d2f2db1bd2448d5 b/.git/objects/db/8e475ecd6307d82c6ca6a95d2f2db1bd2448d5 new file mode 100644 index 0000000..a1220c4 Binary files /dev/null and b/.git/objects/db/8e475ecd6307d82c6ca6a95d2f2db1bd2448d5 differ diff --git a/.git/objects/db/9221cced6d28aec9df64111696839650683629 b/.git/objects/db/9221cced6d28aec9df64111696839650683629 new file mode 100644 index 0000000..5aea053 Binary files /dev/null and b/.git/objects/db/9221cced6d28aec9df64111696839650683629 differ diff --git a/.git/objects/db/a90a092432b392eb3c98d59481821ba40018bb b/.git/objects/db/a90a092432b392eb3c98d59481821ba40018bb new file mode 100644 index 0000000..a813241 --- /dev/null +++ b/.git/objects/db/a90a092432b392eb3c98d59481821ba40018bb @@ -0,0 +1,2 @@ +x-Kj0E;*޼4c2q; +g[`KBfgwcUBgظKD0J'ZӎLh47vZe׬j]0S({LK(RŸrm'vqE{c18m\QOkz.3͵Gbl\Oy/%Bxe>K3 g\pK@n+YI፵u\b.2]=|Jy1mH><>xf]b \ No newline at end of file diff --git a/.git/objects/db/d6c0bbbe0d07ccd646f747c6808a25cd52ea30 b/.git/objects/db/d6c0bbbe0d07ccd646f747c6808a25cd52ea30 new file mode 100644 index 0000000..7be2346 Binary files /dev/null and b/.git/objects/db/d6c0bbbe0d07ccd646f747c6808a25cd52ea30 differ diff --git a/.git/objects/db/f7280c4dafff6d773413fdd04e0caf2bbeaca1 b/.git/objects/db/f7280c4dafff6d773413fdd04e0caf2bbeaca1 new file mode 100644 index 0000000..6a712d0 Binary files /dev/null and b/.git/objects/db/f7280c4dafff6d773413fdd04e0caf2bbeaca1 differ diff --git a/.git/objects/dc/2e1f73501b5b241a452fd485ee72cb9a9a8bf1 b/.git/objects/dc/2e1f73501b5b241a452fd485ee72cb9a9a8bf1 new file mode 100644 index 0000000..bf4ffac Binary files /dev/null and b/.git/objects/dc/2e1f73501b5b241a452fd485ee72cb9a9a8bf1 differ diff --git a/.git/objects/dc/41329f6c1cb6941a158bdcde35acae0ade4f2a b/.git/objects/dc/41329f6c1cb6941a158bdcde35acae0ade4f2a new file mode 100644 index 0000000..4a82dc5 Binary files /dev/null and b/.git/objects/dc/41329f6c1cb6941a158bdcde35acae0ade4f2a differ diff --git a/.git/objects/dc/51bd474f11675febf045f5c1fe4191ec5a336c b/.git/objects/dc/51bd474f11675febf045f5c1fe4191ec5a336c new file mode 100644 index 0000000..c40f6f9 Binary files /dev/null and b/.git/objects/dc/51bd474f11675febf045f5c1fe4191ec5a336c differ diff --git a/.git/objects/dc/551fcb6cc4835cdb2917e3e0d7e9d1e50716ef b/.git/objects/dc/551fcb6cc4835cdb2917e3e0d7e9d1e50716ef new file mode 100644 index 0000000..91c5e9a Binary files /dev/null and b/.git/objects/dc/551fcb6cc4835cdb2917e3e0d7e9d1e50716ef differ diff --git a/.git/objects/dc/5d7de3109a719e955104ad566950ecae6a77e8 b/.git/objects/dc/5d7de3109a719e955104ad566950ecae6a77e8 new file mode 100644 index 0000000..6b2e90a Binary files /dev/null and b/.git/objects/dc/5d7de3109a719e955104ad566950ecae6a77e8 differ diff --git a/.git/objects/dc/748cf93d5c62270affd547f724a56eba66061c b/.git/objects/dc/748cf93d5c62270affd547f724a56eba66061c new file mode 100644 index 0000000..d08ec7d Binary files /dev/null and b/.git/objects/dc/748cf93d5c62270affd547f724a56eba66061c differ diff --git a/.git/objects/dc/75f29eadae8a24ec8fe4cd2e4930119ce274bf b/.git/objects/dc/75f29eadae8a24ec8fe4cd2e4930119ce274bf new file mode 100644 index 0000000..3b94048 Binary files /dev/null and b/.git/objects/dc/75f29eadae8a24ec8fe4cd2e4930119ce274bf differ diff --git a/.git/objects/dc/8e11d682159b6890d87884fbca737ffcaf7ef7 b/.git/objects/dc/8e11d682159b6890d87884fbca737ffcaf7ef7 new file mode 100644 index 0000000..d010fe7 --- /dev/null +++ b/.git/objects/dc/8e11d682159b6890d87884fbca737ffcaf7ef7 @@ -0,0 +1,3 @@ +xUkPgw A˨Dkj  @1".Bw7DrB#ZE(tuR;^FQi Azmnd{@e><[*pL{C6pX}7~J)H*EHx0pA{+fAdXC5;ozf{;(]-<23ڻ *q6v|6 |(z~YzJwi'E_/&CTMR̈́(H;Vmlov.#jv<~`\juܜ((J6Hp/Z-,?V>6^=d)iXeT(,J%X.^S[QG{XϐJBDɘf0M?'k'@X" vrwwLӄļH&HT hEC!X7Psʿe˽c}Y NJ-岸m\${j睜/#eMG%\rkgv<Ѯmf0:PfYLfMu'/9ݾ&eMq !(h.{ڋ{~rC1 Q`\˫۴?*@\H+5|dA*othZ?ZE(T@h~;6%>@.U.8fݾS#`RFm^[@CͯwNǟA#(#,/<&8x}ãŽH 暠Bjb:{>GO6zqI*"Df~NEx:;goۣ)VMs* 'SN)tagŁDv}.M=MO Q%ZV!uѮէִҀC)BH +t6ˢ_V۟߉3gD[uٞ>˪u*"?/HǕB6Y<ۡʃ3VNA-kH`/*) ()S#@ \ No newline at end of file diff --git a/.git/objects/dd/0d899d92b6fad2f7078e8c196dc407dd527a9c b/.git/objects/dd/0d899d92b6fad2f7078e8c196dc407dd527a9c new file mode 100644 index 0000000..ffaf51d --- /dev/null +++ b/.git/objects/dd/0d899d92b6fad2f7078e8c196dc407dd527a9c @@ -0,0 +1,4 @@ +x}R]O0um@H74$AdV_-&Ks[WpxjUPmda +p  .}’s$( Nhv=U^[ƀ޴e +-EUZ?a~Kzq~2J`%1wc"-QD5IJ +O<'("ۑH^a5 J9cL@ҘU'ŐKMޅO(\I6hCNk4R2z0i+&pߣ6>/n?r}}6tUY8Z 4-ټQS T#ڔTJ Q \ No newline at end of file diff --git a/.git/objects/dd/3959704202f38601f133a1ff12f8a590774d04 b/.git/objects/dd/3959704202f38601f133a1ff12f8a590774d04 new file mode 100644 index 0000000..a7666e1 Binary files /dev/null and b/.git/objects/dd/3959704202f38601f133a1ff12f8a590774d04 differ diff --git a/.git/objects/dd/5d16fd2fa6421b2ce27b37ae2d4768b91fb7b0 b/.git/objects/dd/5d16fd2fa6421b2ce27b37ae2d4768b91fb7b0 new file mode 100644 index 0000000..bddcb4a --- /dev/null +++ b/.git/objects/dd/5d16fd2fa6421b2ce27b37ae2d4768b91fb7b0 @@ -0,0 +1,7 @@ +x]iPgǷ*cjB*TBpH ,q7K=݀耊BDx`ءX*NA* ٍL{x#|B?/P +ݗVF}sa]ѡ( BB@ҔS=ɯW*D%F0DK#dJIT#LksO=n;Tu!QP+^Gya|qcZU*CAu~IO^K;ܙ0!;Q\*! dP'-~SG 6r6DKKN +%; +\,̝[%t8# 5$_sQ#*9[eJ3aK11IXZ,ԾyYW;]wؓPn$V\/ +2^d}3c]*_Nn!0 =-[ʡ4dYj8!p[vHջ0'^i3KL1\ëE lF@ +b W*ӲNm'Bhs붩դ',j9[RQ:f|25 /p[lI+UNSw Y@Ah86+e\JЊ'tjzwF!弃'Se8b\ɶXRC͉S9ߜwu MS农gI? \ No newline at end of file diff --git a/.git/objects/dd/6edfd59f723342b0f3cab3aabf405e3ca7b317 b/.git/objects/dd/6edfd59f723342b0f3cab3aabf405e3ca7b317 new file mode 100644 index 0000000..c2dc604 Binary files /dev/null and b/.git/objects/dd/6edfd59f723342b0f3cab3aabf405e3ca7b317 differ diff --git a/.git/objects/dd/6f0109bf6dab7bd543db957ff5227ab07790d6 b/.git/objects/dd/6f0109bf6dab7bd543db957ff5227ab07790d6 new file mode 100644 index 0000000..6093517 --- /dev/null +++ b/.git/objects/dd/6f0109bf6dab7bd543db957ff5227ab07790d6 @@ -0,0 +1 @@ +x5MJ1])j/IφAFwIe:It37s zl1T4:-͢faѺYZ1^jNl8cTEsgLh9!I3G> '܃5xQ`ם|D;Ǻ-)hs|>1Τ4m'6m]組^s9apĭFr?Ꭹ^>5-ֿaĐj* &[P \ No newline at end of file diff --git a/.git/objects/dd/72e6f86aeb2f749a56b58326c0329e176c28b1 b/.git/objects/dd/72e6f86aeb2f749a56b58326c0329e176c28b1 new file mode 100644 index 0000000..defdb63 Binary files /dev/null and b/.git/objects/dd/72e6f86aeb2f749a56b58326c0329e176c28b1 differ diff --git a/.git/objects/de/1ebc7ebf44cdce06abd32a276c9a0b142e7e25 b/.git/objects/de/1ebc7ebf44cdce06abd32a276c9a0b142e7e25 new file mode 100644 index 0000000..f64b05a Binary files /dev/null and b/.git/objects/de/1ebc7ebf44cdce06abd32a276c9a0b142e7e25 differ diff --git a/.git/objects/de/3483eee5460eee21eeab61731ea05b49281a4a b/.git/objects/de/3483eee5460eee21eeab61731ea05b49281a4a new file mode 100644 index 0000000..3d2de9b Binary files /dev/null and b/.git/objects/de/3483eee5460eee21eeab61731ea05b49281a4a differ diff --git a/.git/objects/de/4fd146b8df3f545a40ae89f8fd24d4b3131791 b/.git/objects/de/4fd146b8df3f545a40ae89f8fd24d4b3131791 new file mode 100644 index 0000000..600136b Binary files /dev/null and b/.git/objects/de/4fd146b8df3f545a40ae89f8fd24d4b3131791 differ diff --git a/.git/objects/de/63c3c35c6892df07bb60625a0bdd713114d089 b/.git/objects/de/63c3c35c6892df07bb60625a0bdd713114d089 new file mode 100644 index 0000000..cc14847 Binary files /dev/null and b/.git/objects/de/63c3c35c6892df07bb60625a0bdd713114d089 differ diff --git a/.git/objects/de/a39ed2d81019a1a9c543557d5c2f47255a4523 b/.git/objects/de/a39ed2d81019a1a9c543557d5c2f47255a4523 new file mode 100644 index 0000000..05f2da8 Binary files /dev/null and b/.git/objects/de/a39ed2d81019a1a9c543557d5c2f47255a4523 differ diff --git a/.git/objects/de/f14310d549130db4f0e557c08563264d2f1a2a b/.git/objects/de/f14310d549130db4f0e557c08563264d2f1a2a new file mode 100644 index 0000000..070ad81 --- /dev/null +++ b/.git/objects/de/f14310d549130db4f0e557c08563264d2f1a2a @@ -0,0 +1,4 @@ +x1N0E})l'-V(c{ؖcV7bXLX+~N"ڦJ["&H -JlEou/\ moGGB)^C:YcF*ꚙLa3]L񶒇i' +F<J%p!PqL4Gp +  f>.r9Hkk>"1\e \ No newline at end of file diff --git a/.git/objects/e0/7acae8d9bbf4506058be3e67cbab90eda95ec2 b/.git/objects/e0/7acae8d9bbf4506058be3e67cbab90eda95ec2 new file mode 100644 index 0000000..f0a56d5 --- /dev/null +++ b/.git/objects/e0/7acae8d9bbf4506058be3e67cbab90eda95ec2 @@ -0,0 +1 @@ +xMJ1]oH%]ӕdDqދ<*m)dtsU2@`&mo3; CZI2bh{0V0Ʈ `9ezX!qBŧU.gD:|32c֧mO ap;kZݥz˨b*;hM)[Jf7 \ No newline at end of file diff --git a/.git/objects/e0/7e0f5f11e445c69ca2374d970f87e6d935e58a b/.git/objects/e0/7e0f5f11e445c69ca2374d970f87e6d935e58a new file mode 100644 index 0000000..1cfbce7 Binary files /dev/null and b/.git/objects/e0/7e0f5f11e445c69ca2374d970f87e6d935e58a differ diff --git a/.git/objects/e0/8f75643dc3919e366524693d14fb6d6e27a04b b/.git/objects/e0/8f75643dc3919e366524693d14fb6d6e27a04b new file mode 100644 index 0000000..1600475 Binary files /dev/null and b/.git/objects/e0/8f75643dc3919e366524693d14fb6d6e27a04b differ diff --git a/.git/objects/e0/b65688e65e50fd4347ea1845a6ee0caa26c035 b/.git/objects/e0/b65688e65e50fd4347ea1845a6ee0caa26c035 new file mode 100644 index 0000000..ec5f4a5 Binary files /dev/null and b/.git/objects/e0/b65688e65e50fd4347ea1845a6ee0caa26c035 differ diff --git a/.git/objects/e0/dca48851e1fb2d8ac3eeac35e53825d1d24fcf b/.git/objects/e0/dca48851e1fb2d8ac3eeac35e53825d1d24fcf new file mode 100644 index 0000000..dd0bc08 Binary files /dev/null and b/.git/objects/e0/dca48851e1fb2d8ac3eeac35e53825d1d24fcf differ diff --git a/.git/objects/e0/e19c26a7a6438debe8c3fd556166b0f55b22ea b/.git/objects/e0/e19c26a7a6438debe8c3fd556166b0f55b22ea new file mode 100644 index 0000000..7c2bdf8 --- /dev/null +++ b/.git/objects/e0/e19c26a7a6438debe8c3fd556166b0f55b22ea @@ -0,0 +1 @@ +xKj0Ь}@L˶~B>=R{l%%c}m0xԄfYaVk=g̃פicWH8dA`0Dz8m(K፶cs<^A)ʌ<؅ݥ5ZɁk] d*G8[B-,pƿ9~ɒ` \ No newline at end of file diff --git a/.git/objects/e1/0e5dbf7364bb4802b190621a627b2420771602 b/.git/objects/e1/0e5dbf7364bb4802b190621a627b2420771602 new file mode 100644 index 0000000..15040c8 Binary files /dev/null and b/.git/objects/e1/0e5dbf7364bb4802b190621a627b2420771602 differ diff --git a/.git/objects/e1/12e7b176bd473f7f6cab7ad5b5a68109f3f807 b/.git/objects/e1/12e7b176bd473f7f6cab7ad5b5a68109f3f807 new file mode 100644 index 0000000..8647519 Binary files /dev/null and b/.git/objects/e1/12e7b176bd473f7f6cab7ad5b5a68109f3f807 differ diff --git a/.git/objects/e1/330c8389aa4908200ce1cff23d8b927394d2fe b/.git/objects/e1/330c8389aa4908200ce1cff23d8b927394d2fe new file mode 100644 index 0000000..28446aa Binary files /dev/null and b/.git/objects/e1/330c8389aa4908200ce1cff23d8b927394d2fe differ diff --git a/.git/objects/e1/49eda46759c494d6c9b43b6043038e8379086a b/.git/objects/e1/49eda46759c494d6c9b43b6043038e8379086a new file mode 100644 index 0000000..c6f2b6f Binary files /dev/null and b/.git/objects/e1/49eda46759c494d6c9b43b6043038e8379086a differ diff --git a/.git/objects/e1/6aa532da892e656e69c4fb956222d04c02ed2f b/.git/objects/e1/6aa532da892e656e69c4fb956222d04c02ed2f new file mode 100644 index 0000000..2ab3a74 Binary files /dev/null and b/.git/objects/e1/6aa532da892e656e69c4fb956222d04c02ed2f differ diff --git a/.git/objects/e1/88ddcfb078b02a48994d79ee42e20e6e92384b b/.git/objects/e1/88ddcfb078b02a48994d79ee42e20e6e92384b new file mode 100644 index 0000000..da8eaeb Binary files /dev/null and b/.git/objects/e1/88ddcfb078b02a48994d79ee42e20e6e92384b differ diff --git a/.git/objects/e1/8e751706bee33a7dbb8efe0d59fd3af745b374 b/.git/objects/e1/8e751706bee33a7dbb8efe0d59fd3af745b374 new file mode 100644 index 0000000..3bc5f23 Binary files /dev/null and b/.git/objects/e1/8e751706bee33a7dbb8efe0d59fd3af745b374 differ diff --git a/.git/objects/e1/d4f8ea5a639dc51038366a48508c3551576ee4 b/.git/objects/e1/d4f8ea5a639dc51038366a48508c3551576ee4 new file mode 100644 index 0000000..1be185a Binary files /dev/null and b/.git/objects/e1/d4f8ea5a639dc51038366a48508c3551576ee4 differ diff --git a/.git/objects/e2/01c9a8928e273065c25c6d87261402e7fc7119 b/.git/objects/e2/01c9a8928e273065c25c6d87261402e7fc7119 new file mode 100644 index 0000000..50d0904 Binary files /dev/null and b/.git/objects/e2/01c9a8928e273065c25c6d87261402e7fc7119 differ diff --git a/.git/objects/e2/5774d8f1e186822aa671a404d2084044c111ab b/.git/objects/e2/5774d8f1e186822aa671a404d2084044c111ab new file mode 100644 index 0000000..5f0d6d0 --- /dev/null +++ b/.git/objects/e2/5774d8f1e186822aa671a404d2084044c111ab @@ -0,0 +1 @@ +xn0{Sl#$BTUDPzK^-/d`<~ה—ț.++ȳ+Vv P+;/0axBa&kJJ 7޹yYDVT<@%oM\xic8 睌$!ST<~)5}1V) k 㚐Oj^2WFOV{bA 0@Kҩ5JYa׸"zd,%Ч801qLq$*yJGwӁ+kȅً$ \ No newline at end of file diff --git a/.git/objects/e2/96b1dce0a769d80608dfb36e264d2a209e28d4 b/.git/objects/e2/96b1dce0a769d80608dfb36e264d2a209e28d4 new file mode 100644 index 0000000..e357b28 Binary files /dev/null and b/.git/objects/e2/96b1dce0a769d80608dfb36e264d2a209e28d4 differ diff --git a/.git/objects/e2/bba1206296e05e9a6a1b84fda76a4b0280c438 b/.git/objects/e2/bba1206296e05e9a6a1b84fda76a4b0280c438 new file mode 100644 index 0000000..da451ca Binary files /dev/null and b/.git/objects/e2/bba1206296e05e9a6a1b84fda76a4b0280c438 differ diff --git a/.git/objects/e2/bdfdc0de6b76da307eb264dd9e2c1190a5a35c b/.git/objects/e2/bdfdc0de6b76da307eb264dd9e2c1190a5a35c new file mode 100644 index 0000000..e58f28a Binary files /dev/null and b/.git/objects/e2/bdfdc0de6b76da307eb264dd9e2c1190a5a35c differ diff --git a/.git/objects/e2/d398998e660d7a98385284bd97cb566b878353 b/.git/objects/e2/d398998e660d7a98385284bd97cb566b878353 new file mode 100644 index 0000000..ed1220e Binary files /dev/null and b/.git/objects/e2/d398998e660d7a98385284bd97cb566b878353 differ diff --git a/.git/objects/e2/ed7ac9125390ef4671b22ea88282d3b4943f05 b/.git/objects/e2/ed7ac9125390ef4671b22ea88282d3b4943f05 new file mode 100644 index 0000000..a2e85d0 Binary files /dev/null and b/.git/objects/e2/ed7ac9125390ef4671b22ea88282d3b4943f05 differ diff --git a/.git/objects/e3/45020b31157cb7457680bf632ef633aa4dd2fb b/.git/objects/e3/45020b31157cb7457680bf632ef633aa4dd2fb new file mode 100644 index 0000000..430264b Binary files /dev/null and b/.git/objects/e3/45020b31157cb7457680bf632ef633aa4dd2fb differ diff --git a/.git/objects/e3/76e0769ce3b99b690a2d7faf29d36ef5d9ca1a b/.git/objects/e3/76e0769ce3b99b690a2d7faf29d36ef5d9ca1a new file mode 100644 index 0000000..ddaafa1 Binary files /dev/null and b/.git/objects/e3/76e0769ce3b99b690a2d7faf29d36ef5d9ca1a differ diff --git a/.git/objects/e3/8632c2a61c30c4a380164b0dbf5714dde7d821 b/.git/objects/e3/8632c2a61c30c4a380164b0dbf5714dde7d821 new file mode 100644 index 0000000..8771871 Binary files /dev/null and b/.git/objects/e3/8632c2a61c30c4a380164b0dbf5714dde7d821 differ diff --git a/.git/objects/e3/a16dd846561c836425c852c7a96adaf52572d9 b/.git/objects/e3/a16dd846561c836425c852c7a96adaf52572d9 new file mode 100644 index 0000000..0df13ee Binary files /dev/null and b/.git/objects/e3/a16dd846561c836425c852c7a96adaf52572d9 differ diff --git a/.git/objects/e3/a3c29c0269006b4da33dba470593a1ddb422f3 b/.git/objects/e3/a3c29c0269006b4da33dba470593a1ddb422f3 new file mode 100644 index 0000000..46b083b Binary files /dev/null and b/.git/objects/e3/a3c29c0269006b4da33dba470593a1ddb422f3 differ diff --git a/.git/objects/e3/a880beca973282814514566a6b1b15e6248346 b/.git/objects/e3/a880beca973282814514566a6b1b15e6248346 new file mode 100644 index 0000000..0a287ca Binary files /dev/null and b/.git/objects/e3/a880beca973282814514566a6b1b15e6248346 differ diff --git a/.git/objects/e3/ca73f7df72080226640d6e1f4c9d35efd5fc28 b/.git/objects/e3/ca73f7df72080226640d6e1f4c9d35efd5fc28 new file mode 100644 index 0000000..7a8b81e --- /dev/null +++ b/.git/objects/e3/ca73f7df72080226640d6e1f4c9d35efd5fc28 @@ -0,0 +1 @@ +xAn0E)fىg<*[qUH1-ܞzq9sZDIػu$ĄV)PtL0K(2W^>9J[z[ vL6zoWB[=-<mr(l^7rn2 :nViw()D?<*ЌF=U \ No newline at end of file diff --git a/.git/objects/e3/ea460e9c5c7637992e3dbf0d94f3f3faabeb9f b/.git/objects/e3/ea460e9c5c7637992e3dbf0d94f3f3faabeb9f new file mode 100644 index 0000000..c1ae5d6 --- /dev/null +++ b/.git/objects/e3/ea460e9c5c7637992e3dbf0d94f3f3faabeb9f @@ -0,0 +1,2 @@ +xn D{+ UU9/430A[֫hI0, +3Ÿml֍*j{Z牜'"$6oY'\H!w3_TX D%}¤QQ :vG/7ФdHCU3 ޟzV \ No newline at end of file diff --git a/.git/objects/e3/eaa6181538f774d3542260183eeba93807348d b/.git/objects/e3/eaa6181538f774d3542260183eeba93807348d new file mode 100644 index 0000000..87f08c3 Binary files /dev/null and b/.git/objects/e3/eaa6181538f774d3542260183eeba93807348d differ diff --git a/.git/objects/e4/0aec5d8404f00601c42ff65a0d5b132b193c91 b/.git/objects/e4/0aec5d8404f00601c42ff65a0d5b132b193c91 new file mode 100644 index 0000000..29ee81b --- /dev/null +++ b/.git/objects/e4/0aec5d8404f00601c42ff65a0d5b132b193c91 @@ -0,0 +1,3 @@ +xIN0DY B<$B '%68}3\ 5*ի +W e%J R{NpjI ݛ)*8iV^ʕ[ fH4%qqZ&1zI + +sgn! +WC\JNuN. ::,lZ}_%ў?o@QR&') t׼6sqn臨#ʑ8۞s*|9/Ro!T3״u?7g \ No newline at end of file diff --git a/.git/objects/e5/60d94936922e637238df920b18847041a7549b b/.git/objects/e5/60d94936922e637238df920b18847041a7549b new file mode 100644 index 0000000..f181078 --- /dev/null +++ b/.git/objects/e5/60d94936922e637238df920b18847041a7549b @@ -0,0 +1 @@ +xN0ۥ@ Ǜ8BD t#.oFϋ7}3q] &'8J?hL 1Ʊ}2YfC?TgJ2t5Ou̮cX#</'R}x">~S k\5◼ B wl⡘iK lr \ No newline at end of file diff --git a/.git/objects/e5/621a2da4f75ee6dc171d5277eeb9933d46932d b/.git/objects/e5/621a2da4f75ee6dc171d5277eeb9933d46932d new file mode 100644 index 0000000..bee9580 Binary files /dev/null and b/.git/objects/e5/621a2da4f75ee6dc171d5277eeb9933d46932d differ diff --git a/.git/objects/e5/7f6a1bdeb50706b930a6ccea943be85298f397 b/.git/objects/e5/7f6a1bdeb50706b930a6ccea943be85298f397 new file mode 100644 index 0000000..c9d2098 Binary files /dev/null and b/.git/objects/e5/7f6a1bdeb50706b930a6ccea943be85298f397 differ diff --git a/.git/objects/e5/a556d539e439a12be5487969f5329e2b78b9d0 b/.git/objects/e5/a556d539e439a12be5487969f5329e2b78b9d0 new file mode 100644 index 0000000..ab2397e Binary files /dev/null and b/.git/objects/e5/a556d539e439a12be5487969f5329e2b78b9d0 differ diff --git a/.git/objects/e5/b75f96e1f4b30af0bb238d76a19f5252a6b0a1 b/.git/objects/e5/b75f96e1f4b30af0bb238d76a19f5252a6b0a1 new file mode 100644 index 0000000..e67fe08 Binary files /dev/null and b/.git/objects/e5/b75f96e1f4b30af0bb238d76a19f5252a6b0a1 differ diff --git a/.git/objects/e5/c2b70e1278b35844f32e2a2a962c64cf40991d b/.git/objects/e5/c2b70e1278b35844f32e2a2a962c64cf40991d new file mode 100644 index 0000000..cd0cf2a Binary files /dev/null and b/.git/objects/e5/c2b70e1278b35844f32e2a2a962c64cf40991d differ diff --git a/.git/objects/e5/d1bc1bf07b3cb5a526440fa2b84d4fee326713 b/.git/objects/e5/d1bc1bf07b3cb5a526440fa2b84d4fee326713 new file mode 100644 index 0000000..e738120 --- /dev/null +++ b/.git/objects/e5/d1bc1bf07b3cb5a526440fa2b84d4fee326713 @@ -0,0 +1 @@ +x5PN0䜯;#cBEͺMIƝí0Ҍvg4Zy̠ˑ%Pg:rs֐Bic]bAke *cpVY~^,Dx ^FZ&$'u^b\eʗAJ+0p/ ݊|c`Gq*s7?r=!v>/*=Z=ޒ&oDS{RaOeP_uѢj-^' \ No newline at end of file diff --git a/.git/objects/e7/578978c66322c0787a93aec9192c2021d7da3b b/.git/objects/e7/578978c66322c0787a93aec9192c2021d7da3b new file mode 100644 index 0000000..c6095d3 Binary files /dev/null and b/.git/objects/e7/578978c66322c0787a93aec9192c2021d7da3b differ diff --git a/.git/objects/e7/5dbd5650fbb61490b968aee3de1a765b8ccadc b/.git/objects/e7/5dbd5650fbb61490b968aee3de1a765b8ccadc new file mode 100644 index 0000000..f6218dd Binary files /dev/null and b/.git/objects/e7/5dbd5650fbb61490b968aee3de1a765b8ccadc differ diff --git a/.git/objects/e7/5dcd09234dea12172c650067741620baa78779 b/.git/objects/e7/5dcd09234dea12172c650067741620baa78779 new file mode 100644 index 0000000..76b9fae Binary files /dev/null and b/.git/objects/e7/5dcd09234dea12172c650067741620baa78779 differ diff --git a/.git/objects/e7/625791a07aec1d993fdf2a17b9b73329b00df2 b/.git/objects/e7/625791a07aec1d993fdf2a17b9b73329b00df2 new file mode 100644 index 0000000..6cb7258 --- /dev/null +++ b/.git/objects/e7/625791a07aec1d993fdf2a17b9b73329b00df2 @@ -0,0 +1,2 @@ +x-OKN0dS=jOĨBE˦'xqĎlGЛbX4cȧjT2)[;ָ9o (ВYI5ʥ\w$V0<a~R g,TKt8pol^Avt33]j|kL38.[?xX?ɖ+) +)Z5 Wʇ|Jòa, \ No newline at end of file diff --git a/.git/objects/e7/b71b52fe802307aa84ea88308db059a2d80fbb b/.git/objects/e7/b71b52fe802307aa84ea88308db059a2d80fbb new file mode 100644 index 0000000..ae0504a Binary files /dev/null and b/.git/objects/e7/b71b52fe802307aa84ea88308db059a2d80fbb differ diff --git a/.git/objects/e7/d2b4714d171e1bab84b32bdbb186b0addb1752 b/.git/objects/e7/d2b4714d171e1bab84b32bdbb186b0addb1752 new file mode 100644 index 0000000..99e5481 Binary files /dev/null and b/.git/objects/e7/d2b4714d171e1bab84b32bdbb186b0addb1752 differ diff --git a/.git/objects/e7/d53aa1c2f19eaaa0f69dfbd933d17c6fac6689 b/.git/objects/e7/d53aa1c2f19eaaa0f69dfbd933d17c6fac6689 new file mode 100644 index 0000000..6517ec0 --- /dev/null +++ b/.git/objects/e7/d53aa1c2f19eaaa0f69dfbd933d17c6fac6689 @@ -0,0 +1,2 @@ +xePKK0_W_x ă(v f35NE 3qA/Nq|Sf%&epK^^oQVH>U`2 +Ys~&pF3 ԛ;$P&R%`Ϙò d(G58%OZXiZϻݚf-Hbnes{#0R)(:p6 7Xxncm^?]E0*dN#[qQݑjSe||kNWyi>ȶj 'y(Y9/A[o/]^ Ѫ \ No newline at end of file diff --git a/.git/objects/e7/df527f87b7b717f8ce7889096910816847873d b/.git/objects/e7/df527f87b7b717f8ce7889096910816847873d new file mode 100644 index 0000000..6940f91 Binary files /dev/null and b/.git/objects/e7/df527f87b7b717f8ce7889096910816847873d differ diff --git a/.git/objects/e7/f4b6982e388f773af599c97a798b2d5712a3fc b/.git/objects/e7/f4b6982e388f773af599c97a798b2d5712a3fc new file mode 100644 index 0000000..bf7f62b Binary files /dev/null and b/.git/objects/e7/f4b6982e388f773af599c97a798b2d5712a3fc differ diff --git a/.git/objects/e8/2ab5466ec8671888ccd68f837b51f258dfd25b b/.git/objects/e8/2ab5466ec8671888ccd68f837b51f258dfd25b new file mode 100644 index 0000000..f76d6c6 Binary files /dev/null and b/.git/objects/e8/2ab5466ec8671888ccd68f837b51f258dfd25b differ diff --git a/.git/objects/e8/2dc74162c2bb6d15a4dd24c64d576f519e5ec2 b/.git/objects/e8/2dc74162c2bb6d15a4dd24c64d576f519e5ec2 new file mode 100644 index 0000000..6bf7c00 --- /dev/null +++ b/.git/objects/e8/2dc74162c2bb6d15a4dd24c64d576f519e5ec2 @@ -0,0 +1 @@ +xAj!Eu4mdCe0j6InaVYg\sN,Dg7lwċp1WgˢjR8Fsoa] t$yf%=+:^-uJ^8?<}ix1=zxֳ֊'s>ҷtCZNZ@ZC*xD?0vA&Iީ\O)_ \ No newline at end of file diff --git a/.git/objects/e8/31240221751da3450ae6a4aee330f1710fe373 b/.git/objects/e8/31240221751da3450ae6a4aee330f1710fe373 new file mode 100644 index 0000000..65a8307 Binary files /dev/null and b/.git/objects/e8/31240221751da3450ae6a4aee330f1710fe373 differ diff --git a/.git/objects/e8/38f14f71f835468f07d4482cb0fc2f78c41821 b/.git/objects/e8/38f14f71f835468f07d4482cb0fc2f78c41821 new file mode 100644 index 0000000..529f7b2 Binary files /dev/null and b/.git/objects/e8/38f14f71f835468f07d4482cb0fc2f78c41821 differ diff --git a/.git/objects/e8/56270af7ce5acd70eb293327c00ce60321eb00 b/.git/objects/e8/56270af7ce5acd70eb293327c00ce60321eb00 new file mode 100644 index 0000000..cad2cbd Binary files /dev/null and b/.git/objects/e8/56270af7ce5acd70eb293327c00ce60321eb00 differ diff --git a/.git/objects/e8/5966a935732d666b800ec1c1606d33011a1f9b b/.git/objects/e8/5966a935732d666b800ec1c1606d33011a1f9b new file mode 100644 index 0000000..22c8b3e Binary files /dev/null and b/.git/objects/e8/5966a935732d666b800ec1c1606d33011a1f9b differ diff --git a/.git/objects/e8/6ccd1390852e1de7da9163f8e286e3fa4d5b52 b/.git/objects/e8/6ccd1390852e1de7da9163f8e286e3fa4d5b52 new file mode 100644 index 0000000..756a86e --- /dev/null +++ b/.git/objects/e8/6ccd1390852e1de7da9163f8e286e3fa4d5b52 @@ -0,0 +1,2 @@ +x5MN0YGD:TUEH` {XJj{3\ ny-x(TIILĜֶ)JGbzdNhI +T^{R.pLj9Բ +Lt=شN>rN7sަ7`<"G.[ʳpp6k%|B^ ~[gH>+Ur5ɸ׽sY \ No newline at end of file diff --git a/.git/objects/e8/6da76162444abddde72adcab3165ab14503f08 b/.git/objects/e8/6da76162444abddde72adcab3165ab14503f08 new file mode 100644 index 0000000..28b40fa Binary files /dev/null and b/.git/objects/e8/6da76162444abddde72adcab3165ab14503f08 differ diff --git a/.git/objects/e8/734ba715606d8f602e5b70eeefda2a2ab1f17e b/.git/objects/e8/734ba715606d8f602e5b70eeefda2a2ab1f17e new file mode 100644 index 0000000..93033f3 Binary files /dev/null and b/.git/objects/e8/734ba715606d8f602e5b70eeefda2a2ab1f17e differ diff --git a/.git/objects/e8/77fcbb07399f829d5a072e1b5d647868d02df2 b/.git/objects/e8/77fcbb07399f829d5a072e1b5d647868d02df2 new file mode 100644 index 0000000..c90bc80 Binary files /dev/null and b/.git/objects/e8/77fcbb07399f829d5a072e1b5d647868d02df2 differ diff --git a/.git/objects/e8/78ae624f3d58b8c1c6523fdcc3f204168e768a b/.git/objects/e8/78ae624f3d58b8c1c6523fdcc3f204168e768a new file mode 100644 index 0000000..29e3b98 Binary files /dev/null and b/.git/objects/e8/78ae624f3d58b8c1c6523fdcc3f204168e768a differ diff --git a/.git/objects/e8/79c09763e52887162cf7f50a2d782a0a9252d9 b/.git/objects/e8/79c09763e52887162cf7f50a2d782a0a9252d9 new file mode 100644 index 0000000..3d8a9cb Binary files /dev/null and b/.git/objects/e8/79c09763e52887162cf7f50a2d782a0a9252d9 differ diff --git a/.git/objects/e8/7a69a555b5be4e018cdd0013c852065b886ad8 b/.git/objects/e8/7a69a555b5be4e018cdd0013c852065b886ad8 new file mode 100644 index 0000000..6495560 Binary files /dev/null and b/.git/objects/e8/7a69a555b5be4e018cdd0013c852065b886ad8 differ diff --git a/.git/objects/e8/7d127676cd75c63046e0049b59870b5e399b3c b/.git/objects/e8/7d127676cd75c63046e0049b59870b5e399b3c new file mode 100644 index 0000000..30bbaa1 --- /dev/null +++ b/.git/objects/e8/7d127676cd75c63046e0049b59870b5e399b3c @@ -0,0 +1,3 @@ +xAN!E]siHq= PT ގWp/qoNpa}CrHyAr.Qm"B +bn4tz'bAaK)@>!;69m?F+modp:1=Y(a[ \ No newline at end of file diff --git a/.git/objects/ed/1a3309687233898e6f0034eee154a6f312a5d1 b/.git/objects/ed/1a3309687233898e6f0034eee154a6f312a5d1 new file mode 100644 index 0000000..4db8201 Binary files /dev/null and b/.git/objects/ed/1a3309687233898e6f0034eee154a6f312a5d1 differ diff --git a/.git/objects/ed/1caa5475d8c4b4d5059cbd0e3572c46986bfde b/.git/objects/ed/1caa5475d8c4b4d5059cbd0e3572c46986bfde new file mode 100644 index 0000000..4df24af Binary files /dev/null and b/.git/objects/ed/1caa5475d8c4b4d5059cbd0e3572c46986bfde differ diff --git a/.git/objects/ed/22aaf709fb18d67f3ad81c967aaa7aeb656da5 b/.git/objects/ed/22aaf709fb18d67f3ad81c967aaa7aeb656da5 new file mode 100644 index 0000000..54d3497 Binary files /dev/null and b/.git/objects/ed/22aaf709fb18d67f3ad81c967aaa7aeb656da5 differ diff --git a/.git/objects/ed/24eadff22bbda3ba3194aaa7e4700f7eeb85cb b/.git/objects/ed/24eadff22bbda3ba3194aaa7e4700f7eeb85cb new file mode 100644 index 0000000..2b5af02 Binary files /dev/null and b/.git/objects/ed/24eadff22bbda3ba3194aaa7e4700f7eeb85cb differ diff --git a/.git/objects/ed/2f2709326740b8fae0bacb7e2110b64143840f b/.git/objects/ed/2f2709326740b8fae0bacb7e2110b64143840f new file mode 100644 index 0000000..eddf767 Binary files /dev/null and b/.git/objects/ed/2f2709326740b8fae0bacb7e2110b64143840f differ diff --git a/.git/objects/ed/3a7ace7cdd5a04b0f3e4d20b7f2503cb11874c b/.git/objects/ed/3a7ace7cdd5a04b0f3e4d20b7f2503cb11874c new file mode 100644 index 0000000..5be33a7 Binary files /dev/null and b/.git/objects/ed/3a7ace7cdd5a04b0f3e4d20b7f2503cb11874c differ diff --git a/.git/objects/ed/62f4682dbb4a790f901f0e7bea8be631a0e7cf b/.git/objects/ed/62f4682dbb4a790f901f0e7bea8be631a0e7cf new file mode 100644 index 0000000..6bb9d2a Binary files /dev/null and b/.git/objects/ed/62f4682dbb4a790f901f0e7bea8be631a0e7cf differ diff --git a/.git/objects/ed/638442b5c5b5c85bb2147392a78a4a88c5b989 b/.git/objects/ed/638442b5c5b5c85bb2147392a78a4a88c5b989 new file mode 100644 index 0000000..a378d68 Binary files /dev/null and b/.git/objects/ed/638442b5c5b5c85bb2147392a78a4a88c5b989 differ diff --git a/.git/objects/ed/64f049d7b52c2533cbab2ca4bf1b19dc0ea218 b/.git/objects/ed/64f049d7b52c2533cbab2ca4bf1b19dc0ea218 new file mode 100644 index 0000000..b27354f --- /dev/null +++ b/.git/objects/ed/64f049d7b52c2533cbab2ca4bf1b19dc0ea218 @@ -0,0 +1,2 @@ +x%MN0 Y#I# XfN$46`8{.F Kg5VZBVI%͕4VJ#"31(Dऽ4fX(U1 äImzk%#^\iOL +Gm]mp=֙vs.0 ƺ6mܵ<%nq{7| MޝjArK%6̷[ \ No newline at end of file diff --git a/.git/objects/ed/a9baadcaf1157fc870bf2321875a1cb338db0e b/.git/objects/ed/a9baadcaf1157fc870bf2321875a1cb338db0e new file mode 100644 index 0000000..64d7670 --- /dev/null +++ b/.git/objects/ed/a9baadcaf1157fc870bf2321875a1cb338db0e @@ -0,0 +1,2 @@ +x-KN0 Y^U Bl8Ӡ6T07cňFl,[e1791QfFlIӨm46p37X8dh@G&$Ye=: +<O3cpSqߟx#zO%xRS\AJ i^H!*yJ~Hu9/kvܨx]W'>!O%y! υV2ڙ?`d7 \ No newline at end of file diff --git a/.git/objects/ed/c79c2a673671e28eaa5ada3da859048388ed15 b/.git/objects/ed/c79c2a673671e28eaa5ada3da859048388ed15 new file mode 100644 index 0000000..3353502 Binary files /dev/null and b/.git/objects/ed/c79c2a673671e28eaa5ada3da859048388ed15 differ diff --git a/.git/objects/ed/f2497098f041ebc1c76cf8b0418a399e36ee3a b/.git/objects/ed/f2497098f041ebc1c76cf8b0418a399e36ee3a new file mode 100644 index 0000000..d2c5c1c Binary files /dev/null and b/.git/objects/ed/f2497098f041ebc1c76cf8b0418a399e36ee3a differ diff --git a/.git/objects/ed/f512e84a5389c09ae2951ccb524108c38f5ad9 b/.git/objects/ed/f512e84a5389c09ae2951ccb524108c38f5ad9 new file mode 100644 index 0000000..585d473 Binary files /dev/null and b/.git/objects/ed/f512e84a5389c09ae2951ccb524108c38f5ad9 differ diff --git a/.git/objects/ed/f633e3f677ed86f85bee11f91e51ac73e3e2ab b/.git/objects/ed/f633e3f677ed86f85bee11f91e51ac73e3e2ab new file mode 100644 index 0000000..5807877 Binary files /dev/null and b/.git/objects/ed/f633e3f677ed86f85bee11f91e51ac73e3e2ab differ diff --git a/.git/objects/ed/fccdaaab7e7f761030a1e97837f7810df29a81 b/.git/objects/ed/fccdaaab7e7f761030a1e97837f7810df29a81 new file mode 100644 index 0000000..1652fed --- /dev/null +++ b/.git/objects/ed/fccdaaab7e7f761030a1e97837f7810df29a81 @@ -0,0 +1 @@ +x1N0Ds(DB/BCE7$RbGFoFŰ843OOF)@3I9➼cuoq;ppDN0u$$6 cq}G,e/J !ot$@m}>rއ?~У3Bֶ К!/kn \ No newline at end of file diff --git a/.git/objects/ee/15ada29a9a8fe3fec516d5cfca63030add41d1 b/.git/objects/ee/15ada29a9a8fe3fec516d5cfca63030add41d1 new file mode 100644 index 0000000..f976281 Binary files /dev/null and b/.git/objects/ee/15ada29a9a8fe3fec516d5cfca63030add41d1 differ diff --git a/.git/objects/ee/853830c4510dc528eae91d1d3b20ba6fe662df b/.git/objects/ee/853830c4510dc528eae91d1d3b20ba6fe662df new file mode 100644 index 0000000..39340bf Binary files /dev/null and b/.git/objects/ee/853830c4510dc528eae91d1d3b20ba6fe662df differ diff --git a/.git/objects/ee/9e3f1d28b99ee84e1c38c1188c75a98ae056f6 b/.git/objects/ee/9e3f1d28b99ee84e1c38c1188c75a98ae056f6 new file mode 100644 index 0000000..6f2dab6 Binary files /dev/null and b/.git/objects/ee/9e3f1d28b99ee84e1c38c1188c75a98ae056f6 differ diff --git a/.git/objects/ee/bb80cfc79b6d7f9192cfab821f7fc0f6adb99f b/.git/objects/ee/bb80cfc79b6d7f9192cfab821f7fc0f6adb99f new file mode 100644 index 0000000..d2e2723 Binary files /dev/null and b/.git/objects/ee/bb80cfc79b6d7f9192cfab821f7fc0f6adb99f differ diff --git a/.git/objects/ef/2c5bec559d43d930f75cd58914417b70509d49 b/.git/objects/ef/2c5bec559d43d930f75cd58914417b70509d49 new file mode 100644 index 0000000..a110189 Binary files /dev/null and b/.git/objects/ef/2c5bec559d43d930f75cd58914417b70509d49 differ diff --git a/.git/objects/ef/3835b01081e056ae67f092b0378adeb134093b b/.git/objects/ef/3835b01081e056ae67f092b0378adeb134093b new file mode 100644 index 0000000..3a0c3f4 Binary files /dev/null and b/.git/objects/ef/3835b01081e056ae67f092b0378adeb134093b differ diff --git a/.git/objects/ef/64981a1bb6a9e7e402cd590ec04d46c58713b0 b/.git/objects/ef/64981a1bb6a9e7e402cd590ec04d46c58713b0 new file mode 100644 index 0000000..2fc81ec Binary files /dev/null and b/.git/objects/ef/64981a1bb6a9e7e402cd590ec04d46c58713b0 differ diff --git a/.git/objects/ef/a8b72fa823dcf0b89eeb748fa724d07432ad91 b/.git/objects/ef/a8b72fa823dcf0b89eeb748fa724d07432ad91 new file mode 100644 index 0000000..85ca1bc Binary files /dev/null and b/.git/objects/ef/a8b72fa823dcf0b89eeb748fa724d07432ad91 differ diff --git a/.git/objects/ef/bc64e61c887d18e6f8151f9ad1bfb513760bce b/.git/objects/ef/bc64e61c887d18e6f8151f9ad1bfb513760bce new file mode 100644 index 0000000..d5e621f Binary files /dev/null and b/.git/objects/ef/bc64e61c887d18e6f8151f9ad1bfb513760bce differ diff --git a/.git/objects/ef/e449825c0c852d9abfaca7397da94cdf0af972 b/.git/objects/ef/e449825c0c852d9abfaca7397da94cdf0af972 new file mode 100644 index 0000000..869919d Binary files /dev/null and b/.git/objects/ef/e449825c0c852d9abfaca7397da94cdf0af972 differ diff --git a/.git/objects/ef/eaa94e2c92ebc8a02e92d1a0ac219f6369a1ca b/.git/objects/ef/eaa94e2c92ebc8a02e92d1a0ac219f6369a1ca new file mode 100644 index 0000000..a0921c0 Binary files /dev/null and b/.git/objects/ef/eaa94e2c92ebc8a02e92d1a0ac219f6369a1ca differ diff --git a/.git/objects/f0/2bea6781795d591e7d3473f05adb3d15cfa1a1 b/.git/objects/f0/2bea6781795d591e7d3473f05adb3d15cfa1a1 new file mode 100644 index 0000000..74b1220 Binary files /dev/null and b/.git/objects/f0/2bea6781795d591e7d3473f05adb3d15cfa1a1 differ diff --git a/.git/objects/f0/4c6fe4dc44eaf504d38f3a7af4415541297b77 b/.git/objects/f0/4c6fe4dc44eaf504d38f3a7af4415541297b77 new file mode 100644 index 0000000..c314607 Binary files /dev/null and b/.git/objects/f0/4c6fe4dc44eaf504d38f3a7af4415541297b77 differ diff --git a/.git/objects/f0/50160df8386c77cb6746e04d109e4c62430353 b/.git/objects/f0/50160df8386c77cb6746e04d109e4c62430353 new file mode 100644 index 0000000..87713ee Binary files /dev/null and b/.git/objects/f0/50160df8386c77cb6746e04d109e4c62430353 differ diff --git a/.git/objects/f0/5b3020bb8f18dcae15660388a5b3455a16cdd4 b/.git/objects/f0/5b3020bb8f18dcae15660388a5b3455a16cdd4 new file mode 100644 index 0000000..5326795 Binary files /dev/null and b/.git/objects/f0/5b3020bb8f18dcae15660388a5b3455a16cdd4 differ diff --git a/.git/objects/f0/61474b8884731abdd9da65a33df7484c701a98 b/.git/objects/f0/61474b8884731abdd9da65a33df7484c701a98 new file mode 100644 index 0000000..42f6cfb Binary files /dev/null and b/.git/objects/f0/61474b8884731abdd9da65a33df7484c701a98 differ diff --git a/.git/objects/f0/7fc9b927457b838cd87b036db1afcefb599bae b/.git/objects/f0/7fc9b927457b838cd87b036db1afcefb599bae new file mode 100644 index 0000000..bc39131 --- /dev/null +++ b/.git/objects/f0/7fc9b927457b838cd87b036db1afcefb599bae @@ -0,0 +1,5 @@ +xUkPgwL"B :Aj DČ b&`fwIݸ!CVnvT*hkdVV񂝎;U.Kȸ?|y99 }@σF)T un:57sh~o옍P !$ Nhq?*mn( YhM("JDBx>DrsUwMyέe8;Dڈ5(HMi5hü+l%J"z~yrBwi.'3N'+i@%d )\c$z+g*?qC盃쵘hQ4PW,VM Ju_^gDqF=ذ R8^`eWy'?֡Ead٧ƅ6= +]A,Ls^قws!$b60q b_u S EZIٙ%}ݭS=b!/sx ՁjFh׊֏6Ԟ +hv'8- +Yeui״EgsVr,rG{H"Fky䷮ +A`ŘL%Abj+_yOe]Ž坍ø i}=Wtإ = W \C0꣛t~^'b!f12m z*K*c3|约&ːczLϾ#1 R SrifdevYa 'LF@|$QOJ[Q:0Q0:4OFEh_ڌi.{Ԥ#g `"m__ziۗ/5P#[+pqW{1ւw0T`Py>B:kb#Zb=|1m_qCUDIA~NU|_XҶ,Sœ$ AJce6= .杼1Fo+ZTҾ7Yڪ Qs{;t7yͤsAVAG?蕳1S*UR!Q`:Z-nX97pikJKZhsdL +QAG_m* c&:c ?5'MߥH'f }p>k/L]|BnitHqxW"d \ No newline at end of file diff --git a/.git/objects/f5/4eeb26f745db0807ea2cf0f7b2a3fa43efecc2 b/.git/objects/f5/4eeb26f745db0807ea2cf0f7b2a3fa43efecc2 new file mode 100644 index 0000000..45ea3c7 Binary files /dev/null and b/.git/objects/f5/4eeb26f745db0807ea2cf0f7b2a3fa43efecc2 differ diff --git a/.git/objects/f5/651857bdb5fc5204d30e9a7a10e675a92ce2ee b/.git/objects/f5/651857bdb5fc5204d30e9a7a10e675a92ce2ee new file mode 100644 index 0000000..b5bd0bc Binary files /dev/null and b/.git/objects/f5/651857bdb5fc5204d30e9a7a10e675a92ce2ee differ diff --git a/.git/objects/f5/8fd58d83268ec01bb5f933efd3b92c63dd8bff b/.git/objects/f5/8fd58d83268ec01bb5f933efd3b92c63dd8bff new file mode 100644 index 0000000..fca61ed Binary files /dev/null and b/.git/objects/f5/8fd58d83268ec01bb5f933efd3b92c63dd8bff differ diff --git a/.git/objects/f5/93c926e383bfd142783acb7c2eaec57485a3db b/.git/objects/f5/93c926e383bfd142783acb7c2eaec57485a3db new file mode 100644 index 0000000..02f1331 --- /dev/null +++ b/.git/objects/f5/93c926e383bfd142783acb7c2eaec57485a3db @@ -0,0 +1 @@ +x=J0E]+^,I״0Ȁ;pF'MIǯ7(11 Hy ! }'8 dQsK(ɚA*gISMۺbgy ^9xN<cxVG[*$xY-V8qgm{xR]+翀 ߷[k*iq`DYl(LZ{ \ No newline at end of file diff --git a/.git/objects/f5/96ce1e81a150ff3fb8e177dd6bcddc19e6a7b4 b/.git/objects/f5/96ce1e81a150ff3fb8e177dd6bcddc19e6a7b4 new file mode 100644 index 0000000..8eb350c Binary files /dev/null and b/.git/objects/f5/96ce1e81a150ff3fb8e177dd6bcddc19e6a7b4 differ diff --git a/.git/objects/f6/1a75cf16b6e3745ff925b1d22be7670727c2ac b/.git/objects/f6/1a75cf16b6e3745ff925b1d22be7670727c2ac new file mode 100644 index 0000000..b5e93e3 Binary files /dev/null and b/.git/objects/f6/1a75cf16b6e3745ff925b1d22be7670727c2ac differ diff --git a/.git/objects/f6/b75a3566210d94b58cd76d12d6db52bb72180c b/.git/objects/f6/b75a3566210d94b58cd76d12d6db52bb72180c new file mode 100644 index 0000000..1889595 Binary files /dev/null and b/.git/objects/f6/b75a3566210d94b58cd76d12d6db52bb72180c differ diff --git a/.git/objects/f6/c7d02e45aba773210e557ce0a363bbe0282a68 b/.git/objects/f6/c7d02e45aba773210e557ce0a363bbe0282a68 new file mode 100644 index 0000000..7d53157 Binary files /dev/null and b/.git/objects/f6/c7d02e45aba773210e557ce0a363bbe0282a68 differ diff --git a/.git/objects/f7/0bd8ba86bec59ba42b9a1b4809d26eb1bb69c5 b/.git/objects/f7/0bd8ba86bec59ba42b9a1b4809d26eb1bb69c5 new file mode 100644 index 0000000..559d41f Binary files /dev/null and b/.git/objects/f7/0bd8ba86bec59ba42b9a1b4809d26eb1bb69c5 differ diff --git a/.git/objects/f7/0c9db0e38a0e69656cec45e3c6892cccb498ac b/.git/objects/f7/0c9db0e38a0e69656cec45e3c6892cccb498ac new file mode 100644 index 0000000..deaeaeb Binary files /dev/null and b/.git/objects/f7/0c9db0e38a0e69656cec45e3c6892cccb498ac differ diff --git a/.git/objects/f7/4ca33d083e3d300c1d84e7325e0addbf872847 b/.git/objects/f7/4ca33d083e3d300c1d84e7325e0addbf872847 new file mode 100644 index 0000000..d5d1c4f Binary files /dev/null and b/.git/objects/f7/4ca33d083e3d300c1d84e7325e0addbf872847 differ diff --git a/.git/objects/f7/861ca4503e528d9f64d531515dc48a973524d1 b/.git/objects/f7/861ca4503e528d9f64d531515dc48a973524d1 new file mode 100644 index 0000000..d89ef3e Binary files /dev/null and b/.git/objects/f7/861ca4503e528d9f64d531515dc48a973524d1 differ diff --git a/.git/objects/f7/8a7c931b91e4d7ca7709e3460f50a4599832dd b/.git/objects/f7/8a7c931b91e4d7ca7709e3460f50a4599832dd new file mode 100644 index 0000000..f703f53 --- /dev/null +++ b/.git/objects/f7/8a7c931b91e4d7ca7709e3460f50a4599832dd @@ -0,0 +1,3 @@ +x-NN0WLXJVh +QA%1%vd;=?cӲ +ljFfb^r0JDϨsG1z$Ugx4sBBy' 画:FSawTtzSp7㗎3<f});G,pM= fI^SlZn2{֏k4P1峎pq>װCDžG7Dxm!ˊB"ɼ7>[ _y \ No newline at end of file diff --git a/.git/objects/f7/9f17de2eac5569635eaf914ebc079a04ba300a b/.git/objects/f7/9f17de2eac5569635eaf914ebc079a04ba300a new file mode 100644 index 0000000..6e73f9a Binary files /dev/null and b/.git/objects/f7/9f17de2eac5569635eaf914ebc079a04ba300a differ diff --git a/.git/objects/f7/9f23a08ed822bd114219284b6b66af7c38afec b/.git/objects/f7/9f23a08ed822bd114219284b6b66af7c38afec new file mode 100644 index 0000000..530db27 Binary files /dev/null and b/.git/objects/f7/9f23a08ed822bd114219284b6b66af7c38afec differ diff --git a/.git/objects/f7/a1e181cd4364d21d981acda557c584a65cf25b b/.git/objects/f7/a1e181cd4364d21d981acda557c584a65cf25b new file mode 100644 index 0000000..0bf3498 --- /dev/null +++ b/.git/objects/f7/a1e181cd4364d21d981acda557c584a65cf25b @@ -0,0 +1 @@ +x%OJ0uݯ{ 2"Ӎ_pimR3yq+j!2sG͘;gTNJt^;TbT%k!(E( o:U3^\e@>3%.68cS/uYǜ`- gkl][T﹌?py_55q OLxoP5CNpYVcaő_Xy \ No newline at end of file diff --git a/.git/objects/f7/fcc9f053b6ad2951948be6d8c5c32975fc02f5 b/.git/objects/f7/fcc9f053b6ad2951948be6d8c5c32975fc02f5 new file mode 100644 index 0000000..035bf4d Binary files /dev/null and b/.git/objects/f7/fcc9f053b6ad2951948be6d8c5c32975fc02f5 differ diff --git a/.git/objects/f8/180a7c9a2fa815fd83a79d0444c7708ade5d7f b/.git/objects/f8/180a7c9a2fa815fd83a79d0444c7708ade5d7f new file mode 100644 index 0000000..3b78720 Binary files /dev/null and b/.git/objects/f8/180a7c9a2fa815fd83a79d0444c7708ade5d7f differ diff --git a/.git/objects/f8/1a338ee26ab1144d4393c3afe2034b7379afbb b/.git/objects/f8/1a338ee26ab1144d4393c3afe2034b7379afbb new file mode 100644 index 0000000..46e5b9b Binary files /dev/null and b/.git/objects/f8/1a338ee26ab1144d4393c3afe2034b7379afbb differ diff --git a/.git/objects/f8/4c811569af3b87d70fae25935fb3cd00dbd1a0 b/.git/objects/f8/4c811569af3b87d70fae25935fb3cd00dbd1a0 new file mode 100644 index 0000000..1cbdd4a Binary files /dev/null and b/.git/objects/f8/4c811569af3b87d70fae25935fb3cd00dbd1a0 differ diff --git a/.git/objects/f8/518adef50003017562535581b8e16f817c09c9 b/.git/objects/f8/518adef50003017562535581b8e16f817c09c9 new file mode 100644 index 0000000..1b8bc9c Binary files /dev/null and b/.git/objects/f8/518adef50003017562535581b8e16f817c09c9 differ diff --git a/.git/objects/f8/51d9378f026acacb7904db46cec9a44cf5545c b/.git/objects/f8/51d9378f026acacb7904db46cec9a44cf5545c new file mode 100644 index 0000000..7b7e1df --- /dev/null +++ b/.git/objects/f8/51d9378f026acacb7904db46cec9a44cf5545c @@ -0,0 +1,2 @@ +x-ON0䜯xwDeKT"pxyn,yl?Ώa*.fь1$ZAEb4rr1㦑82Nf|2|T@\EİyVX4¨)j-TXÛԭbwIXᨺzj+ݒt;_҅2{+rQ &I=>7@=>\T3 +|Jb* Mu\1 \ No newline at end of file diff --git a/.git/objects/f8/77faa0b1177a3a0ecee861f90c8fe4fc632036 b/.git/objects/f8/77faa0b1177a3a0ecee861f90c8fe4fc632036 new file mode 100644 index 0000000..a86200e Binary files /dev/null and b/.git/objects/f8/77faa0b1177a3a0ecee861f90c8fe4fc632036 differ diff --git a/.git/objects/f8/a95cfde893d74e7e88997b020a184f02b280fe b/.git/objects/f8/a95cfde893d74e7e88997b020a184f02b280fe new file mode 100644 index 0000000..858af75 Binary files /dev/null and b/.git/objects/f8/a95cfde893d74e7e88997b020a184f02b280fe differ diff --git a/.git/objects/f8/aac936fe4e067d78faa8f856f3f1c350b9c306 b/.git/objects/f8/aac936fe4e067d78faa8f856f3f1c350b9c306 new file mode 100644 index 0000000..6035f5d Binary files /dev/null and b/.git/objects/f8/aac936fe4e067d78faa8f856f3f1c350b9c306 differ diff --git a/.git/objects/f8/fb363ce42eba353ac74f7871cb3663b2b9df0a b/.git/objects/f8/fb363ce42eba353ac74f7871cb3663b2b9df0a new file mode 100644 index 0000000..a26b0de --- /dev/null +++ b/.git/objects/f8/fb363ce42eba353ac74f7871cb3663b2b9df0a @@ -0,0 +1,3 @@ +xj0S ٴ]H>P +@.+ci#"Kf4WΡyIf Lt2}uK;X77DvM?wӤhڐ) +z,ja54gu#zT91|;=a_kM[uU2oB%ķp sFF8P8c`2i]]UKLLǗ.J{$Yx9R,>)$-)Ӎ)r1p3]0 <ia\3xmb9&o&O~pڈ\,,\NE % \ No newline at end of file diff --git a/.git/objects/f9/5f3d533a78198a5ef058bddfd17b2a9a12efb1 b/.git/objects/f9/5f3d533a78198a5ef058bddfd17b2a9a12efb1 new file mode 100644 index 0000000..f2bcceb Binary files /dev/null and b/.git/objects/f9/5f3d533a78198a5ef058bddfd17b2a9a12efb1 differ diff --git a/.git/objects/f9/934cb8e335ae680e6e6ccbf433b71bb308d26e b/.git/objects/f9/934cb8e335ae680e6e6ccbf433b71bb308d26e new file mode 100644 index 0000000..799d484 Binary files /dev/null and b/.git/objects/f9/934cb8e335ae680e6e6ccbf433b71bb308d26e differ diff --git a/.git/objects/f9/cfc40cc7856cd46f09cebc1857dbe7f5188a88 b/.git/objects/f9/cfc40cc7856cd46f09cebc1857dbe7f5188a88 new file mode 100644 index 0000000..5654c46 Binary files /dev/null and b/.git/objects/f9/cfc40cc7856cd46f09cebc1857dbe7f5188a88 differ diff --git a/.git/objects/f9/de10dd755546868fe2530ad70f0795a18a519d b/.git/objects/f9/de10dd755546868fe2530ad70f0795a18a519d new file mode 100644 index 0000000..93e83c4 Binary files /dev/null and b/.git/objects/f9/de10dd755546868fe2530ad70f0795a18a519d differ diff --git a/.git/objects/f9/dfcf5891799501704ef5c68e5d622add3f2690 b/.git/objects/f9/dfcf5891799501704ef5c68e5d622add3f2690 new file mode 100644 index 0000000..44ab26a Binary files /dev/null and b/.git/objects/f9/dfcf5891799501704ef5c68e5d622add3f2690 differ diff --git a/.git/objects/f9/e712382dfb195211d59e025e5dc3fbe999ec67 b/.git/objects/f9/e712382dfb195211d59e025e5dc3fbe999ec67 new file mode 100644 index 0000000..a348b93 --- /dev/null +++ b/.git/objects/f9/e712382dfb195211d59e025e5dc3fbe999ec67 @@ -0,0 +1,4 @@ +x1n0 E;!$G A )CRf{ +FΝHtqC%aI'I\'Qz8%q@͂Q^BJtV5IlՃ=VYୌ1˘Bטpr\~n¥eȑ R*+8Ѹ-mz>}'\31% 'RFHy*9 +շqc0c ]o J +52m0M+G,| ?` = \ No newline at end of file diff --git a/.git/objects/fa/2d3dc05aa8eb2a622010e962c8615350eb20cc b/.git/objects/fa/2d3dc05aa8eb2a622010e962c8615350eb20cc new file mode 100644 index 0000000..8c7ab40 Binary files /dev/null and b/.git/objects/fa/2d3dc05aa8eb2a622010e962c8615350eb20cc differ diff --git a/.git/objects/fa/5a0b722ebdc17dfe09c0fc8bc5d44af7c18708 b/.git/objects/fa/5a0b722ebdc17dfe09c0fc8bc5d44af7c18708 new file mode 100644 index 0000000..f34877a Binary files /dev/null and b/.git/objects/fa/5a0b722ebdc17dfe09c0fc8bc5d44af7c18708 differ diff --git a/.git/objects/fa/8031eb3340d0643a5bcee5dd9b04218ba84ef2 b/.git/objects/fa/8031eb3340d0643a5bcee5dd9b04218ba84ef2 new file mode 100644 index 0000000..2336a26 Binary files /dev/null and b/.git/objects/fa/8031eb3340d0643a5bcee5dd9b04218ba84ef2 differ diff --git a/.git/objects/fa/b4ff0e59ef37a5f8e768036833ebc0de253daf b/.git/objects/fa/b4ff0e59ef37a5f8e768036833ebc0de253daf new file mode 100644 index 0000000..4ae5dc8 Binary files /dev/null and b/.git/objects/fa/b4ff0e59ef37a5f8e768036833ebc0de253daf differ diff --git a/.git/objects/fa/eb5af055024b0b2c2b6ab6786b6bc928c5dd00 b/.git/objects/fa/eb5af055024b0b2c2b6ab6786b6bc928c5dd00 new file mode 100644 index 0000000..ff05144 Binary files /dev/null and b/.git/objects/fa/eb5af055024b0b2c2b6ab6786b6bc928c5dd00 differ diff --git a/.git/objects/fa/fcbce1bd070b7aa94f4ab3576646bd52650ffa b/.git/objects/fa/fcbce1bd070b7aa94f4ab3576646bd52650ffa new file mode 100644 index 0000000..9c51075 --- /dev/null +++ b/.git/objects/fa/fcbce1bd070b7aa94f4ab3576646bd52650ffa @@ -0,0 +1,2 @@ +xKj0E;*bҒqslEB }M Xrp>F#NkP%e + vAE'nYћVZj hDdJiI:m.]>c~oDiyvspB3r[~RJPתR ~QZ0 +ě2OxT \ No newline at end of file diff --git a/.git/objects/fb/0c66b5868522e8988056e7b81106f3a269d962 b/.git/objects/fb/0c66b5868522e8988056e7b81106f3a269d962 new file mode 100644 index 0000000..7998158 Binary files /dev/null and b/.git/objects/fb/0c66b5868522e8988056e7b81106f3a269d962 differ diff --git a/.git/objects/fb/13cd7c13a9aaf2c3fef4ce468baabb73cad48b b/.git/objects/fb/13cd7c13a9aaf2c3fef4ce468baabb73cad48b new file mode 100644 index 0000000..0f8266b --- /dev/null +++ b/.git/objects/fb/13cd7c13a9aaf2c3fef4ce468baabb73cad48b @@ -0,0 +1,2 @@ +x-An D)`(U&'d¸in}/Vu7̛-TgL8.jU7HT`Éǖ}@S +Uf/c \ No newline at end of file diff --git a/.git/objects/fb/604b9d8e731178ab53be63f413455bb49dddba b/.git/objects/fb/604b9d8e731178ab53be63f413455bb49dddba new file mode 100644 index 0000000..9c8c3e3 Binary files /dev/null and b/.git/objects/fb/604b9d8e731178ab53be63f413455bb49dddba differ diff --git a/.git/objects/fb/a110cf157cf509fbd7187442f95728d41232a7 b/.git/objects/fb/a110cf157cf509fbd7187442f95728d41232a7 new file mode 100644 index 0000000..ba67962 Binary files /dev/null and b/.git/objects/fb/a110cf157cf509fbd7187442f95728d41232a7 differ diff --git a/.git/objects/fc/0ce612859df3da8a49a5e04e152983fb006e12 b/.git/objects/fc/0ce612859df3da8a49a5e04e152983fb006e12 new file mode 100644 index 0000000..06a64e2 Binary files /dev/null and b/.git/objects/fc/0ce612859df3da8a49a5e04e152983fb006e12 differ diff --git a/.git/objects/fc/1e1bfb28cd229ea8cffe9038c32bfb7dc8e655 b/.git/objects/fc/1e1bfb28cd229ea8cffe9038c32bfb7dc8e655 new file mode 100644 index 0000000..5f61a61 Binary files /dev/null and b/.git/objects/fc/1e1bfb28cd229ea8cffe9038c32bfb7dc8e655 differ diff --git a/.git/objects/fc/379cb4a1674456194ca4a4047c65ba9876aaf6 b/.git/objects/fc/379cb4a1674456194ca4a4047c65ba9876aaf6 new file mode 100644 index 0000000..1f7a231 --- /dev/null +++ b/.git/objects/fc/379cb4a1674456194ca4a4047c65ba9876aaf6 @@ -0,0 +1,3 @@ +x-PN0Wlqlj:- o%؎#FϏa!A&'"Z(C)٠hl:!qwM`u=vF7|М vH\}#pcL0K ^'gW +pIJ=B1=pQ%&2XU%w.>OcVxΛ?\@vK;V7 + *Z< c׵3}Ju *^ \ No newline at end of file diff --git a/.git/objects/fc/3dc556ea234b878c06317d3ac97fab1bfee4c0 b/.git/objects/fc/3dc556ea234b878c06317d3ac97fab1bfee4c0 new file mode 100644 index 0000000..f4d48ed Binary files /dev/null and b/.git/objects/fc/3dc556ea234b878c06317d3ac97fab1bfee4c0 differ diff --git a/.git/objects/fc/558599e917de7e778f93ab85a96a6d314cd9b6 b/.git/objects/fc/558599e917de7e778f93ab85a96a6d314cd9b6 new file mode 100644 index 0000000..c15b6c0 Binary files /dev/null and b/.git/objects/fc/558599e917de7e778f93ab85a96a6d314cd9b6 differ diff --git a/.git/objects/fc/9b66b868ed9f18a49b86e54b9c273b36e4225e b/.git/objects/fc/9b66b868ed9f18a49b86e54b9c273b36e4225e new file mode 100644 index 0000000..5fc49e3 Binary files /dev/null and b/.git/objects/fc/9b66b868ed9f18a49b86e54b9c273b36e4225e differ diff --git a/.git/objects/fc/9bcb492728e4f258dd23dd4f2f5111d264832e b/.git/objects/fc/9bcb492728e4f258dd23dd4f2f5111d264832e new file mode 100644 index 0000000..6125bb8 --- /dev/null +++ b/.git/objects/fc/9bcb492728e4f258dd23dd4f2f5111d264832e @@ -0,0 +1,2 @@ +xKN0 `= (6 Ap{8༦eQ\u)4=<~ӻ +ş)7jui%}a]?=Ur \ No newline at end of file diff --git a/.git/objects/fe/0e8bfaeea90d8b3ea1d7019c914d786262c7e7 b/.git/objects/fe/0e8bfaeea90d8b3ea1d7019c914d786262c7e7 new file mode 100644 index 0000000..8200d85 Binary files /dev/null and b/.git/objects/fe/0e8bfaeea90d8b3ea1d7019c914d786262c7e7 differ diff --git a/.git/objects/fe/0ecca7a6054841d6c0275d0aafe857d552c4cf b/.git/objects/fe/0ecca7a6054841d6c0275d0aafe857d552c4cf new file mode 100644 index 0000000..25be3ee Binary files /dev/null and b/.git/objects/fe/0ecca7a6054841d6c0275d0aafe857d552c4cf differ diff --git a/.git/objects/fe/56884a98ac13c2cbe5af26af33063a9089edb9 b/.git/objects/fe/56884a98ac13c2cbe5af26af33063a9089edb9 new file mode 100644 index 0000000..87fcc10 --- /dev/null +++ b/.git/objects/fe/56884a98ac13c2cbe5af26af33063a9089edb9 @@ -0,0 +1,2 @@ +x-MN0 FY#FiDAAH8m&bm}߳+)ewk%Epi Ѩ`4ڞ݂ +NJoPA+,:h-w^sGJp[Ri/̞*FWf5]358^։R%NGJ6a3Xu<3]: [:}.D~ǭFw{}PK. ay#`Qk`] \ No newline at end of file diff --git a/.git/objects/fe/5c6ba433e486108b3c4d9c290e55c11e42a0b4 b/.git/objects/fe/5c6ba433e486108b3c4d9c290e55c11e42a0b4 new file mode 100644 index 0000000..b0aad7a Binary files /dev/null and b/.git/objects/fe/5c6ba433e486108b3c4d9c290e55c11e42a0b4 differ diff --git a/.git/objects/fe/77781aba1cb10d06cfd11cd7517e06387581ee b/.git/objects/fe/77781aba1cb10d06cfd11cd7517e06387581ee new file mode 100644 index 0000000..dfd0337 Binary files /dev/null and b/.git/objects/fe/77781aba1cb10d06cfd11cd7517e06387581ee differ diff --git a/.git/objects/fe/80fc34b6a1446820ee1c8f435a51c9f56c2bd6 b/.git/objects/fe/80fc34b6a1446820ee1c8f435a51c9f56c2bd6 new file mode 100644 index 0000000..6a278ca Binary files /dev/null and b/.git/objects/fe/80fc34b6a1446820ee1c8f435a51c9f56c2bd6 differ diff --git a/.git/objects/fe/89ff75f46f9f4a5b1500279aef893624fc6b47 b/.git/objects/fe/89ff75f46f9f4a5b1500279aef893624fc6b47 new file mode 100644 index 0000000..c3e6f8c Binary files /dev/null and b/.git/objects/fe/89ff75f46f9f4a5b1500279aef893624fc6b47 differ diff --git a/.git/objects/fe/c4edfa8feeaa42b13d11a8d2890c55ebdaa014 b/.git/objects/fe/c4edfa8feeaa42b13d11a8d2890c55ebdaa014 new file mode 100644 index 0000000..3f5187d Binary files /dev/null and b/.git/objects/fe/c4edfa8feeaa42b13d11a8d2890c55ebdaa014 differ diff --git a/.git/objects/fe/c70ff9bb9e94f98c7946cdba17c81ce132a1e9 b/.git/objects/fe/c70ff9bb9e94f98c7946cdba17c81ce132a1e9 new file mode 100644 index 0000000..038b38d Binary files /dev/null and b/.git/objects/fe/c70ff9bb9e94f98c7946cdba17c81ce132a1e9 differ diff --git a/.git/objects/fe/fb74d1acde3d1d71260ced9b5d379ed80cce2c b/.git/objects/fe/fb74d1acde3d1d71260ced9b5d379ed80cce2c new file mode 100644 index 0000000..63b9539 --- /dev/null +++ b/.git/objects/fe/fb74d1acde3d1d71260ced9b5d379ed80cce2c @@ -0,0 +1 @@ +xAN09s_ M pA<`<Kٳ˸1 oUjus0sE:C {'^1h48;:#T$)Zbf eO~F 4}GW]s&x7UIUTxFu)yn'0ٹyp]Knm=qlIcNV8d:?0,퉿6k \ No newline at end of file diff --git a/.git/objects/ff/0c64027f7a7d3843e23a4d38e7579e6aa08572 b/.git/objects/ff/0c64027f7a7d3843e23a4d38e7579e6aa08572 new file mode 100644 index 0000000..a48f75e Binary files /dev/null and b/.git/objects/ff/0c64027f7a7d3843e23a4d38e7579e6aa08572 differ diff --git a/.git/objects/ff/1b8fb4b052c16a99e4a5c156a575c70c1866b9 b/.git/objects/ff/1b8fb4b052c16a99e4a5c156a575c70c1866b9 new file mode 100644 index 0000000..1bc30b1 Binary files /dev/null and b/.git/objects/ff/1b8fb4b052c16a99e4a5c156a575c70c1866b9 differ diff --git a/.git/objects/ff/39f508539482fe84636ceb1b81de27fe2b8598 b/.git/objects/ff/39f508539482fe84636ceb1b81de27fe2b8598 new file mode 100644 index 0000000..a44bad4 --- /dev/null +++ b/.git/objects/ff/39f508539482fe84636ceb1b81de27fe2b8598 @@ -0,0 +1,7 @@ +x]iPgǷ *cj*VQG DF4`*q$ n܃(D6:Ui9* E #ȡ1-J6d72~/}@/.OR + \VM@#tQV!!IsY'^ۊתRzBcđ|(Z,h`κ:SI5XtCdhX< Iq%ȸuvj:e-DbiPRߵjq7ϕ3pԠI +ע{@ +1p +i w?\2Z)F\ZzF:0/Ʌ?hsis[8QQV6JC=NnEg $S>Nl[9v&d 0u|+,]bL6oq_d +HW+BZF4T[=fƵO5^ f{N]|k/Js\ߗ,)?-Aٜ˝ncuf$vTQl,e~3}l+FhF)Dˠ F"|lO l4r^vgQ-5Tp9-Dvk, MwV8NΆ%WPSE D@b8W HRNzܐc'2@HZ:weL9ysZζT8MOjV߲CK CǴXb-˯ܴh#jiHh BREO%i-c$;Vw3UL:V^FWJq%bI M&4aN%L2yϘ,T9Mj mxin%E/2 \ No newline at end of file diff --git a/.git/objects/ff/593451846c400cf6ca1f5e79fa60ab394f7a6a b/.git/objects/ff/593451846c400cf6ca1f5e79fa60ab394f7a6a new file mode 100644 index 0000000..d48f7f2 Binary files /dev/null and b/.git/objects/ff/593451846c400cf6ca1f5e79fa60ab394f7a6a differ diff --git a/.git/objects/ff/84b7ab38fd47a7dcb6357b5108e8b61ff3cfa3 b/.git/objects/ff/84b7ab38fd47a7dcb6357b5108e8b61ff3cfa3 new file mode 100644 index 0000000..a37f7d1 Binary files /dev/null and b/.git/objects/ff/84b7ab38fd47a7dcb6357b5108e8b61ff3cfa3 differ diff --git a/.git/objects/ff/8f056da09d8f37752626f1f3b76425a4882c98 b/.git/objects/ff/8f056da09d8f37752626f1f3b76425a4882c98 new file mode 100644 index 0000000..3fc6ae6 Binary files /dev/null and b/.git/objects/ff/8f056da09d8f37752626f1f3b76425a4882c98 differ diff --git a/.git/objects/ff/a33ca4f1c3460632854d64e0c8b556d9a23bc2 b/.git/objects/ff/a33ca4f1c3460632854d64e0c8b556d9a23bc2 new file mode 100644 index 0000000..6e3e782 Binary files /dev/null and b/.git/objects/ff/a33ca4f1c3460632854d64e0c8b556d9a23bc2 differ diff --git a/.git/objects/ff/c78f4db83a42a261539dac8f1e464334bc30fd b/.git/objects/ff/c78f4db83a42a261539dac8f1e464334bc30fd new file mode 100644 index 0000000..683abcb Binary files /dev/null and b/.git/objects/ff/c78f4db83a42a261539dac8f1e464334bc30fd differ diff --git a/.git/objects/ff/ea8924f521bbeb4d6407eabb2fcd511be0d74c b/.git/objects/ff/ea8924f521bbeb4d6407eabb2fcd511be0d74c new file mode 100644 index 0000000..3032ee1 Binary files /dev/null and b/.git/objects/ff/ea8924f521bbeb4d6407eabb2fcd511be0d74c differ diff --git a/.git/objects/info/.gitignore b/.git/objects/info/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.git/objects/pack/pack-6de5354a861fd8767105652089201f0db42165a3.idx b/.git/objects/pack/pack-6de5354a861fd8767105652089201f0db42165a3.idx new file mode 100644 index 0000000..3a3e4a7 Binary files /dev/null and b/.git/objects/pack/pack-6de5354a861fd8767105652089201f0db42165a3.idx differ diff --git a/.git/objects/pack/pack-6de5354a861fd8767105652089201f0db42165a3.pack b/.git/objects/pack/pack-6de5354a861fd8767105652089201f0db42165a3.pack new file mode 100644 index 0000000..cb17499 Binary files /dev/null and b/.git/objects/pack/pack-6de5354a861fd8767105652089201f0db42165a3.pack differ diff --git a/.git/packed-refs b/.git/packed-refs new file mode 100644 index 0000000..22603f7 --- /dev/null +++ b/.git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +5a9e078df620ab1f29ace3f9f6f78ced726c762b refs/remotes/origin/master diff --git a/.git/refs/heads/master b/.git/refs/heads/master new file mode 100644 index 0000000..4b3ad9d --- /dev/null +++ b/.git/refs/heads/master @@ -0,0 +1 @@ +5a9e078df620ab1f29ace3f9f6f78ced726c762b diff --git a/.git/refs/remotes/origin/HEAD b/.git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..6efe28f --- /dev/null +++ b/.git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ee9e3f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/data +include/config.php diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..dc28799 --- /dev/null +++ b/.htaccess @@ -0,0 +1,26 @@ +# default permissions +allow from all + +# uncomment this to take the website offline +# RedirectMatch ^.*$ http://appdb.winehq.org/site_outage.html + +# Set Our Default Directory Index +DirectoryIndex index.php + +# 404 not found document +ErrorDocument 404 http://www.winehq.org/site/404 + +# Modify the PHP configuration (global vars, etc.) +php_value register_globals 0 +php_value short_open_tag 0 +php_value register_long_arrays 0 +php_value magic_quotes_gpc 0 +php_flag zlib.output_compression on + +# make sure gc_probability is non-zero, we want php to take care of +# session cleanup for us +php_value session.gc_probability 1 + +# lower the probability of calling garbage collection +# the appdb gets so many hits we want to increase the divisor above 100 +php_value session.gc_divisor 2000 diff --git a/CODING_STANDARD b/CODING_STANDARD new file mode 100644 index 0000000..463140e --- /dev/null +++ b/CODING_STANDARD @@ -0,0 +1,115 @@ +WineHQ Application Database Coding Practice + +/** + * HTML + */ +- Respect html coding standards. The current doctype is HTML 4.01 transitional (http://www.w3.org/TR/REC-html40/) +Try to make your content validate nicely (http://validator.w3.org/) + +Avoid using implicitly closed elements eg.
in HTML 4.01 transitional, as it can lead to validation errors. +http://www.w3.org/TR/html401/struct/text.html#edef-BR + +/** + * Variables naming + */ +variables that don't come from outside your script (i.e. that aren't fetched from superglobals) should be named this way +(a.k.a hungarian notation): +prefix + var_name + +Where prefix is one of: +Scalar types: +i for integers +f for floats +s for strings +sh for html strings +b for booleans +Compound types: +a for arrays +o for objects +Special type: +h for handles + +the rest of the variable's name is using camel style +examples: +$aUsers +$iTopicId +$hRecordSet +$sQuery +$hResult + + +/** + * Functions naming + */ +1)functions name should be declarative and be prefixed with the name of the module (=file) where it is stored (for example image_show_thumbnail()) +2)methods (functions inside a class) are named like this: setMyName() (i.e. words separated with an upper case character) +3)normal functions (outside a class) are named like this: query_appdb() (i.e. words separated with an underscore) + + +/** + * general coding guidelines + */ +1) functions, loops and if's are written this way (look at the way {}'s are lined up): + + +2) indentation is made of 4 spaces (no tabs please) + +3) line length should be no more than 130 characters, preferably < 80 + +4) use long php tags () instead of short ones () as : + a) it could be removed from future versions of php + b) if conflicts with tags like that are used in xhtml + +5) do not use vars that require register_globals to be on as: + a) it is off by default in php 4.1+ + b) it is more secure + c) it makes it easier to understand where your vars are coming from (forms, session, etc.) + + +/** + * comments + */ +1) function, method, header and multiline comments: +/** + * This functions does nothing interesing. + * More comments to come here... + */ +function bar() +{ + foo(); +} + +2) one-line comments +// This is a one line comment + +3) always put a single space after the comment mark + +4) never use # for commenting as it will become obsolete in the future + +/** + * string quotes + */ +There are two different ways to quote strings in PHP - single quotes or double quotes. +The difference is that the parser does variable interpolation in double-quoted strings, but not in single quoted strings. +Because of this, always use single quotes unless the string contains a variable that needs to be parsed. + +Also if the string contains a variable put it inside double quotes instead of using 'bla' . $var . 'bla'; +To increase readability of the code. +Wrong: +$str = "This is a long string without any variables"; +$str = 'This string contains a variable ' . $var . ' enough said.'; + +Right: +$str = 'This is a long string without any variables'; +$str = "This string contains a variable $var enough said"; diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..207a79c --- /dev/null +++ b/LICENSE @@ -0,0 +1,278 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + diff --git a/README b/README new file mode 100644 index 0000000..c13d3fc --- /dev/null +++ b/README @@ -0,0 +1,93 @@ +WineHQ Application Database +#------------------------------------------------------------------------# +Authors: + Jeremy Newman + Charles Leop + +Contributors: + Paul van Schayck + Chris Morgan + Tony Lambregts + Jonathan Ernst + +To install locally for testing/hacking: +#------------------------------------------------------------------------# + +# Symlink from /var/www to the appdb directory + +# Copy include/config.php.sample to include/config.php + +# Edit include/config.php as you see fit, the default name of the database + used in the table creation step below is "apidb", you'll have to modify + these files if you change this in config.php + + # NOTE: You must update the APPDB_ROOT entry to be YOUR url to the application database + If this the APPDB_ROOT isn't correct your urls will point to the wrong pages. + + # NOTE: if you've changed the name of the database by changing the define of + 'APPS_DB' in include/config.php you'll have to modify the 'create database' and 'use' + entries in pretty much every file in the /tables/ directory. The recommendation is to + leave the default value of APPS_DB to keep things simple + +# 'cd tables', run './create_tables' to create the database tables + +# Look in include/config.php at the 'APPS_DBUSER' and 'APPS_DBPASS' defines. + Ensure that this user and password exist in your mysql users list and that this user + has been granted 'SELECT', 'INSERT', 'UPDATE' and 'DELETE' privileges on the database + defined by the value of 'APPS_DB' in include/config.php + +# Try to open up localhost/appdb, if you get a directory listing + Edit your /etc/apache/httpd.conf "DirectoryIndex" to include index.php + so apache will open index.php after not finding index.html/index.htm etc + +# Also ensure these options in /etc/apache/php.ini: + register_globals 0 + short_open_tag 0 + register_long_arrays 0 + magic_quotes_gpc 0 + Or ensure your appdb directory has AllowOverride' set to 'All' inside + httpd.conf to let .htaccess set these settings. + +# An AppDB admin user has been automatically created while running + the create_tables script + email: admin@localhost + password: testing + You should change the password as soon as possible! + +#------------------------------------------------------------------------# +You can either set up a real bugzilla database or a fake one +# +# cd tables, run ./create_bugzilla_tables to create the fake bugzilla tables +#------------------------------------------------------------------------# +# or installing a real bugzilla database (hope this helps) +# +# download buzilla (password for cvs is cvs) + +cd /var/www/html +export CVSROOT=:pserver:cvs@cvs.winehq.org:/home/wine +cvs login +cvs -z 0 checkout bugzilla + +# change directory to bugzilla and change the group ownership to apache. + +cd bugzilla +chgrp -R apache . +chmod -R g+rX . + + +# change to su and run ./checksetup.pl and fix up what it finds wrong. +# this may take several runs + +su +./checksetup.pl + +# in the /etc/httpd/conf/hppt.conf file find "AddHandler cgi-script .cgi" and add the following. + + +Options ExecCGI +AllowOverride Limit +Order allow,deny +Allow from all + + +# edit local config as necessary to allow access. diff --git a/README.xinha_customizations b/README.xinha_customizations new file mode 100644 index 0000000..19dd3fd --- /dev/null +++ b/README.xinha_customizations @@ -0,0 +1,13 @@ +Removed: + plugins/Abbreviation + plugins/BackgroundImage + plugins/EditTag + plugins/Equation - don't think we need this + plugins/FormOperations + plugins/InsertMarquee - scrolling text? blah + plugins/InsertSmiley - no thanks + plugins/InsertWords + plugins/ImageManager + plugins/LangMarks + plugins/NoteServer - musical notes + plugins/Template diff --git a/TODO b/TODO new file mode 100644 index 0000000..a827994 --- /dev/null +++ b/TODO @@ -0,0 +1,5 @@ +WineHQ Application Database TODO List + +For the current TODO list please refer to the Wine Wiki at: + +http://wiki.winehq.org/AppdbInfo diff --git a/account.php b/account.php new file mode 100644 index 0000000..eaeadf2 --- /dev/null +++ b/account.php @@ -0,0 +1,210 @@ +logout(); + + util_redirect_and_exit(apidb_fullurl("index.php")); + } + // not valid command, display error page + util_show_error_page_and_exit("Internal Error","This module was called with incorrect parameters"); +} + +/** + * retry + */ +function retry($sCmd, $sMsg) +{ + addmsg($sMsg, "red"); + do_account($sCmd); +} + + +/** + * create new account + */ +function cmd_do_new() +{ + global $aClean; + + if(!ereg("^.+@.+\\..+$", $aClean['sUserEmail'])) + { + $aClean['sUserEmail'] = ""; + retry("new", "Invalid email address"); + return; + } + if(empty($aClean['sUserRealname'])) + { + retry("new", "You don't have a Real name?"); + return; + } + + $oUser = new User(); + $sPassword = substr(base_convert(rand(0, PHP_INT_MAX),10, 36), 0, 9); + $iResult = $oUser->create($aClean['sUserEmail'], $sPassword, + $aClean['sUserRealname'], $aClean['sWineRelease'] ); + + if($iResult == SUCCESS) + { + mail_appdb($oUser->sEmail, "New account", "Your password is ".$sPassword); + util_redirect_and_exit(apidb_fullurl()); + } + else if($iResult == USER_CREATE_EXISTS) + { + addmsg("An account with this e-mail exists already.", "red"); + retry("new", "Failed to create account"); + } else if($iResult = USER_CREATE_FAILED) + { + addmsg("Error while creating a new user.", "red"); + retry("new", "Failed to create account"); + } else + { + addmsg("Unknown failure while creating new user. Please report this problem to appdb admins.", "red"); + retry("new", "Failed to create account"); + } +} + + +/** + * email lost password + */ +function cmd_send_passwd() +{ + global $aClean; + + /* if the user didn't enter any email address we should */ + /* ask them to */ + if($aClean['sUserEmail'] == "") + { + addmsg("Please enter your email address in the 'E-mail' field and re-request a new password", + "green"); + util_redirect_and_exit(apidb_fullurl("account.php?sCmd=login")); + } + + $shNote = '(Note: accounts for appdb.winehq.org and bugs.winehq.org ' + .'are separated, so You might need to create second account for appdb.)'; + + $iUserId = User::exists($aClean['sUserEmail']); + $sPasswd = User::generate_passwd(); + $oUser = new User($iUserId); + if ($iUserId) + { + if ($oUser->update_password($sPasswd)) + { + $sSubject = "Application DB Lost Password"; + $sMsg = "We have received a request that you lost your password.\r\n"; + $sMsg .= "We will create a new password for you. You can then change\r\n"; + $sMsg .= "your password at the Preferences screen.\r\n"; + $sMsg .= "Your new password is: ".$sPasswd."\r\n"; + + + if (mail_appdb($oUser->sEmail, $sSubject ,$sMsg)) + { + addmsg("Your new password has been emailed to you.", "green"); + } + else + { + addmsg("Your password has changed, but we could not email it to you. Contact Support (".APPDB_OWNER_EMAIL.") !", "red"); + } + } + else + { + addmsg("Internal Error, we could not update your password.", "red"); + } + } + else + { + addmsg("Sorry, that user (".$aClean['sUserEmail'].") does not exist.

" + .$shNote, "red"); + } + + util_redirect_and_exit(apidb_fullurl("account.php?sCmd=login")); +} + +/** + * on login handler + */ +function cmd_do_login() +{ + global $aClean; + + $oUser = new User(); + $iResult = $oUser->login($aClean['sUserEmail'], $aClean['sUserPassword']); + + if($iResult == SUCCESS) + { + $sReturnUrl = urldecode($aClean['sReturnTo']); + if(!$sReturnUrl) + $sReturnUrl = apidb_fullurl("index.php"); + addmsg("You are successfully logged in as '$oUser->sRealname'.", "green"); + util_redirect_and_exit($sReturnUrl); + } else + { + retry("login","Login failed ".$shNote); + } +} + +?> diff --git a/admin/.cvsignore b/admin/.cvsignore new file mode 100644 index 0000000..55d2fba --- /dev/null +++ b/admin/.cvsignore @@ -0,0 +1,2 @@ +stderr + diff --git a/admin/adminCommentView.php b/admin/adminCommentView.php new file mode 100644 index 0000000..13f5929 --- /dev/null +++ b/admin/adminCommentView.php @@ -0,0 +1,73 @@ + 100) $ItemsPerPage = 100; + + +/* display page selection links */ +echo "
"; +echo "Page $currentPage of $totalPages
"; +display_page_range($currentPage, $pageRange, $totalPages, $_SERVER['PHP_SELF']."?iItemsPerPage=".$ItemsPerPage); +echo "
"; +echo "
"; + +/* display the option to choose how many comments per-page to display */ +echo "
"; +echo "Number of comments per page:"; +echo " "; + +echo ""; +echo " "; +echo "
"; + +echo "
"; + +/* query for all of the commentId's, ordering by their time in reverse order */ +$offset = (($currentPage-1) * $ItemsPerPage); +$commentIds = query_parameters("SELECT commentId from appComments ORDER BY ". + "appComments.time ASC LIMIT ?, ?", $offset, $ItemsPerPage); +while ($oRow = query_fetch_object($commentIds)) +{ + $sQuery = "SELECT from_unixtime(unix_timestamp(time), \"%W %M %D %Y, %k:%i\") as time, ". + "commentId, parentId, versionId, userid, subject, body ". + "FROM appComments WHERE commentId = '?'"; + $hResult = query_parameters($sQuery, $oRow->commentId); + /* call view_app_comment to display the comment */ + $oComment_row = query_fetch_object($hResult); + Comment::view_app_comment($oComment_row, true); +} + +/* display page selection links */ + +echo "
"; +display_page_range($currentPage, $pageRange, $totalPages, $_SERVER['PHP_SELF']."?iItemsPerPage=".$ItemsPerPage); +echo "
"; + +apidb_footer(); +?> diff --git a/admin/adminMaintainers.php b/admin/adminMaintainers.php new file mode 100644 index 0000000..da56f47 --- /dev/null +++ b/admin/adminMaintainers.php @@ -0,0 +1,113 @@ +hasPriv("admin")) + util_show_error_page_and_exit("Insufficient privileges."); + +apidb_header("Admin Maintainers"); +echo '
',"\n"; + + + +// get available maintainers +$sQuery = "SELECT * FROM appMaintainers, user_list where appMaintainers.userId = user_list.userid"; +$sQuery.= " AND state='accepted' ORDER BY realname;"; +$hResult = query_parameters($sQuery); + +if(!$hResult || !query_num_rows($hResult)) +{ + // no apps + echo html_frame_start("","90%"); + echo '

There are no application maintainers.

',"\n"; + echo html_frame_end(" "); +} +else +{ + echo ''; + + // show applist + echo html_frame_start("","90%","",0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 1; + $oldUserId = 0; + while($oRow = query_fetch_object($hResult)) + { + $oUser = new User($oRow->userId); + $oApp = new application($oRow->appId); + if ($c % 2 == 1) { $bgcolor = 'color0'; } else { $bgcolor = 'color1'; } + + /* if this is a new user we should print a header that has the aggregate of the applications */ + /* the user super maintains and versions they maintain */ + if($oRow->userId != $oldUserId) + { + $style = "border-top:thin solid;border-bottom:thin solid"; + + echo "\n"; + echo " \n"; + + echo " \n"; + + $count = Maintainer::getMaintainerCountForUser($oUser, true); + if($count == 0) + echo " \n"; + else if($count <= 1) + echo " \n"; + else + echo " \n"; + + + $count = Maintainer::getMaintainerCountForUser($oUser, false); + if($count == 0) + echo " \n"; + else if($count <= 1) + echo " \n"; + else + echo " \n"; + + echo " \n"; + echo "\n\n"; + + $oldUserId = $oRow->userId; + } + + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + if($oRow->superMaintainer) + { + echo " \n"; + } else + { + $oVersion = new version($oRow->versionId); + echo " \n"; + } + echo " \n"; + echo "\n\n"; + $c++; + } + echo "
Submission DateMaintainerApplicationVersionAction
Maintainer summary".$oUser->objectMakeLink()." ".$count." app".$count." apps ".$count." version".$count." versions 
".print_date(mysqldatetime_to_unixtimestamp($oRow->submitTime))."  ".$oUser->objectMakeLink()."".$oApp->objectMakeLink()."*".$oVersion->objectMakeLink()."[delete]
\n\n"; + echo html_frame_end(" "); +} + +echo "
"; +apidb_footer(); +?> diff --git a/admin/adminScreenshots.php b/admin/adminScreenshots.php new file mode 100644 index 0000000..96e3759 --- /dev/null +++ b/admin/adminScreenshots.php @@ -0,0 +1,144 @@ +hasPriv("admin")) + util_show_error_page_and_exit("Insufficient privileges."); + +/* + * We issued a delete command. + */ +if(isset($aClean['sCmd'])) +{ + // process screenshot deletion + if($aClean['sCmd'] == "delete" && is_numeric($aClean['iImageId'])) + { + $oScreenshot = new Screenshot($aClean['iImageId']); + $oScreenshot->delete(); + $oScreenshot->free(); + } + util_redirect_and_exit($_SERVER['PHP_SELF']. + "?iItemsPerPage=".$aClean['iItemsPerPage']. + "&iPage=".$aClean['iPage']); +} + + +apidb_header("Screenshots"); +// regenerate all screenshots +if(isset($aClean['sRegenerate'])) +{ + $sQuery = "SELECT id FROM appData WHERE type = 'screenshot'"; + $hResult = query_parameters($sQuery); + while($oRow = query_fetch_object($hResult)) + { + echo "REGENERATING IMAGE ".$oRow->id."
"; + $screenshot = new Screenshot($oRow->id); + $screenshot->generate(); + $screenshot->free(); + set_time_limit(60); + } +} +echo "
"; +echo "Regenerate all screenshots ! ". + "(use only if you know what you are doing)
"; +echo "
"; + +/* display a range of 10 pages */ +$pageRange = 10; + +$ItemsPerPage = isset($aClean['iItemsPerPage']) ? $aClean['iItemsPerPage'] : 6; +$currentPage = isset($aClean['iPage']) ? $aClean['iPage'] : 1; + +$ItemsPerPage = min($ItemsPerPage,100); +$totalPages = ceil(screenshot::objectGetEntriesCount('accepted')/$ItemsPerPage); +$currentPage = min($currentPage,$totalPages); +$offset = (($currentPage-1) * $ItemsPerPage); + + +/* display page selection links */ +echo "
"; +echo "Page $currentPage of $totalPages
"; +display_page_range($currentPage, $pageRange, $totalPages, + $_SERVER['PHP_SELF']."?iItemsPerPage=".$ItemsPerPage); +echo "
"; +echo "
"; + +/* display the option to choose how many screenshots per-page to display */ +echo '
'; +echo 'Number of Screenshots per page:'; +echo " "; + +echo ""; +echo " "; +echo "
"; + +echo "
"; + +/* query for all of the Screenshots in assending order */ +$Ids = query_parameters("SELECT * from appData + WHERE type = 'screenshot' + AND state = 'accepted' + ORDER BY id ASC LIMIT ?, ?", $offset, $ItemsPerPage); +$c = 1; +echo "
\n"; +while ($oRow = query_fetch_object($Ids)) +{ + // display thumbnail + $oVersion = new Version($oRow->versionId); + $oApp = new Application($oVersion->iAppId); + $oScreenshot = new Screenshot($oRow->id); + $img = $oScreenshot->get_thumbnail_img(); + echo "\n"; + // end row if counter of 3 + if ($c % 3 == 0) echo "\n"; + $c++; + +} +echo "
\n"; + echo $img; + echo "
". substr($oRow->description,0,20). "\n"; + + echo "
[".$oApp->objectMakeLink()."]"; + + echo "
[".$oVersion->objectMakeLink()."]"; + + //show admin delete link + if($_SESSION['current']->isLoggedIn() && + ($_SESSION['current']->hasPriv("admin") || + $_SESSION['current']->isMaintainer($aClean['iVersionId']))) + { + echo "
[id"; + echo "&iPage=".$currentPage."&iItemsPerPage=".$ItemsPerPage."'>"; + echo "Delete Image]"; + } + echo "

\n"; + +/* display page selection links */ +echo "
"; +display_page_range($currentPage, $pageRange, $totalPages, + $_SERVER['PHP_SELF']."?iItemsPerPage=".$ItemsPerPage); +echo "
"; + +apidb_footer(); + +?> diff --git a/admin/adminUsers.php b/admin/adminUsers.php new file mode 100644 index 0000000..f7861ca --- /dev/null +++ b/admin/adminUsers.php @@ -0,0 +1,145 @@ +hasPriv("admin")) + util_show_error_page_and_exit("Insufficient privileges."); + + +// we want to delete a user +if(isset($aClean['sAction']) && $aClean['sAction'] == "delete" && + is_numeric($aClean['iUserId'])) +{ + $oUser = new User($aClean['iUserId']); + $oUser->delete(); +} + + +// search form +echo html_frame_start("Users Management","400","",0); + +$aClean['sSearch'] = isset($aClean['sSearch']) ? $aClean['sSearch'] : ''; + +$sLimit100 = $sLimit200 = $sLimit500 = ''; +if ( isset($aClean['iLimit']) ) +{ + switch ($aClean['iLimit']) + { + case '100': + $sLimit100 = 'selected'; + break; + case '200': + $sLimit200 = 'selected'; + break; + case '500': + $sLimit500 = 'selected'; + break; + } +} + +$sOrder1 = $sOrder2 = $sOrder3 = ''; +if ( isset($aClean['sOrderBy']) ) +{ + switch ($aClean['sOrderBy']) + { + case 'email': + $sOrder1 = 'selected'; + break; + case 'realname': + $sOrder2 = 'selected'; + break; + case 'created': + $sOrder3 = 'selected'; + break; + } +} + +?> +
+ + + + + + + + + + + + + + + + +
Pattern + +
(leave blank to match all) +
Show first + +
Order by + +
+
+\n\n"; + echo "\n"; + echo " Real name\n"; + echo " E-mail\n"; + echo " Creation date\n"; + echo " Last connected\n"; + echo " Roles\n"; + echo " Action\n"; + echo "\n\n"; + if(is_numeric($aClean['iLimit']) && in_array($aClean['sOrderBy'],array("email","realname","created"))) + { + $sSearch = $aClean['sSearch']; + $sQuery = "SELECT * FROM user_list + WHERE realname LIKE '%?%' OR email LIKE '%?%' + ORDER BY ? + LIMIT ?"; + $hResult = query_parameters($sQuery, $sSearch, $sSearch, $aClean['sOrderBy'], + $aClean['iLimit']); + $i=0; + while($hResult && $oRow = query_fetch_object($hResult)) + { + $oUser = new User($oRow->userid); + $sAreYouSure = "Are you sure that you want to delete user ".addslashes($oUser->sRealname)." ?"; + echo "\n"; + echo " ".$oUser->sRealname."\n"; + echo " ".$oUser->sEmail."\n"; + echo " ".$oUser->sDateCreated."\n"; + echo " ".$oUser->sStamp."\n"; + echo " "; + if($oUser->hasPriv("admin")) echo "A"; + if($oUser->isMaintainer()) echo "M"; + echo " \n"; + echo " [userid."&sSearch=".$sSearch."&iLimit=".$aClean['iLimit']."&sOrderBy=".$aClean['sOrderBy']."\">edit] [userid."&sSearch=".$sSearch."&iLimit=".$aClean['iLimit']."&sOrderBy=".$aClean['sOrderBy']."&sSubmit=true\">delete]\n"; + echo "\n\n"; + } + } + echo ""; + echo html_frame_end(); +} +apidb_footer(); +?> diff --git a/admin/editAppFamily.php b/admin/editAppFamily.php new file mode 100644 index 0000000..1908692 --- /dev/null +++ b/admin/editAppFamily.php @@ -0,0 +1,60 @@ +hasPriv("admin") || $_SESSION['current']->isSuperMaintainer($aClean['iAppId']))) + util_show_error_page_and_exit("Insufficient Privileges!"); + +if(!empty($aClean['sSubmit'])) +{ + process_app_version_changes(false); + url::processForm($aClean); + $oApp = new application($aClean['iAppId']); + util_redirect_and_exit($oApp->objectMakeUrl()); +} +else +// Show the form for editing the Application Family +{ + $family = new TableVE("edit"); + + + $oApp = new Application($aClean['iAppId']); + + if(!$oApp) + { + util_show_error_page_and_exit('Application does not exist'); + } + + if($_SESSION['current']->showDebuggingInfos()) { echo "

appName: $oApp->sName

"; } + + apidb_header("Edit Application Family"); + + echo "
\n"; + + $oApp->outputEditor(""); + + echo '', "\n"; + echo '',"\n"; + echo '
', "\n"; + echo "
"; + + echo "

"; + + // URL editor + echo url::outputEditor("editAppFamily.php", NULL, $oApp); + + echo html_back_link(1,$oApp->objectMakeUrl()); +} + +apidb_footer(); +?> diff --git a/admin/editAppVersion.php b/admin/editAppVersion.php new file mode 100644 index 0000000..fe0e8bf --- /dev/null +++ b/admin/editAppVersion.php @@ -0,0 +1,63 @@ +hasPriv("admin") && !$_SESSION['current']->isMaintainer($aClean['iVersionId']) && !$_SESSION['current']->isSuperMaintainer($aClean['iAppId'])) + util_show_error_page_and_exit("Insufficient Privileges!"); + +/* process the changes the user entered into the web form */ +if(!empty($aClean['sSubmit'])) +{ + process_app_version_changes(true); + downloadurl::processForm($aClean); + url::processForm($aClean); + $oVersion = new version($aClean['iVersionId']); + util_redirect_and_exit($oVersion->objectMakeUrl()); +} else /* or display the webform for making changes */ +{ + + $oVersion = new Version($aClean['iVersionId']); + + apidb_header("Edit Application Version"); + + echo "

\n"; + + echo "
\n"; + + if($_SESSION['current']->hasPriv("admin")) + $oVersion->outputEditor(true, true); /* false = not allowing the user to modify the parent application */ + else + $oVersion->outputEditor(false, true); /* false = not allowing the user to modify the parent application */ + + echo '',"\n"; + echo '',"\n"; + echo html_table_end(); + + echo ""; + + echo "

\n"; + + /* URL editor */ + echo url::outputEditor("editAppVersion.php", $oVersion); + + /* Display some text about download url usage */ + echo "A place where this version can be downloaded for free. Other downloads, "; + echo "such as updates, should be added in the regular URL form\n"; + + /* Download URL editor */ + echo downloadurl::outputEditor($oVersion, "editAppVersion.php"); + + echo html_back_link(1,$oVersion->objectMakeUrl()); + + echo "\n"; + + apidb_footer(); +} +?> diff --git a/admin/editBundle.php b/admin/editBundle.php new file mode 100644 index 0000000..b0523e6 --- /dev/null +++ b/admin/editBundle.php @@ -0,0 +1,98 @@ +hasPriv("admin")) + util_show_error_page_and_exit(); + +function build_app_list() +{ + $hResult = query_parameters("SELECT appId, appName FROM appFamily ORDER BY appName"); + + echo "\n"; +} + +if($aClean['sCmd']) +{ + if($aClean['sCmd'] == "delete") + { + $hResult = query_parameters("DELETE FROM appBundle WHERE appId ='?' AND bundleId = '?'", + $aClean['iAppId'], $aClean['iBundleId']); + if($hResult) + addmsg("App deleted from bundle", "green"); + else + addmsg("Failed to delete app from bundle!", "red"); + } + if($aClean['sCmd'] == "add") + { + $hResult = query_parameters("INSERT INTO appBundle (bundleId, appId) VALUES". + "('?', '?')", + $aClean['iBundleId'], + $aClean['iAppId']); + if($hResult) + addmsg("App $appId added to Bundle".$aClean['iBundleId'], "green"); + } +} + + +apidb_header("Edit Application Bundle"); + +$hResult = query_parameters("SELECT bundleId, appBundle.appId, appName FROM appBundle, appFamily ". + "WHERE bundleId = '?' AND appFamily.appId = appBundle.appId", + $aClean['iBundleId']); + +echo html_frame_start("Apps in this Bundle","300",'',0); +echo "
\n\n"; + +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +if($hResult && query_num_rows($hResult)) +{ + $c = 1; + while($oRow = query_fetch_object($hResult)) + { + //set row color + if ($c % 2 == 1) { $bgcolor = 'color0'; } else { $bgcolor = 'color1'; } + + $delete_link = "[appId'>delete]"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } +} else if($hResult && !query_num_rows($hResult)) +{ + /* indicate to the user that there are no apps in this bundle at the moment */ + echo "\n"; + echo " \n"; + echo "\n"; +} + +echo "
Application Name Delete
$oRow->appName  $delete_link  
No applications in this bundle
\n\n"; +echo html_frame_end(); + +echo "
\n"; + +echo html_frame_start("Application List (double click to add)","",'',2); +build_app_list(); +echo html_frame_end(); + +echo "\n"; +echo "\n"; +echo "
\n"; + +apidb_footer(); + +?> diff --git a/admin/maintainerNotification.php b/admin/maintainerNotification.php new file mode 100644 index 0000000..99a8185 --- /dev/null +++ b/admin/maintainerNotification.php @@ -0,0 +1,61 @@ +\n"; + +$bFoundNonZero = false; +while($oRow = query_fetch_object($hResult)) +{ + $oMaintainer = new maintainer(null, $oRow); + + if($oMaintainer->iNotificationLevel != 0) + { + $bFoundNonZero = true; + echo "iMaintainerId: $oMaintainer->iMaintainerId
"; + echo "iNotificationLevel: $oMaintainer->iNotificationLevel
"; + echo "
\n"; + } +} + +if(!$bFoundNonZero) +{ + echo "No maintainers have a non-zero notification level
\n"; +} + + +echo "
\n"; +echo "
\n"; + + +// retrieve all of the maintainers +echo "Maintainers with notification iTargetLevel != 0
\n"; +$hResult = maintainer::objectGetEntries(false, false); +while($oRow = query_fetch_object($hResult)) +{ + $oMaintainer = new maintainer(null, $oRow); + + $oNotificationUpdate = $oMaintainer->fetchNotificationUpdate(); + + if($oNotificationUpdate->iTargetLevel != 0) + { + echo "iMaintainerId: $oMaintainer->iMaintainerId
\n"; + echo "iNotificationLevel: $oMaintainer->iNotificationLevel
\n"; + echo "iTargetLevel: $oNotificationUpdate->iTargetLevel
\n"; + echo "
\n"; + } +} + +apidb_footer(); + +?> \ No newline at end of file diff --git a/admin/path.php b/admin/path.php new file mode 100644 index 0000000..4ae17f9 --- /dev/null +++ b/admin/path.php @@ -0,0 +1,3 @@ + diff --git a/apidb.css b/apidb.css new file mode 100644 index 0000000..cdfb1bf --- /dev/null +++ b/apidb.css @@ -0,0 +1,108 @@ +/*******************************************************************/ +/* The following styles are used exclusively in appdb */ +/*******************************************************************/ +TD.cline { background-color: #EEEEEE; color: #000000; + text-align: center; font-weight: bold; font-size: 10pt; } + +TH.qheader { background-color: #C3C8E5; color: #555555; font-size: 10pt; } +TR.qheader { background-color: #C3C8E5; color: #555555; font-size: 10pt; } + +TABLE.bg { background-color: #FF6666; color: #FFFFFF } +TABLE.bg2 { background-color: #E0E0E0; } +TD.bg2 { background-color: #E0E0E0; } + +TD.line1 { background-color: #E7E7E7; } +TD.line2 { background-color: #C0C0C0; color: #505050; font-size: 8pt; } +TD.line3 { background-color: #6F6F6F; } +TR.line1 { background-color: #E7E7E7; } +TR.line2 { background-color: #C0C0C0; color: #505050 } +TR.line3 { background-color: #6F6F6F; } + + +TH.titlex { background-color: #BBC2E5 } +TH.title { background-color: #C0C0C0; font-weight: bold } +TD.title { background-color: #C0C0C0; font-weight: bold } +TD.btitle { background-color: #FFFFFF } + +TH.sqtitle { background-color: #C3C8E5; color: #555555 } + + +TR.buttons { background-color: #BDDAE5 } +TD.button { background-color: #BDDAE5 } +TD.button2 { background-color: #ABB2D5; } + +/* misc table styles */ +.rowtitle { background-color: black; color: white; font-weight: bold; } + +/* misc backgrounds from color name */ +.white { background-color: #FFFFFF; } + +/* query row colors */ +.color0 { background-color: #E0E0E0 } +.color1 { background-color: #C0C0C0 } +.color2 { background-color: #FFFFFF } +.color3 { background-color: #666666 } +.color4 { background-color: #999999 } + +/* Colors for supported apps table */ +.platinum {background-color: #ECECEC; } +.gold { background-color: #FFF600 } +.silver { background-color: silver; } +.bronze { background-color: #FCBA0A; } +.garbage { background-color: #999966; } + +/* box */ +.box-title { background-color: #AAAAAA; color: #FFFFFF; font-weight: bold } +.box-label { background-color: #C0C0C0 } +.box-body { background-color: #E0E0E0 } + +/* labels */ +TD.label { font-weight: bold } + +/* for inwine/intwine */ +TD.yes { color: #00B100; font-style: italic; text-align: center } +TD.no { color: #B10000; font-style: italic; text-align: center } +TD.stub { color: #0000B1; font-style: italic; text-align: center } + +/* width of the application column in the top 'X' lists on the main page */ +TD.app_name { padding:10px; width: 150px } + +/* Rating Number */ +.rating { font-family: Helvetica, Arial; font-size: 6pt; color: #333333; } + + +/* Vote Button */ +.votebutton { background-color: #666666; color: #ffffff; font-family: Helvetica, Arial; font-size: 8pt; padding: 0; } + + +/* Rate Button */ +.ratebutton { background-color: #666666; color: #ffffff; font-family: Helvetica, Arial; font-size: 8pt; padding: 0; } + + +/* Search Button */ +.searchbutton { background-color: #666666; color: #ffffff; font-family: Helvetica, Arial; font-size: 10pt; padding: 0; } + +/* Search Field */ +.searchfield { background-color: #E0E0E0; color: #666666; font-family: Helvetica, Arial; font-size: 10pt; padding: 0; } + +/* Note box */ +.note { padding: 7px; } + +/* Default div style */ +div.default_container { padding: 5px; } + +/*******************************************************************/ +/* Specific elements */ +/*******************************************************************/ + +/* Main table */ +.mainTable { padding-left: 7px; } + +/* Banner div */ +#banner { border: 1px solid black; } + +/* Editor textarea */ +#editor { height: 25em; width:700px; } + +/* zoom image overlay style */ +.zoom_overlay { position:relative; top:10px; left:10px; margin-left:-32px; padding:0px; } diff --git a/appbrowse.php b/appbrowse.php new file mode 100644 index 0000000..2a96800 --- /dev/null +++ b/appbrowse.php @@ -0,0 +1,17 @@ + diff --git a/appdbStats.php b/appdbStats.php new file mode 100644 index 0000000..0915839 --- /dev/null +++ b/appdbStats.php @@ -0,0 +1,96 @@ +\n"; + +echo html_frame_start("","60%",""); +echo "\n\n"; + +/* Display the number of users */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the active users in the last 30 days */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the active users in the last 60 days */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the active users in the last 90 days */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the inactive users */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the users who were warned and pending deletion */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the number of comments */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the number of application familes */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the number of versions */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the number of application maintainers */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the number of test reports */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +/* Display the number of images */ +echo "\n"; +echo " \n"; +echo " \n"; +echo "\n\n"; + +echo "
Users:".User::objectGetEntriesCount()."
Users active within the last 30 days:".User::active_users_within_days(30)."
Users active within the last 60 days:".User::active_users_within_days(60)."
Users active within the last 90 days:".User::active_users_within_days(90)."
Inactive users (not logged in since six months):".(User::objectGetEntriesCount()- + User::active_users_within_days(183))."
Inactive users pending deletion:".User::get_inactive_users_pending_deletion()."
Comments:".getNumberOfComments()."
Application families:".application::objectGetEntriesCount('accepted')."
Versions:".version::objectGetEntriesCount('accepted')."
Application maintainers:".Maintainer::getNumberOfMaintainers()."
Test reports:".testData::objectGetEntriescount('accepted')."
Screenshots:".screenshot::objectGetEntriesCount('accepted')."
\n\n"; + +echo "
\n"; + +echo html_frame_end(" "); +apidb_footer(); +?> diff --git a/appimage.php b/appimage.php new file mode 100644 index 0000000..00cc6c4 --- /dev/null +++ b/appimage.php @@ -0,0 +1,75 @@ +canViewImage($aClean['iId'])) + util_show_error_page_and_exit("Insufficient privileges."); + +$oScreenshot = new Screenshot($aClean['iId']); +$fImage = fopen(appdb_fullpath("data/screenshots/".$oScreenshot->sUrl), "rb"); + +/* if we can open the image we should get its last modified time and read */ +/* a few bytes from its header information and close it */ +if($fImage) +{ + $fstat_val = fstat($fImage); + $iModTime = $fstat_val['mtime']; + $sMagic = fread($fImage, 8); /* read 8 bytes from the header, that lets us idenfity the type of + image without loading it */ + fclose($fImage); /* don't leave the fopened image open */ +} + +/* identify what kind of image this is, if we can't identify it */ +/* we should report that its a bad image */ +if (strcmp("\x89PNG\r\n\x1A\n", $sMagic)==0) +{ + header("Content-Type: image/png"); +} else if (preg_match("^\xD8\xFF^", $sMagic)) { + header("Content-Type: image/jpeg"); +} else { + header("500 Bad image format"); + exit; +} + +header("Cache-Control: public"); +header("Expires: "); + +/* if the browser is asking if the file was modified since a particular date */ +/* and the date is the same that the file was modified, then we can report */ +/* that the file wasn't modified, the browser can used the cached image */ +if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && + $iModTime == pHttpDate($_SERVER['HTTP_IF_MODIFIED_SINCE'])) +{ + header("HTTP/1.0 304 Not Modified"); + exit; +} + +header("Last-Modified: ".fHttpDate($iModTime)); + +if(!$aClean['bThumbnail']) + $oScreenshot->output_screenshot(false); +else + $oScreenshot->output_screenshot(true); +?> diff --git a/application.css b/application.css new file mode 100644 index 0000000..91e29d8 --- /dev/null +++ b/application.css @@ -0,0 +1,85 @@ +;/***********************************************************************/ +/* The following styles are used for application description and notes */ +/***********************************************************************/ + +.title { font-weight: bold; } + +.subtitle { text-decoration: underline; font-style: italic; } + +/* Define to behave like "generic" quoted software input and output. */ +.code { background-color: #efefef; padding: 0.5em; border-width: 1pt; + border-style: solid; border-color: #c0c0c0; white-space: -moz-pre-wrap; + font-family: monospace; } + +/* bash shell command prompt input and output */ +.quote_terminal { background-color: #f0ece6; padding: 0.5em; border-width: 1pt; + border-style: solid; border-color: #c0c0c0; white-space: -moz-pre-wrap; + font-family: monospace; } + +/* graphical user interface input and output */ +.quote_window { background-color: #c0e0f0; padding: 0.5em; border-width: 1pt; + border-style: solid; border-color: #c0c0c0; white-space: -moz-pre-wrap; + font-family: monospace; } + +/* + Wine registry modification. + Modifying the registry is a somewhat common wine task, and other How To's already + uniquely quote registry modifications, so here is a CSS to formalize this behavior. + In practice this tag is not necessary, since, like almost everything else, registry + edits are done either via a command prompt (regedit /C foo.reg (once implemented)) + or via the regedit graphical user interface. +*/ +.quote_registry { background-color: #c6ffc6; padding: 0.5em; border-width: 1pt; + border-style: solid; border-color: #c0c0c0; white-space: -moz-pre-wrap; + font-family: monospace; } + +p { + font-family: "bitstream vera sans", "verdana", "arial", "helvetica", sans-serif; + font-size: 12px; + } +thead.historyHeader { font-weight: bold } + +table.historyTable { border: 1px; + font-family: "bitstream vera sans", "verdana", "arial", "helvetica", sans-serif; + font-size: 12px; } + +td.platinum { background-color: #ECECEC; } +td.gold { background-color: #fff600; } +td.silver { background-color: silver; } +td.bronze { background-color: #fcba0a; } +td.garbage { background-color: #999966; } + +td.platinum { background-color: #ECECEC; } +tr.gold { background-color: #fff600; } +tr.silver { background-color: silver; } +tr.bronze { background-color: #fcba0a; } +tr.garbage { background-color: #999966; } +tr.warning { background-color: #ff3333; } /* novascotia salmon */ +tr.howto { background-color: green; } +tr.defaultnote { background-color: #0066CC; } /* mid-light blue */ +tr.notetitle { background-color: #cccccc; font-weight: bold; } +/* classes for the version info pane */ +/* version info pane is the right hand pane at the top of the version page */ +div.version_info_pane p { margin:0px; } +div.info_container { margin:6px; border: 1px solid; } +div.info_contents { padding:10px; background-color: #eee; } +div.title_class { font-weight: bold; border-bottom: 1px solid; padding: 4px; + font-size: 140%; background-color: #ddd; } + +/* Classes for a note box */ +div.note_container { margin:6px; border: 1px solid; } +div.note_body { padding: 10px; background-color: #ffe732; } +div.note_title { font-weight: bold; border-bottom: 1px solid; padding: 4px; + font-size: 140%; background-color: #ffc004; } + +/* Boxes for session notes, as used by addmsg() */ +div.session_note { border: 1px solid; margin-bottom: 5px;} + +/* classes for the main page */ +div.rating_header { padding: 8px; } +div.rating_title { padding-bottom: 4px; font-weight: bold; font-size: 160%; } +div.topx_style { padding:7px; margin:6px; border:2px solid; } +div.imgarea { text-align:center; text-align:center; + margin-top:0px; + margin-bottom:0px; + padding:0px;} \ No newline at end of file diff --git a/appview.php b/appview.php new file mode 100644 index 0000000..dc2e1f7 --- /dev/null +++ b/appview.php @@ -0,0 +1,39 @@ +objectGetCustomTitle("view")); + + if(isset($aClean['iVersionId'])) + $oObject->display($aClean); + else + $oObject->display(); + + apidb_footer(); +} else +{ + // Oops! Called with no params, bad llamah! + util_show_error_page_and_exit('Page Called with No Params!'); +} + +?> diff --git a/comment_body.php b/comment_body.php new file mode 100644 index 0000000..a4e0cbe --- /dev/null +++ b/comment_body.php @@ -0,0 +1,9 @@ + diff --git a/commentview.php b/commentview.php new file mode 100644 index 0000000..e25774d --- /dev/null +++ b/commentview.php @@ -0,0 +1,26 @@ + diff --git a/contact.php b/contact.php new file mode 100644 index 0000000..06757c6 --- /dev/null +++ b/contact.php @@ -0,0 +1,157 @@ +iUserId); + +/* Restrict error to logged-in users */ +if(!$oUser->isLoggedIn()) +{ + login_form(); + exit; +} + +$oRecipient = null; +$sRecipientText = ''; +$iRecipientId = null; +$sRecipientGroup = getInput('sRecipientGroup', $aClean); +$sRecipients = ''; + +if($sRecipientGroup) +{ + if(!$oUser->hasPriv('admin')) + util_show_error_page_and_exit("Only admins can do this"); + + switch($sRecipientGroup) + { + case 'maintainers': + $sRecipientText = 'all maintainers'; + $sRecipients = maintainer::getSubmitterEmails(); + if($sRecipients === FALSE) + util_show_error_page_and_exit("Failed to get list of maintainers"); + break; + + default: + util_show_error_page_and_exit("Invalid recipient group"); + } +} else +{ + $oRecipient = new User($aClean['iRecipientId']); + $iRecipientId = $oRecipient->iUserId; + $sRecipients = $oRecipient->sEmail; + + if(!User::exists($oRecipient->sEmail)) + util_show_error_page_and_exit("User not found"); + + $sRecipientText = $oRecipient->sRealname; +} + +/* Check for errors */ +if((!$aClean['sMessage'] || !$aClean['sSubject']) && $aClean['sSubmit']) +{ + $error = "Please enter both a subject and a ". + "message."; + $aClean['sSubmit'] = ""; +} + +/* Display the feedback form if nothing else is specified */ +if(!$aClean['sSubmit']) +{ + apidb_header("E-mail $sRecipientText"); + echo ' '; + echo html_frame_start("Composer",400,"",0); + + echo $error; + echo "
"; + + /* User manager */ + if($_SESSION['current']->hasPriv("admin") && $oRecipient) + { + echo "

iUserId."&sSearch=Administrator&iLimit". + "=100&sOrderBy=email\">User manager

"; + } + + if($oRecipient) + { + echo "

iUserId}&sTitle=Maintained+Apps\">Maintained apps"; + } + + echo "

E-mail $sRecipientText.

"; + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetBorder(0); + $oTable->SetCellPadding(2); + $oTable->SetCellSpacing(2); + + $oTableRow = new TableRow(); + $oTableRow->SetClass("color4"); + $oTableRow->AddTextCell("Subject"); + $oTableCell = new TableCell(""); + $oTableRow->AddCell($oTableCell); + $oTable->AddRow($oTableRow); + + $oTableRow = new TableRow(); + $oTableRow->SetClass("color4"); + $oTableCell = new TableCell("Message"); + $oTableCell->SetValign("top"); + $oTableRow->AddCell($oTableCell); + $oTableCell = new TableCell(""); + $oTableRow->AddCell($oTableCell); + $oTable->AddRow($oTableRow); + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell(""); + $oTableRow->AddTextCell(""); + $oTable->AddRow($oTableRow); + + // output the table + echo $oTable->GetString(); + + echo ""; + + echo ""; + + echo "
\n"; + + echo html_frame_end(" "); + +} else if ($aClean['sSubject'] && $aClean['sMessage']) +{ + if($oRecipient) + { + $sSubjectRe = $aClean['sSubject']; + if(substr($sSubjectRe, 0, 4) != "Re: ") + $sSubjectRe = "Re: $sSubjectRe"; + + $sSubjectRe = urlencode($sSubjectRe); + + $sMsg = "The following message was sent to you from $oUser->sRealname "; + $sMsg .= "through the Wine AppDB contact form.\nTo Reply, visit "; + $sMsg .= APPDB_ROOT."contact.php?iRecipientId=$oUser->iUserId&sSubject="; + $sMsg .= $sSubjectRe."\n\n"; + $sMsg .= $aClean['sMessage']; + } else + { + $sMsg = "The following message was sent to you by the AppDB admins:\n\n"; + $sMsg .= $aClean['sMessage']; + } + + mail_appdb($sRecipients, '[PM] '.$aClean['sSubject'], $sMsg); + + util_redirect_and_exit(BASE."index.php"); +} + +?> diff --git a/cron/.htaccess b/cron/.htaccess new file mode 100644 index 0000000..717730f --- /dev/null +++ b/cron/.htaccess @@ -0,0 +1,8 @@ +Deny from all + +#Modify PHP configuration +php_value register_globals 0 +php_value short_open_tag 0 +php_value register_long_arrays 0 +php_value magic_quotes_gpc 0 + diff --git a/cron/cleanup.php b/cron/cleanup.php new file mode 100644 index 0000000..79b7173 --- /dev/null +++ b/cron/cleanup.php @@ -0,0 +1,353 @@ +#!/usr/bin/php +userid); + + /* if we get back true the user was warned and flagged as being warned */ + /* if we get back false we didn't warn the user and didn't flag the user as warned */ + /* because they have data associated with their account */ + if($oUser->warnForInactivity()) + { + $usersWarned++; + } else + { + $usersUnwarnedWithData++; + } + } + } + + /* warned >= 1 month ago */ + $hUsersToDelete = warnedSince(1); + if($hUsersToDelete) + { + while($oRow = query_fetch_object($hUsersToDelete)) + { + $oUser = new User($oRow->userid); + if(!$oUser->hasDataAssociated()) + { + $usersDeleted++; + deleteUser($oRow->userid); + } else + { + /* is the user a maintainer? if so remove their maintainer privileges */ + if($oUser->isMaintainer()) + { + Maintainer::deleteMaintainer($oUser); + } + + $usersWithData++; + } + } + } + + notifyAdminsOfCleanupExecution($usersWarned, $usersUnwarnedWithData, $usersDeleted, $usersWithData); +} + +/* Users that are unwarned and inactive since $iMonths */ +function unwarnedAndInactiveSince($iMonths) +{ + $sQuery = "SELECT userid FROM user_list WHERE DATE_SUB(CURDATE(),INTERVAL $iMonths MONTH) >= stamp AND inactivity_warned='false'"; + $hResult = query_appdb($sQuery); + return $hResult; +} + +/* users that were warned at least $iMonths ago */ +function warnedSince($iMonths) +{ + $sQuery = "SELECT userid FROM user_list WHERE DATE_SUB(CURDATE(),INTERVAL $iMonths MONTH) >= inactivity_warn_stamp "; + $sQuery .= "AND inactivity_warned='true'"; + $hResult = query_appdb($sQuery); + return $hResult; +} + +function deleteUser($iUserId) +{ + $oUser = new User($iUserId); + warnUserDeleted($oUser->sEmail); + $oUser->delete(); + echo "user ".$oUser->sEmail." deleted.\n"; +} + +function warnUserDeleted($sEmail) +{ + $sSubject = "Warning: account removed"; + $sMsg = "You didn't log in in the past seven months to the AppDB.\r\n"; + $sMsg .= "As you don't have any data associated to your account we have removed it.\r\n"; + $sMsg .= "Please feel free to recreate an account anytime.\r\n"; + + mail_appdb($sEmail, $sSubject, $sMsg); +} + +function notifyAdminsOfCleanupStart() +{ + global $sEmailSubject; + + $sSubject = $sEmailSubject."Cleanup script starting\r\n"; + $sMsg = "Appdb cleanup cron script started.\r\n"; + $sEmail = User::get_notify_email_address_list(null, null); /* get list admins */ + if($sEmail) + mail_appdb($sEmail, $sSubject, $sMsg); +} + +/* email all admins that the appdb cleanup script is executing */ +/* so we admins have some visibility into the background cleanup */ +/* events of the appdb */ +function notifyAdminsOfCleanupExecution($usersWarned, $usersUnwarnedWithData, $usersDeleted, $usersWithData) +{ + global $sEmailSubject; + + $warnedUsers = User::get_inactive_users_pending_deletion(); + + $sSubject = $sEmailSubject."Inactive users\r\n"; + $sMsg = "Appdb inactive users cleanup executed.\r\n"; + $sMsg .= "Status\r\n"; + $sMsg .= "--------------------------\r\n"; + $sMsg .= "Users warned:".$usersWarned."\r\n"; + $sMsg .= "Users we would warn, but don't because they have data associated:".$usersUnwarnedWithData."\r\n"; + $sMsg .= "Warned users pending deletion:".$warnedUsers."\r\n"; + $sMsg .= "Users deleted:".$usersDeleted."\r\n"; + $sMsg .= "Users pending deletion but have appdb data:".$usersWithData."\r\n"; + $sEmail = User::get_notify_email_address_list(null, null); /* get list admins */ + if($sEmail) + mail_appdb($sEmail, $sSubject, $sMsg); +} + +/* check for and report orphaned versions in the database */ +/* we don't report anything if no orphans are found */ +function orphanVersionCheck() +{ + global $sEmailSubject; + + $sQuery = "select versionId, versionName from appVersion where appId = 0 and state != 'deleted'"; + $hResult = query_appdb($sQuery); + $found_orphans = false; + + $sMsg = "Found these orphaned versions in the database with\r\n"; + $sMsg.= "this sql command '".$sQuery."'\r\n"; + + /* don't report anything if no orphans are found */ + if(query_num_rows($hResult) == 0) + return; + + $sMsg .= "versionId/name\r\n"; + while($oRow = query_fetch_object($hResult)) + { + $sMsg .= $oRow->versionId."/".$oRow->versionName."\r\n"; + } + + $sSubject = $sEmailSubject."Orphan version cleanup\r\n"; + + $sEmail = User::get_notify_email_address_list(null, null); /* get list admins */ + if($sEmail) + mail_appdb($sEmail, $sSubject, $sMsg); +} + +// report the database error log entries to the mailing list +function reportErrorLogEntries() +{ + global $sEmailSubject; + error_log::mail_admins_error_log($sEmailSubject); + error_log::flush(); +} + +// returns an array of iScreenshotIds of screenshots that are +// missing their files +function getMissingScreenshotArray() +{ + $aMissingScreenshotIds = array(); + + // retrieve all screenshots, not queued, not rejected + $hResult = Screenshot::objectGetEntries(false, false); + + // go through each screenshot + while($oRow = query_fetch_object($hResult)) + { + $iScreenshotId = $oRow->id; + $oScreenshot = new Screenshot($iScreenshotId); + + // load the screenshot and thumbnail + $oScreenshot->load_image(true); + $oScreenshot->load_image(false); + + // are the screenshot and thumbnail images not loaded? if so + // add this screenshot id to the array + if(!$oScreenshot->oScreenshotImage->isLoaded() && + !$oScreenshot->oThumbnailImage->isLoaded()) + { + // add the screenshot id to the array + $aMissingScreenshotIds[] = $iScreenshotId; + } + } + + return $aMissingScreenshotIds; +} + +function removeScreenshotsWithMissingFiles() +{ + global $sEmailSubject; + + $aMissingScreenshotIds = getMissingScreenshotArray(); + + if(sizeof($aMissingScreenshotIds)) + { + $sPlural = (sizeof($aMissingScreenshotIds) == 1) ? "" : "s"; + // build the email to admins about what we are doing + $sMsg = "Found ".count($aMissingScreenshotIds)." screenshot$sPlural with missing files.\r\n"; + + if($sPlural) + $sMsg.= "Deleting these screenshots.\r\n"; + else + $sMsgm.= "Deleting it.\r\n"; + + // add the screenshot ids to the email so we can see which screenshots are + // going to be deleted + $sMsg.="\r\n"; + $sMsg.="Screenshot ID$sPlural:\r\n"; + foreach($aMissingScreenshotIds as $iScreenshotId) + { + $sMsg.=$iScreenshotId."\r\n"; + } + } else + { + $sMsg = "No screenshot entries with missing files were found.\r\n"; + } + + $sSubject = $sEmailSubject."Missing screenshot cleanup\r\n"; + + $sEmail = User::get_notify_email_address_list(null, null); /* get list admins */ + if($sEmail) + mail_appdb($sEmail, $sSubject, $sMsg); + + // log in as admin user with user id 1000 + // NOTE: this is a bit of a hack but we need admin + // access to delete these screenshots + $oUser = new User(); + $oUser->iUserId = 1000; + $_SESSION['current'] = $oUser; + + // remove the screenshots with missing files + foreach($aMissingScreenshotIds as $iScreenshotId) + { + $oScreenshot = new Screenshot($iScreenshotId); + $oScreenshot->delete(); // delete the screenshot + } + + // log out as user + $oUser->logout(); +} + +/* check and notify maintainers about data they have pending in their queues */ +/* if they don't process the data soon enough we'll strip them of their maintainer */ +/* status since they aren't really maintaining the application/version */ +function maintainerCheck() +{ + maintainer::notifyMaintainersOfQueuedData(); +} + +/* remove votes for versions that have been deleted */ +function cleanupVotes() +{ + $hResult = mysql_query("SELECT appVotes.* FROM appVotes,appVersion WHERE + appVotes.versionId = appVersion.versionId + AND appVersion.state = 'deleted'"); + + if(!$hResult) + return; + + $iDeleted = 0; + $iFailed = 0; + + while($oRow = mysql_fetch_object($hResult)) + { + $oVote = new vote(null, $oRow); + if($oVote->delete()) + $iDeleted++; + else + $iFailed++; + } + + $sEmails = user::get_notify_email_address_list(null, null); // only admins + + if($sEmails) + { + global $sEmailSubject; + $sSubject = $sEmailSubject . 'Vote Cleanup'; + $sPlural = ($iDeleted == 1) ? '' : 's'; + $sMsg = "Removed $iDeleted vote$sPlural cast for deleted versions\n"; + if($iFailed) + { + $sPlural = ($iFailed == 1) ? '' : 's'; + $sMsg .= "WARNING: Failed to delete $iFailed vote$sPlural\n"; + } + mail_appdb($sEmails, $sSubject, $sMsg); + } +} + +function updateRatings() +{ + $hResult = query_parameters("SELECT * FROM appVersion"); + + if(!$hResult) + return; + + while($oRow = mysql_fetch_object($hResult)) + { + $oVersion = new version(0, $oRow); + $oVersion->updateRatingInfo(); + } +} + +?> diff --git a/cron/path.php b/cron/path.php new file mode 100644 index 0000000..4ae17f9 --- /dev/null +++ b/cron/path.php @@ -0,0 +1,3 @@ + diff --git a/data/README b/data/README new file mode 100644 index 0000000..22229b1 --- /dev/null +++ b/data/README @@ -0,0 +1 @@ +Lowest level data directory diff --git a/data/screenshots/README b/data/screenshots/README new file mode 100644 index 0000000..aa49a37 --- /dev/null +++ b/data/screenshots/README @@ -0,0 +1 @@ +Scaled and watermarked screenshots are kept in here diff --git a/data/screenshots/originals/README b/data/screenshots/originals/README new file mode 100644 index 0000000..995293d --- /dev/null +++ b/data/screenshots/originals/README @@ -0,0 +1,3 @@ +Original screenshots are kept in here. This allows us to regenerate scaled +screenshots at any time and is useful when migrating from GD 1.X to GD 2.X as GD +1.X messes up the colors on certain images. diff --git a/data/screenshots/thumbnails/README b/data/screenshots/thumbnails/README new file mode 100644 index 0000000..eb27f52 --- /dev/null +++ b/data/screenshots/thumbnails/README @@ -0,0 +1,3 @@ +Thumbnails of the scaled, watermarked images are kept in here. Using thumbnails +reduces our overall bandwidth because we only send the full image if the user +explicitly displays it. diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..78b6d9b Binary files /dev/null and b/favicon.ico differ diff --git a/help/.cvsignore b/help/.cvsignore new file mode 100644 index 0000000..55d2fba --- /dev/null +++ b/help/.cvsignore @@ -0,0 +1,2 @@ +stderr + diff --git a/help/appdb_faq.help b/help/appdb_faq.help new file mode 100644 index 0000000..bc66693 --- /dev/null +++ b/help/appdb_faq.help @@ -0,0 +1,87 @@ + + +

Application Database FAQ

+ +

This FAQ answers questions related to the usage of the +Application Database.

+ +
    + +

    Q: What is the Application Database?

    +
    +

    A: The Application Database is a repository for +Windows application compatibility information with Wine. +In particular it provides the following information:
    +(see the Visual FoxPro entry for an +example)

    +

      +
    • Whether a given application works at all with Wine.
    • +
    • If it is partially working, then which areas of the application + have problems.
    • +
    • How to install and get that application working best.
    • +
    +

    And if the Windows application you want most to use with Wine does not +work, it lets you vote for it to bring it to the attention of Wine +developers.

    +
    + +

    Q: What is Wine?

    +
    +

    A:Think of Wine as a Windows compatibility layer. Wine does not require +Microsoft Windows, as it is a completely alternative implementation +consisting of 100% Microsoft-free code, but it can optionally use +native system DLLs if they are available. Wine provides both a development +toolkit (Winelib) for porting Windows sources to Unix and a program loader, +allowing many unmodified Windows binaries to run on x86-based Unixes, including +Linux, +FreeBSD, and +Solaris.

    + +

    More information can be found at the +Wine FAQ.

    +

    + +

    Q: What are the benefits of this Application Database?

    +
    +

    A: The Application database benefits both Wine developers and users. +It lets Wine developers know which applications the community most wants to +see working. And it lets Wine user know beforehand if their application will +work in Wine, and also what are the tricks to get it working best.

    +

    + +

    Q: How does a new application get added to the database?

    +
    +

    A: Any registered user can submit an application. Use the Submit App link in the AppDB sidebar to add an entry; it will be processed by an admin before becoming visible to all users. You can make changes to your queued entries by visiting the Your Queued Items page.

    +
    + +

    Q: How can I submit screenshots?

    +
    +

    A: We love to hear from our users. Send those helpful screenshots by clicking on any screenshot image you will see in the specific version page of the application you want to add a screenshot for. If you are not a maintainer, your screenshot will be reviewed and will then be added to the database.

    +
    + +

    Q: How can I submit how-to's?

    +
    +

    A:If you are not a maintainer, you can't create new official How-to's. So the best way to proceed is to post your How-to as a comment in the specific version page of the application of interest. A maintainer might then choose to add your How-to as an official How-to for this database entry.

    +
    + + +

    Q: How do I become an Application Database maintainer?

    +
    +

    A: Pretty much anyone supporting Wine is welcome (begged?) to be an application maintainer. +Simply click on the button you will find in the application overview or specific version page to send your request. An administrator will then review your proposal and add you to the maintainer's team for this application or version. Once we have a community of maintainers, we hope that community will further refine the policies and procedures.

    +
    + + +

    Q: What is the difference between a super maintainer and a maintainer?

    +
    +

    A: A super maintainer maintains an application and all its versions. A maintainer maintains only one specific version of an application.

    +
    + +

    Q: What is meant by the term ‘vendor’?

    +
    +

    A: The vendor is the developer of an application.

    +
    +
+ +If you have more questions you would like to add to our FAQ, please contact us +at appdb@winehq.org. diff --git a/help/generic.help b/help/generic.help new file mode 100644 index 0000000..64afbb2 --- /dev/null +++ b/help/generic.help @@ -0,0 +1,56 @@ + + +
This is meant as a general guide in case an AppDB entry +for a certain program hasn't been created.
+ +
    + +
  1. Make sure your Wine release is recent.

    + +

    +
  2. +
  3. Run your program by changing into the directory where it is located, and then type 'wine yourprogram.exe'. +
    Alternately your file manager should know to open .exe files with 'wine').

  4. + +
  5. If there is an error about missing files, or it does not start at all, make sure you are in the directory where it was installed.

  6. + +
  7. Many newer games contain copy protection, which is sometimes not supported in Wine.
    Third party applications may be able to circumvent this, + when this is required an application cannot be rated higher than Gold.

  8. + +
  9. In case of failure, try different builtin, native DLL settings: +Run Wine with 'WINEDEBUG=+loaddll wine yourprogram.exe' to find out which +DLLs are loaded as native or builtin. +
    Then make sure appropriate native versions are in the +c:\windows\system32 directory as configured in winecfg's DLL overrides tab. +
    There are four options you can choose from when setting +dll overrides.

    + +

    +(native, builtin)
    +(builtin, native)
    +(native)
    +(builtin)
    +
    +
  10. +
  11. For sound problems, run ‘winecfg’ and look at the audio tab.

  12. + +
  13. In case of persisting failure, you may want to read over the +Wine Documentation +and you may also want to read the +Wine FAQ.

  14. + +
  15. The Wine 'Getting Help' page shows the current methods of getting help with Wine.

  16. + +
  17. If you have more questions, please contact us +at appdb@winehq.org.

  18. + +
+ +

 

diff --git a/help/index.php b/help/index.php new file mode 100644 index 0000000..f366671 --- /dev/null +++ b/help/index.php @@ -0,0 +1,105 @@ +\n"; + + echo "

Providing all the help you need 24x7


\n"; + + echo "
    \n"; + + // read dir + $files = array(); + $d = opendir($help_path); + while($entry = readdir($d)) + { + array_push($files, $entry); + } + closedir($d); + + // sort dir + sort($files); + + // display dir + while (list($key,$file) = each($files)) + { + if(!ereg("(.+)\\.help$", $file, $arr)) + continue; + + $id = $arr[1]; + $title = get_help_title("$help_path/$file"); + + echo "
  • $title

  • \n"; + } + + echo "

\n"; + + echo "

Need more help? Contact us at ".APPDB_OWNER_EMAIL."

\n"; + + echo "\n"; + + apidb_footer(); +} + +function display_help ($topic) +{ + global $help_path; + + $file = "$help_path/$topic.help"; + $title = get_help_title($file); + + if(! $title) { + $title = "Help on $topic"; + } + + apidb_header($title); + echo "

\n"; + if(file_exists($file)) { + include($file); + } else { + echo "

No help available on that topic

\n"; + } + echo "

\n"; + + apidb_footer(); +} + +function get_help_title ($file) +{ + $fp = @fopen($file, "r"); + if(!$fp) + return null; + + $line = fgets($fp, 1024); + if(!$line) + return null; + + $line = trim($line); + + if(eregi("^$", $line, $arr)) + { + return $arr[1]; + } + return "Internal Error: missing title"; +} + +?> diff --git a/help/maintainer.help b/help/maintainer.help new file mode 100644 index 0000000..15c4247 --- /dev/null +++ b/help/maintainer.help @@ -0,0 +1,21 @@ + + +

Maintainers

+ +

+Information on what a maintainer is and why they are important to the appdb. +

+ +

+Maintainers are privileged users who have the ability to administrate applications and versions. Maintainers typically use the +applications and versions they maintain on a daily or weekely basis and test them with each new version of Wine that is +released. They also respond to forum posts for their applications/versions and review and process test results and +screenshots that users submit. Please see the maintainer's guidelines +for more information on the kinds of things a maintainer has stewardship over. +

+Maintainers are crucial to the usefulness of the AppDB as they ensure that information is kept up-to-date. With the large +number of applications and versions present in the AppDB today it would be a difficult task for the small number of AppDB +admins to try to perform this task. +

+See the AppDB FAQ for the difference between a maintainer and a super +maintainer. diff --git a/help/maintainer_guidelines.help b/help/maintainer_guidelines.help new file mode 100644 index 0000000..6293057 --- /dev/null +++ b/help/maintainer_guidelines.help @@ -0,0 +1,109 @@ + + +

Maintainers Guidelines

+ +

+This page gives information on how to maintain an application once you are an application maintainer. If you are looking for information on how to become an application maintainer, this topic is covered in the FAQ. +

+ +

+Becoming a (super) maintainer gives you certain rights on the Application Database. However as you may know, with great power, comes great responsibility... +

+ +

An application maintainer is someone who runs the application regularly and who is willing to be active in reporting regressions with newer versions of Wine and to help other users run this application under Wine.

+ +You are expected to: +
    +
  • Keep the application comments clean, all stale data should be removed
  • +
  • Be an active user of that application and version
  • +
  • Keep up-to-date with all Wine releases, if there are regressions they should filed as bugs in Bugzilla if there are not bugs already filed.
  • +
+ +You will: +
    +
  • Receive an email when a comment is posted or deleted for the application or the application information is modified
  • +
  • Be able to modify all aspects of your application(s) and version(s), including the description, screenshots, HOWTOs, notes, comments, etc.
  • +
+ +
+ +

Application overview page guidelines

+

N.B. Only super maintainers can change the general description of an application.
+You can edit an application overview page by clicking on the "Edit Application" button in the application overview page. You will be then presented with a form whose fields are explained thereafter. +

    +
  • +Application name should be checked against official application name and should not contain the vendor's name. +
  • +
  • +Application vendor should be set correctly. If the vendor is missing, please contact appdb@winehq.org. +
  • +
  • +Keywords are used by the search engine. You don't need to repeat the application's name but you are encouraged to provide some keywords in this field. +
  • +
  • +Description should describe the application in a general manner (what it does). The Wine and version specific considerations go in version-specific pages (described below). If you want to add more than a short sentence, please add a carriage return after the first sentence as it will be used when showing the application summary in the search engine, top-25 page and so on. +
  • +
  • +Webpage should contain the home page for this application. Please remember that a URL starts with http://. +
  • +
+ + +

Version page guidelines

+

+You can edit a version page by clicking on the "Edit Version" button in any version page for which you are a (super) maintainer. You will then be presented with a form whose fields are explained thereafter. +

    +
  • +Version name should be checked against official version name. However if you feel that two minor revisions of an application will share the same problems or success, you are encouraged to use wildcards in the version number to avoid cluttering the database with hundreds of versions. For example if you know that Adobe Acrobat 6.0, 6.01 and 6.1 are about the same application, just choose 6.x as a version name. You can however use the full version name in an history table in the description field (see below). +
  • +
  • +Description should describe the application version and not be a repetition of the application description. Please use a short sentence as the first line of your description to describe what this version is, and then add a carriage return after this first sentence as it will be used when showing version summary, in the application page for example.
    +
  • +
  • +Rating lets you rate how this version ran with the latest Wine version you tested. For rating definitions, please see this page. +
  • +
  • +Release is the latest release of Wine you tested this version with. +
  • +
+ +

Additional URLs guidelines

+

+In both application and version editing pages you can add additional URLs. These URLs can, for example, help the user find native alternatives for this application (in application overview page) or find specific dlls (in version page). +

+ +

Screenshots guidelines

+

+As a maintainer you are encouraged to provide screenshots for the versions you tested under Wine. To add a screenshot, simply click on the screenshot thumbnail in the version page. +

+ +

Notes guidelines

+

+In the version page you can add, edit and delete notes for the versions you maintain. Just click on the "Add note" button. +

+ + +

HOWTO guidelines

+

+HOWTOs are just a special kind of notes. You can provide step-by-step explanations on how to install or run a specific version of the current application here. Please try to keep HOWTOs up to date (for example some steps might no longer be needed if using a more recent version of Wine). +

+ +

Warnings guidelines

+

+Warnings are just a special kind of note. Warnings appear in red to catch the attention of the reader. They can be used to warning users against potential data corruption for instance. Please keep the warning up-to-date, especially if it is not true when using a recent Wine version (in this case you might choose to keep the warning and tell users that since Wine X.Y, this has been fixed). +

+ +

Comments guidelines

+

+As a maintainer you are entitled to delete comments. Use this feature wisely and always explain why you deleted a comment. If a comment is useless or is not true anymore, you can safely delete it. Whenever you can, extract how-tos, other peoples tests (for your test history table for example) from the comments and put it in your versions page and how-to notes. +

+If users paste large amounts of debug/crash output from wine, it might be a good idea to delete their comment and depending on whether or not a bug report as been filed for the problem, ask them to file a report and attach the information. +

+ + +

Using the HTML editor

+

+The HTML editor allows users of the AppDB to write richer descriptions, guides or warnings by providing a WYSIWYG HTML editor. The HTML editor can be disabled in your Preferences which will allow you to edit the html source of various fields. +

+
+

If you have additional questions, please do not hesitate to contact us on appdb@winehq.org.

diff --git a/help/maintainer_ratings.help b/help/maintainer_ratings.help new file mode 100644 index 0000000..8eabe94 --- /dev/null +++ b/help/maintainer_ratings.help @@ -0,0 +1,47 @@ + + +

Maintainer Rating Definitions

+ +

+The Application Database features a maintainer rating system that allows you to see +which applications work best in Wine. This rating system is designed to assist +users by giving a rating based on an ‘expert's’ experience. +

+ +
    + +
  • Platinum + +

    +An application can be rated as Platinum if it installs and runs flawlessly ‘out of the box’. No changes required in winecfg. +

    +
  • +
  • Gold + +

    +Application works flawlessly with some DLL overrides, other settings or third party software. +

    +
  • +
  • Silver + +

    +Application works excellently for ‘normal’ use; a game works fine in single-player but not +in multi-player, Windows Media Player works fine as a plug-in and stand-alone player, but cannot handle DRM etc. +

    +
  • + +
  • Bronze + +

    +Application works, but it has some issues, even for normal use; a game may not redraw properly or display fonts in wrong colours, be much slower than it should etc. +

    +
  • +
  • Garbage + +

    +An application gets this rating if it cannot be used for the purpose it was designed for. +There should be at least one bug report in Bugzilla if it gets this rating. +Application cannot be installed, does not start, or starts but has so many errors that it is nearly impossible to use it. +

    +
  • +
diff --git a/help/path.php b/help/path.php new file mode 100644 index 0000000..4ae17f9 --- /dev/null +++ b/help/path.php @@ -0,0 +1,3 @@ + diff --git a/help/privacy.help b/help/privacy.help new file mode 100644 index 0000000..a30f97e --- /dev/null +++ b/help/privacy.help @@ -0,0 +1,38 @@ + + +

Application Database Privacy Policy

+ +

+WineHQ is dedicated to the privacy of its users.
+

    + Whatever specific information you give to us will be used only to enable user + specific features of the Application Database. We will give your information + to no third parties, nor will we send you email that you have not requested. +
+

+ +

+Cookies +

    + The Application Database uses cookies only to preserve login information in your web browser. + Advertisers and other companies do not have access to the AppDB's cookies. +
+

+ +

+Changes to this Privacy Policy
+

    + We may amend this policy from time to time. If we make any + substantial changes in the way we use your personal information we + will notify you by posting a prominent announcement on our pages. +
+

+ +

+Questions or Suggestions
+

    + If you have questions or suggestions, feel free to contact us at + appdb@winehq.org +
+

+ diff --git a/help/voting.help b/help/voting.help new file mode 100644 index 0000000..ae48bf2 --- /dev/null +++ b/help/voting.help @@ -0,0 +1,39 @@ + + +

Application Voting System Help

+ +

+The Application Database features a voting system that allows you to pick which 3 application versions +you would MOST like to see running in Wine. +

+ +

Step by Step Help on Voting

+
    + +
  1. Log in to the Application Database.

  2. + +
  3. Browse to the application version you wish to add to your vote list.

  4. + +
  5. In the table showing name, license, rating etc., click on ‘Vote’.

  6. + +
  7. Select the slots you wish to use, and press ‘Submit’

  8. + +
  9. Done!

  10. + +
+ + +

Voting System Notes

+ +
    + +
  • Please vote for applications which will benefit the + community. Don't vote for applications that are known to be working well. + We know Solitaire works. Voting for it would not make much sense.
  • + +
  • You can clear your vote at any time. Browse to any application + version, select ‘Vote’ from the table showing name, license, rating etc., then choose the slots you wish to clear and press ‘Delete’.

  • + +
+ +

 

diff --git a/images/appdb_montage.jpg b/images/appdb_montage.jpg new file mode 100644 index 0000000..f9cc46a Binary files /dev/null and b/images/appdb_montage.jpg differ diff --git a/images/back.gif b/images/back.gif new file mode 100644 index 0000000..abb3072 Binary files /dev/null and b/images/back.gif differ diff --git a/images/bg.jpg b/images/bg.jpg new file mode 100644 index 0000000..16bb0b5 Binary files /dev/null and b/images/bg.jpg differ diff --git a/images/bk.gif b/images/bk.gif new file mode 100644 index 0000000..743ac5f Binary files /dev/null and b/images/bk.gif differ diff --git a/images/blank.gif b/images/blank.gif new file mode 100644 index 0000000..c080147 Binary files /dev/null and b/images/blank.gif differ diff --git a/images/compare.gif b/images/compare.gif new file mode 100644 index 0000000..b2d6268 Binary files /dev/null and b/images/compare.gif differ diff --git a/images/cw_logo_sm.png b/images/cw_logo_sm.png new file mode 100644 index 0000000..3099535 Binary files /dev/null and b/images/cw_logo_sm.png differ diff --git a/images/go.gif b/images/go.gif new file mode 100644 index 0000000..60ec749 Binary files /dev/null and b/images/go.gif differ diff --git a/images/grey_pixel.gif b/images/grey_pixel.gif new file mode 100644 index 0000000..bf677fd Binary files /dev/null and b/images/grey_pixel.gif differ diff --git a/images/list.gif b/images/list.gif new file mode 100644 index 0000000..54b1256 Binary files /dev/null and b/images/list.gif differ diff --git a/images/next.gif b/images/next.gif new file mode 100644 index 0000000..bbe694e Binary files /dev/null and b/images/next.gif differ diff --git a/images/no_screenshot.png b/images/no_screenshot.png new file mode 100644 index 0000000..dae61cd Binary files /dev/null and b/images/no_screenshot.png differ diff --git a/images/remove.gif b/images/remove.gif new file mode 100644 index 0000000..13a3066 Binary files /dev/null and b/images/remove.gif differ diff --git a/images/s0.gif b/images/s0.gif new file mode 100644 index 0000000..21b6be5 Binary files /dev/null and b/images/s0.gif differ diff --git a/images/s1.gif b/images/s1.gif new file mode 100644 index 0000000..0bf6bfb Binary files /dev/null and b/images/s1.gif differ diff --git a/images/s2.gif b/images/s2.gif new file mode 100644 index 0000000..1205878 Binary files /dev/null and b/images/s2.gif differ diff --git a/images/side_menu_bg.png b/images/side_menu_bg.png new file mode 100644 index 0000000..c8cbcc0 Binary files /dev/null and b/images/side_menu_bg.png differ diff --git a/images/side_menu_bot.png b/images/side_menu_bot.png new file mode 100644 index 0000000..8bc9b5d Binary files /dev/null and b/images/side_menu_bot.png differ diff --git a/images/side_menu_top.png b/images/side_menu_top.png new file mode 100644 index 0000000..047c4c0 Binary files /dev/null and b/images/side_menu_top.png differ diff --git a/images/tab_h.png b/images/tab_h.png new file mode 100644 index 0000000..59620cd Binary files /dev/null and b/images/tab_h.png differ diff --git a/images/tab_s.png b/images/tab_s.png new file mode 100644 index 0000000..54d367b Binary files /dev/null and b/images/tab_s.png differ diff --git a/images/tab_u.png b/images/tab_u.png new file mode 100644 index 0000000..ff84b7a Binary files /dev/null and b/images/tab_u.png differ diff --git a/images/tree.gif b/images/tree.gif new file mode 100644 index 0000000..e4e818c Binary files /dev/null and b/images/tree.gif differ diff --git a/images/w0.gif b/images/w0.gif new file mode 100644 index 0000000..ab10835 Binary files /dev/null and b/images/w0.gif differ diff --git a/images/w1.gif b/images/w1.gif new file mode 100644 index 0000000..70ea8f2 Binary files /dev/null and b/images/w1.gif differ diff --git a/images/watermark.png b/images/watermark.png new file mode 100644 index 0000000..5e3770c Binary files /dev/null and b/images/watermark.png differ diff --git a/images/winehq_logo_16.png b/images/winehq_logo_16.png new file mode 100644 index 0000000..83d2c4c Binary files /dev/null and b/images/winehq_logo_16.png differ diff --git a/images/winehq_logo_glass_sm.png b/images/winehq_logo_glass_sm.png new file mode 100644 index 0000000..949334b Binary files /dev/null and b/images/winehq_logo_glass_sm.png differ diff --git a/images/winehq_logo_text.png b/images/winehq_logo_text.png new file mode 100644 index 0000000..29b6ecb Binary files /dev/null and b/images/winehq_logo_text.png differ diff --git a/images/xinha-red-95.png b/images/xinha-red-95.png new file mode 100644 index 0000000..71e6a77 Binary files /dev/null and b/images/xinha-red-95.png differ diff --git a/images/xmag_32.png b/images/xmag_32.png new file mode 100644 index 0000000..af1e065 Binary files /dev/null and b/images/xmag_32.png differ diff --git a/include/.cvsignore b/include/.cvsignore new file mode 100644 index 0000000..ba483ce --- /dev/null +++ b/include/.cvsignore @@ -0,0 +1,2 @@ +config.php +stderr diff --git a/include/.htaccess b/include/.htaccess new file mode 100644 index 0000000..8d2f256 --- /dev/null +++ b/include/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/include/appData.php b/include/appData.php new file mode 100644 index 0000000..91c0e58 --- /dev/null +++ b/include/appData.php @@ -0,0 +1,628 @@ +iSubmitterId = $oObject->iSubmitterId; + $this->sDescription = $oObject->sDescription; + $this->iAppId = $oObject->iAppId; + $this->iVersionId = $oObject->iVersionId; + $this->sSubmitTime = $oObject->sSubmitTime; + $this->iId = $iId; + $this->bQueued = $oObject->bQueued; + return; + } + + if(!$oRow) + { + $hResult = query_parameters("SELECT * FROM appData WHERE id = '?'", $iId); + $oRow = query_fetch_object($hResult); + } + + if($oRow) + { + $this->iSubmitterId = $oRow->submitterId; + $this->iAppId = $oRow->appId; + $this->iVersionId = $oRow->versionId; + $this->sSubmitTime = $oRow->submitTime; + $this->iId = $iId; + $this->bQueued = ($oRow->sState == 'accepted') ? false : true; + $this->sDescription = $oRow->description; + } + } + + function purge() + { + return $this->delete(); + } + + function delete() + { + if(!$this->canEdit()) + return FALSE; + + $sQuery = "DELETE FROM appData WHERE id = '?'"; + + $hResult = query_parameters($sQuery, $this->iId); + + if(!$hResult) + return FALSE; + + return $hResult; + } + + function reQueue() + { + if(!$this->canEdit()) + return FALSE; + + $sQuery = "UPDATE appData SET state = '?' WHERE id = '?'"; + $hResult = query_parameters($sQuery, 'queued', $this->iId); + + if(!$hResult) + return FALSE; + else + return TRUE; + } + + function reject() + { + if(!$this->canEdit()) + return FALSE; + + $sQuery = "UPDATE appData SET state = '?' WHERE id = '?'"; + $hResult = query_parameters($sQuery, 'rejected', $this->iId); + + if(!$hResult) + return FALSE; + else + return TRUE; + } + + function update() + { + if(!$this->canEdit()) + return FALSE; + + $sQuery = "UPDATE appData SET versionId = '?', appId = '?', description = '?' + WHERE id = '?'"; + $hResult = query_parameters($sQuery, $this->iVersionId, $this->iAppId, + $this->sDescription, $this->iId); + + if(!$hResult) + return FALSE; + + return TRUE; + } + + public function objectGetParent($sClass = '') + { + if($this->iVersionId) + return new version($this->iVersionId); + else + return new application($this->iAppId); + } + + public function objectSetParent($iNewId, $sClass = '') + { + if($this->iVersionId) + $this->iVersionId = $iNewId; + else + $this->iAppId = $iNewId; + } + + function listSubmittedBy($iUserId, $bQueued = true) + { + $sExtra = ''; + if($bQueued) // downloadurls are only queued together with versions + $sExtra = " AND appData.type != 'downloadurl' "; + + $hResult = query_parameters("SELECT * FROM appData WHERE + appData.submitterId = '?' + AND + appData.state = '?' $sExtra + ORDER BY appData.id", + $iUserId, $bQueued ? 'queued' : 'accepted'); + + if(!$hResult || !query_num_rows($hResult)) + return false; + + $oTable = new table(); + $oTable->setWidth("100%"); + $oTable->setAlign("center"); + + $oTableRow = new tableRow(); + + $oTableRow->addTextCell("Version"); + $oTableRow->addTextCell("Type"); + $oTableRow->addTextCell("Description"); + $oTableRow->addTextCell("Submission Date"); + + if($bQueued) + $oTableRow->addTextCell("Action"); + + $oTableRow->setClass("color4"); + $oTable->addRow($oTableRow); + + for($i = 1; $oRow = query_fetch_object($hResult); $i++) + { + $oTableRow = new tableRow(); + if($oRow->versionId) + { + $oVersion = new version($oRow->versionId); + $sLink = "objectMakeUrl()."\">". + $oVersion->fullName($oVersion->iVersionId).""; + } else + { + $oApp = new application($this->appId); + $sLink = $oApp->objectMakeLink(); + } + + $oTableRow->addTextCell($sLink); + $oTableRow->addTextCell($oRow->type); + $oTableRow->addTextCell($oRow->description); + $oTableRow->addTextCell(print_date(mysqldatetime_to_unixtimestamp($oRow->submitTime))); + + if($bQueued) + { + $oM = new objectManager($oRow->type); + $oM->setReturnTo(array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : ""); + $shDeleteLink = 'id, "Delete entry").'">delete'; + $shEditLink = 'id, "Edit entry").'">edit'; + $oTableRow->addTextCell("[ $shEditLink ]   [ $shDeleteLink ]"); + } + + $oTableRow->setClass(($i % 2) ? "color0" : "color1"); + $oTable->addRow($oTableRow); + } + + return $oTable->getString(); + + } + + /* Get appData for a given version/application, optionally filter by type */ + function getData($iId, $sType, $bIsVersion = TRUE, $bQueued = FALSE, $bRejected = FALSE) + { + $iAppId = 0; + $iVersionId = 0; + + if($bIsVersion) + $iVersionId = $iId; + else + $iAppId = $iId; + + $sState = objectManager::getStateString($bQueued, $bRejected); + + $hResult = query_parameters("SELECT * FROM appData WHERE appId = '?' AND + versionId = '?' AND TYPE = '?' AND state = '?'", + $iAppId, $iVersionId, $sType, $sState); + + if(!$hResult || !query_num_rows($hResult)) + return FALSE; + + return $hResult; + } + + function objectGetEntriesCount($sState, $sType = null, $oFilters = null) + { + /* Not implemented for appData */ + if($sState == 'rejected') + return FALSE; + + $sSelectType = ""; + $sWhereFilter = ''; + + if($oFilters) + { + $aOptions = $oFilters->getOptions(); + if($aOptions['appCategory']) + { + $oCategory = new category($aOptions['appCategory']); + $sWhereFilter .= ' AND ' . $oCategory->getSqlQueryPart(); + } + } + + if(($sState != 'accepted') && + !$_SESSION['current']->hasPriv("admin")) + { + $sQuery = "SELECT COUNT(DISTINCT appData.id) as count FROM appData, + appMaintainers, appVersion, appFamily WHERE + appFamily.appId = appVersion.appId + AND + appMaintainers.state = 'accepted' + AND + appMaintainers.userId = '?' + AND + ( + ( + appMaintainers.appId = appFamily.appId + OR + appMaintainers.appId = appVersion.appId + ) + AND + appMaintainers.superMaintainer = '1' + AND + ( + appData.appId = appMaintainers.appId + OR + ( + appData.versionId = appVersion.versionId + AND + appVersion.appId = appMaintainers.appId + ) + ) + OR + ( + appMaintainers.superMaintainer = '0' + AND + appMaintainers.versionId = appVersion.versionId + AND + appMaintainers.versionId = appData.versionId + ) + ) + AND + appVersion.state = 'accepted' + AND + appFamily.state = 'accepted'$sWhereFilter"; + + if($sState != 'all') + $sQuery .= " AND appData.state = '$sState'"; + + if($sType) + { + $sQuery .= " AND type = '?'"; + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sType); + } else + { + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId); + } + } else + { + if($sState != 'all') + $sAppDataQueued = " AND appData.state = '$sState'"; + else + $sAppDataQueued = ''; + + if($sType) + $sSelectType = " AND type = '?'"; + + $sQuery = "(SELECT COUNT(DISTINCT appData.id) as count FROM appData, + appFamily WHERE + ( + appData.appId = appFamily.appId + AND + appData.versionId = '0' + ) + AND + appFamily.state = 'accepted'$sAppDataQueued$sSelectType$sWhereFilter) UNION + ( + SELECT COUNT(DISTINCT appData.id) as count FROM appData, + appFamily, appVersion WHERE + appFamily.appId = appVersion.appId + AND + ( + appData.versionId = appVersion.versionId + ) + AND + appVersion.state = 'accepted' + AND + appFamily.state = 'accepted'$sAppDataQueued$sSelectType$sWhereFilter)"; + + if($sType) + $hResult = query_parameters($sQuery, $sType, $sType); + else + $hResult = query_parameters($sQuery); + } + + if(!$hResult) + return FALSE; + + for($iCount = 0; $oRow = query_fetch_object($hResult);) + $iCount += $oRow->count; + + return $iCount; + } + + function objectGetHeader($sType) + { + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("Submission Date"); + $oTableRow->AddTextCell("Submitter"); + $oTableRow->AddTextCell("Application"); + $oTableRow->AddTextCell("Version"); + return $oTableRow; + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true, $sType = null, $oFilters = null) + { + /* Not implemented for appData */ + if($sState == 'rejected') + return FALSE; + + $sSelectType = ""; + $sLimit = ""; + $sWhereFilter = ''; + + if($oFilters) + { + $aOptions = $oFilters->getOptions(); + if($aOptions['appCategory']) + { + $oCategory = new category($aOptions['appCategory']); + $sWhereFilter .= ' AND ' . $oCategory->getSqlQueryPart(); + } + } + + if($sState != 'accepted' && !$_SESSION['current']->hasPriv("admin")) + { + $sQuery = "SELECT DISTINCT appData.* FROM appData, appMaintainers, + appVersion, appFamily WHERE + appFamily.appId = appVersion.appId + AND + appMaintainers.state = 'accepted' + AND + appMaintainers.userId = '?' + AND + ( + ( + ( + appMaintainers.appId = appFamily.appId + OR + appMaintainers.appId = appVersion.appId + ) + AND + appMaintainers.superMaintainer = '1' + AND + ( + appData.appId = appMaintainers.appId + OR + ( + appData.versionId = appVersion.versionId + AND + appVersion.appId = appMaintainers.appId + ) + ) + ) + OR + ( + appMaintainers.superMaintainer = '0' + AND + appMaintainers.versionId = appVersion.versionId + AND + appMaintainers.versionId = appData.versionId + ) + ) + AND + appVersion.state = 'accepted' + AND + appFamily.state = 'accepted' + AND + appData.state = '?' + AND + appData.type = '?' + $sWhereFilter + ORDER BY appFamily.appName"; + if(!$iRows && !$iStart) + { + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sState, $sType); + } else + { + if(!$iRows) + $iRows = appData::objectGetEntriesCount($sState, $sType, $oFilters); + $sQuery .= " LIMIT ?,?"; + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sState, $sType, + $iStart, $iRows); + } + } else + { + if($iStart || $iRows) + $sLimit = " LIMIT ?,?"; + + $sQuery = + "( + SELECT DISTINCT appData.* FROM appData, + appFamily WHERE + ( + appData.appId = appFamily.appId + AND + appData.versionId = '0' + ) + AND + appFamily.state = 'accepted' + AND + appData.state = '?' + AND + appData.type = '?' $sWhereFilter ORDER BY appFamily.appName $sLimit + ) + UNION + ( + SELECT DISTINCT appData.* FROM appData, + appFamily, appVersion WHERE + appFamily.appId = appVersion.appId + AND + ( + appData.versionId = appVersion.versionId + ) + AND + appVersion.state = 'accepted' + AND + appFamily.state = 'accepted' + AND + appData.state = '?' + AND + appData.type = '?' $sWhereFilter ORDER BY appFamily.appName $sLimit + )"; + if(!$iRows && !$iStart) + { + $hResult = query_parameters($sQuery, $sState, $sType, + $sState, $sType); + } else + { + if(!$iRows) + $iRows = appData::objectGetEntriesCount($sState, $sType, $oFilters); + $hResult = query_parameters($sQuery, $sState, $sType, + $iStart, $iRows, + $sState, $sType, + $iStart, $iRows); + } + } + + if(!$hResult) + return FALSE; + + return $hResult; + } + + function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + return TRUE; + if($this) + { + if($this->bQueued && $this->iSubmitterId == $_SESSION['current']->iUserId) + return true; + + if($this->iVersionId) + { + $oVersion = new version($this->iVersionId); + if($oVersion->canEdit()) + return TRUE; + else + return FALSE; + } else if($this->iAppId) + { + $oApp = new application($this->iAppId); + if($oApp->canEdit()) + return TRUE; + else + return FALSE; + } else + return FALSE; + } + } + + function mustBeQueued() + { + if($_SESSION['current']->hasPriv("admin")) + return FALSE; + if($this) + { + if($this->iVersionId) + { + $oVersion = new version($this->iVersionId); + if($oVersion->canEdit() && $oVersion->objectGetState() == 'accepted') + return FALSE; + else + return TRUE; + } else if($this->iAppId) + { + $oApp = new application($this->iAppId); + if($oApp->canEdit() && $oApp->objectGetState() == 'accepted') + return FALSE; + else + return TRUE; + } else + return TRUE; + } + } + + function objectGetTableRow() + { + $oVersion = new Version($this->iVersionId); + + if(!$this->iAppId) + $this->iAppId = $oVersion->iAppId; + + $oApp = new Application($this->iAppId); + $oUser = new User($this->iSubmitterId); + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($this->sSubmitTime))); + $oTableRow->AddTextCell($oUser->objectMakeLink()); + $oTableRow->AddTextCell($oApp->objectMakeLink()); + $oTableRow->AddTextCell($this->iVersionId ? $oVersion->objectMakeLink() : "N/A"); + + // create the object manager specific row + $oOMTableRow = new OMTableRow($oTableRow); + + return $oOMTableRow; + } + + function objectDisplayQueueProcessingHelp() + { + $sHelp = "

This is a list of application data submitted by users. ". + "Please inspect the data carefully before accepting or rejecting it.

"; + echo $sHelp; + } + + /* Output the part of an appData editor which is the same for all data types */ + function outputEditorGeneric() + { + $oVersion = new version($this->iVersionId); + if($oVersion->iVersionId) + { + $this->iAppId = $oVersion->iAppId; + $sVersionName = $oVersion->objectMakeLink(); + } + else + $sVersionName = "N/A"; + + $oApp = new Application($this->iAppId); + + // view application details + echo html_frame_start("New Application Data Form",600,"",0); + echo "\n"; + + // app name + echo '',"\n"; + echo "\n"; + + // version + echo '',"\n"; + echo "\n"; + + //dataDescription + echo '',"\n"; + echo '',"\n"; + } + + function getDefaultReply() + { + $sReplyText = "Enter a personalized reason for acceptance or rejection of the". + " submitted application data here"; + return $sReplyText; + } + + function objectGetId() + { + return $this->iId; + } +} + +?> diff --git a/include/appdb.php b/include/appdb.php new file mode 100644 index 0000000..51bd8e8 --- /dev/null +++ b/include/appdb.php @@ -0,0 +1,41 @@ +catHitId); + } else + { + query_parameters("INSERT INTO catHitStats (appHitId, time, ip, catId, count) ". + "VALUES (?, ?, '?', '?', '?')", + "null", "null", $REMOTE_ADDR, $catId, "1"); + } +} + +function log_application_visit($appId) +{ + global $REMOTE_ADDR; + + $result = query_parameters("SELECT * FROM appHitStats WHERE ip = '?' AND appId = '?'", + $REMOTE_ADDR, $appId); + if($result && query_num_rows($result) == 1) + { + $stats = query_fetch_object($result); + query_parameters("UPDATE appHitStats SET count = count + 1 WHERE appHitId = '?'", + $stats->appHitId); + } else + { + query_parameters("INSERT INTO appHitStats (appHitId, time, ip, appId, count) ". + "VALUES (?, ?, '?', '?', '?')", + "null", "null", $REMOTE_ADDR, $appId, "1"); + } +} + +?> diff --git a/include/application.php b/include/application.php new file mode 100644 index 0000000..256afa1 --- /dev/null +++ b/include/application.php @@ -0,0 +1,1459 @@ +aVersions = array(); // Should always be an array + + // we are working on an existing application + if(!$iAppId && !$oRow) + return; + + if(!$oRow) + { + /* fetch this applications information */ + $sQuery = "SELECT * + FROM appFamily + WHERE appId = '?'"; + if($hResult = query_parameters($sQuery, $iAppId)) + $oRow = query_fetch_object($hResult); + } + + if($oRow) + { + $this->iAppId = $oRow->appId; + $this->iVendorId = $oRow->vendorId; + $this->iCatId = $oRow->catId; + $this->iSubmitterId = $oRow->submitterId; + $this->sSubmitTime = $oRow->submitTime; + $this->sName = $oRow->appName; + $this->sKeywords = $oRow->keywords; + $this->sDescription = $oRow->description; + //TODO: we should move the url to the appData table + // and return an id into the appData table here + $this->sWebpage = Url::normalize($oRow->webPage); + $this->sState = $oRow->state; + } + + /* fetch versions of this application, if there are any */ + $this->aVersionsIds = array(); + + /* only admins can view all versions */ + //FIXME: it would be nice to move this permission into the user class as well as keep it generic + if($_SESSION['current']->hasPriv("admin")) + { + $hResult = $this->_internal_retrieve_all_versions(); + } else + { + $hResult = $this->_internal_retrieve_unqueued_versions(); + } + if($hResult) + { + while($oRow = query_fetch_object($hResult)) + { + $this->aVersionsIds[] = $oRow->versionId; + } + } + } + + private function _internal_retrieve_all_versions($bOnlyAccepted = false, $bIncludeObsolete = TRUE, $bIncludeDeleted = false) + { + $sExtraTerms = ''; + + if(!$bIncludeObsolete) + $sExtraTerms .= " AND obsoleteBy = '0'"; + + if($bOnlyAccepted) + $sExtraTerms .= " AND state = 'accepted'"; + else if(!$bIncludeDeleted) + $sExtraTerms .= " AND state != 'deleted'"; + + $sQuery = "SELECT versionId FROM appVersion WHERE + appId = '?'$sExtraTerms ORDER by versionName"; + $hResult = query_parameters($sQuery, $this->iAppId); + return $hResult; + } + + private function _internal_retrieve_unqueued_versions() + { + $sQuery = "SELECT versionId FROM appVersion WHERE + state = 'accepted' AND + appId = '?'"; + $hResult = query_parameters($sQuery, $this->iAppId); + return $hResult; + } + + /** + * Creates a new application. + */ + public function create() + { + if(!$_SESSION['current']->canCreateApplication()) + return false; + + $hResult = query_parameters("INSERT INTO appFamily (appName, description, ". + "keywords, webPage, vendorId, catId, ". + "submitTime, submitterId, ". + "state) VALUES (". + "'?', '?', '?', '?', '?', '?', ?, '?', '?')", + $this->sName, $this->sDescription, $this->sKeywords, + $this->sWebpage, $this->iVendorId, $this->iCatId, + "NOW()", $_SESSION['current']->iUserId, + $this->mustBeQueued() ? 'queued' : 'accepted'); + if($hResult) + { + $this->iAppId = query_appdb_insert_id(); + $this->application($this->iAppId); + $this->SendNotificationMail(); // Only administrators will be mailed as no supermaintainers exist for this app. + + /* Submit super maintainer request if asked to */ + if($this->iMaintainerRequest == SUPERMAINTAINER_REQUEST) + { + $oMaintainer = new Maintainer(); + $oMaintainer->iAppId = $this->iAppId; + $oMaintainer->iUserId = $_SESSION['current']->iUserId; + $oMaintainer->sMaintainReason = "This user submitted the application; auto-queued."; + $oMaintainer->bSuperMaintainer = 1; + $oMaintainer->create(); + } + + return true; + } else + { + addmsg("Error while creating a new application.", "red"); + return false; + } + } + + + /** + * Update application. + * Returns true on success and false on failure. + */ + public function update($bSilent=false) + { + $sWhatChanged = ""; + + /* if the user doesn't have permission to modify this application, don't let them */ + if(!$_SESSION['current']->canModifyApplication($this)) + return; + + /* create an instance of ourselves so we can see what has changed */ + $oApp = new Application($this->iAppId); + + if ($this->sName && ($this->sName!=$oApp->sName)) + { + if (!query_parameters("UPDATE appFamily SET appName = '?' WHERE appId = '?'", + $this->sName, $this->iAppId)) + return false; + $sWhatChanged .= "Name was changed from ".$oApp->sName." to ".$this->sName.".\n\n"; + } + + if ($this->sDescription && ($this->sDescription!=$oApp->sDescription)) + { + if (!query_parameters("UPDATE appFamily SET description = '?' WHERE appId = '?'", + $this->sDescription, $this->iAppId)) + return false; + $sWhatChanged .= "Description was changed from\n ".$oApp->sDescription."\n to \n".$this->sDescription.".\n\n"; + } + + if ($this->sKeywords && ($this->sKeywords!=$oApp->sKeywords)) + { + if (!query_parameters("UPDATE appFamily SET keywords = '?' WHERE appId = '?'", + $this->sKeywords, $this->iAppId)) + return false; + $sWhatChanged .= "Keywords were changed from\n ".$oApp->sKeywords."\n to \n".$this->sKeywords.".\n\n"; + } + + if ($this->sWebpage!=$oApp->sWebpage) + { + if (!query_parameters("UPDATE appFamily SET webPage = '?' WHERE appId = '?'", + $this->sWebpage, $this->iAppId)) + return false; + $sWhatChanged .= "Web page was changed from ".$oApp->sWebpage." to ".$this->sWebpage.".\n\n"; + } + + if ($this->iVendorId && ($this->iVendorId!=$oApp->iVendorId)) + { + if (!query_parameters("UPDATE appFamily SET vendorId = '?' WHERE appId = '?'", + $this->iVendorId, $this->iAppId)) + return false; + $oVendorBefore = new Vendor($oApp->iVendorId); + $oVendorAfter = new Vendor($this->iVendorId); + $sWhatChanged .= "Developer was changed from ".$oVendorBefore->sName." to ".$oVendorAfter->sName.".\n\n"; + } + + if ($this->iCatId && ($this->iCatId!=$oApp->iCatId)) + { + if (!query_parameters("UPDATE appFamily SET catId = '?' WHERE appId = '?'", + $this->iCatId, $this->iAppId)) + return false; + $oCatBefore = new Category($oApp->iCatId); + $oCatAfter = new Category($this->iCatId); + $sWhatChanged .= "Category was changed from ".$oCatBefore->sName." to ".$oCatAfter->sName.".\n\n"; + } + if($sWhatChanged and !$bSilent) + $this->SendNotificationMail("edit",$sWhatChanged); + return true; + } + + /** + * Deletes the application from the database. + * and request the deletion of linked elements. + */ + public function purge() + { + $bSuccess = true; + + /* make sure the current user has the appropriate permission to delete + this application */ + if(!$_SESSION['current']->canDeleteApplication($this)) + return false; + + foreach($this->objectGetChildren(true) as $oChild) + { + if(!$oChild->purge()) + $bSuccess = FALSE; + } + + /* Flag the entry as deleted */ + $sQuery = "DELETE FROM appFamily + WHERE appId = '?' + LIMIT 1"; + if(!($hResult = query_parameters($sQuery, $this->iAppId))) + $bSuccess = false; + + return $bSuccess; + } + + /** + * Falgs the application as deleted + * and request the deletion of linked elements. + */ + public function delete() + { + $bSuccess = true; + + /* make sure the current user has the appropriate permission to delete + this application */ + if(!$_SESSION['current']->canDeleteApplication($this)) + return false; + + foreach($this->objectGetChildren() as $oChild) + { + if(!$oChild->delete()) + $bSuccess = FALSE; + } + + /* Flag the entry as deleted */ + $sQuery = "UPDATE appFamily SET state = 'deleted' + WHERE appId = '?' + LIMIT 1"; + if(!($hResult = query_parameters($sQuery, $this->iAppId))) + $bSuccess = false; + + return $bSuccess; + } + + + /** + * Move application out of the queue. + */ + public function unQueue() + { + if(!$_SESSION['current']->canUnQueueApplication()) + return; + + if(query_parameters("UPDATE appFamily SET state = '?', keywords = '?' WHERE appId = '?'", + 'accepted', str_replace(" *** ","",$this->sKeywords), $this->iAppId)) + { + $this->sState = 'accepted'; + // we send an e-mail to interested people + $this->mailSubmitter(); + $this->SendNotificationMail(); + + /* Unqueue matching super maintainer request */ + $hResultMaint = query_parameters("SELECT maintainerId FROM appMaintainers WHERE userId = '?' AND appId = '?'", $this->iSubmitterId, $this->iAppId); + if($hResultMaint && query_num_rows($hResultMaint)) + { + $oMaintainerRow = query_fetch_object($hResultMaint); + $oMaintainer = new Maintainer($oMaintainerRow->maintainerId); + $oMaintainer->unQueue("OK"); + } + } + } + + public function Reject() + { + if(!$_SESSION['current']->canRejectApplication($this)) + return; + + // If we are not in the queue, we can't move the application out of the queue. + if($this->sState != 'queued') + return false; + + if(query_parameters("UPDATE appFamily SET state = '?' WHERE appId = '?'", + 'rejected', $this->iAppId)) + { + $this->sState = 'rejected'; + // we send an e-mail to interested people + $this->mailSubmitter("reject"); + $this->SendNotificationMail("reject"); + + // the application has been rejected + addmsg("The application has been rejected.", "green"); + } + } + + public static function objectGetItemsPerPage($sState = 'accepted') + { + $aItemsPerPage = array(25, 50, 100, 200); + $iDefaultPerPage = 25; + return array($aItemsPerPage, $iDefaultPerPage); + } + + public function ReQueue() + { + if(!$_SESSION['current']->canRequeueApplication($this)) + return false; + + if(query_parameters("UPDATE appFamily SET state = '?' WHERE appId = '?'", + 'queued', $this->iAppId)) + { + $this->sState = 'queued'; + // we send an e-mail to interested people + $this->SendNotificationMail(); + + // the application has been re-queued + addmsg("The application has been re-queued.", "green"); + } + } + + public function objectGetSubmitterId() + { + return $this->iSubmitterId; + } + + public function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + public function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + if($bMailSubmitter) + { + switch($sAction) + { + case "delete": + $sSubject = "Submitted application deleted"; + $sMsg = "The application you submitted (".$this->sName. + ") has been deleted."; + break; + } + $aMailTo = null; + } else + { + switch($sAction) + { + case "delete": + $sSubject = $this->sName." deleted"; + $sMsg = "The application '".$this->sName."' has been deleted."; + break; + } + $aMailTo = User::get_notify_email_address_list($this->iAppId); + } + return array($sSubject, $sMsg, $aMailTo); + } + + private function mailSubmitter($sAction="add") + { + global $aClean; + if(!isset($aClean['sReplyText'])) + $aClean['sReplyText'] = ""; + + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + switch($sAction) + { + case "add": + $sSubject = "Submitted application accepted"; + $sMsg = "The application you submitted (".$this->sName.") has been accepted by ".$_SESSION['current']->sRealname.".\n"; + $sMsg .= "Administrator's Response:\n"; + break; + case "reject": + $sSubject = "Submitted application rejected"; + $sMsg = "The application you submitted (".$this->sName.") has been rejected by ".$_SESSION['current']->sRealname."."; + $sMsg .= "Clicking on the link in this email will allow you to modify and resubmit the application. "; + $sMsg .= "A link to your queue of applications and versions will also show up on the left hand side of the Appdb site once you have logged in. "; + $sMsg .= APPDB_ROOT."objectManager.php?sClass=application_queue". + "&bIsQueue=true&bIsRejected=true&iId=".$this->iAppId."&sTitle=". + "Edit+Application\n"; + $sMsg .= "Reason given:\n"; + break; + } + + $sMsg .= $aClean['sReplyText']."\n"; + $sMsg .= "We appreciate your help in making the Application Database better for all users."; + + mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg); + } + } + + + public static function countWithRating($sRating) + { + $sQuery = "SELECT DISTINCT count(appId) as total + FROM appVersion + WHERE rating = '?' + AND state = 'accepted'"; + + if($hResult = query_parameters($sQuery, $sRating)) + { + $oRow = query_fetch_object($hResult); + } + return $oRow->total; + } + + public static function getWithRating($sRating, $iOffset, $iItemsPerPage) + { + $aApps = array(); + $sQuery = "SELECT DISTINCT appVersion.appId, appName + FROM appVersion, appFamily WHERE + appVersion.appId = appFamily.appId + AND + rating = '?' + AND + appVersion.state = 'accepted' + ORDER BY appName ASC LIMIT ?, ?"; + + if($hResult = query_parameters($sQuery, $sRating, $iOffset, $iItemsPerPage)) + { + while($aRow = query_fetch_row($hResult)) + { + array_push($aApps, $aRow[0]); + } + } + return $aApps; + } + + private function SendNotificationMail($sAction="add",$sMsg=null) + { + global $aClean; + if(!isset($aClean['sReplyText'])) + $aClean['sReplyText'] = ""; + + switch($sAction) + { + case "add": + if($this->sState == 'accepted') // Has been accepted. + { + $sSubject = $this->sName." has been added by ".$_SESSION['current']->sRealname; + $sMsg = $this->objectMakeUrl()."\n"; + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + $sMsg .= "This application has been submitted by ".$oSubmitter->sRealname."."; + $sMsg .= "\n"; + } + if($aClean['sReplyText']) + { + $sMsg .= "Appdb admin reply text:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + + addmsg("The application was successfully added into the database.", "green"); + } else + { + $sSubject = $this->sName." has been submitted by ".$_SESSION['current']->sRealname; + $sMsg .= "This application has been queued."; + $sMsg .= "\n"; + addmsg("The application you submitted will be added to the database after being reviewed.", "green"); + } + break; + case "edit": + $sSubject = $this->sName." has been modified by ".$_SESSION['current']->sRealname; + $sMsg .= $this->objectMakeUrl()."\n"; + addmsg("Application modified.", "green"); + break; + case "reject": + $sSubject = $this->sName." has been rejected by ".$_SESSION['current']->sRealname; + $sMsg .= APPDB_ROOT."objectManager.php?sClass=application_queue". + "&bIsQueue=true&bIsRejected=true&iId=".$this->iAppId."&sTitle=". + "Edit+Application\n"; + + // if sReplyText is set we should report the reason the application was rejected + if($aClean['sReplyText']) + { + $sMsg .= "Reason given:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + + addmsg("Application rejected.", "green"); + break; + } + $sEmail = User::get_notify_email_address_list($this->iAppId); + if($sEmail) + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + public function objectShowPreview() + { + return TRUE; + } + + /* output a html table and this applications values to the fields for editing */ + public function outputEditor($sVendorName = "") + { + HtmlAreaLoaderScript(array("app_editor")); + + echo ''; + + /* Used to distinguish between the first step of entering an application + name and the full editor displayed here */ + echo ''."\n"; + + echo html_frame_start("Application Form", "90%", "", 0); + echo "
App Name".$oApp->objectMakeLink()."
App Version$sVersionName
Description
\n"; + echo '',"\n"; + echo '',"\n"; + + // app Category + echo '',"\n"; + + $oVendor = new vendor($this->iVendorId); + $sVendorHelp = "The developer of the application. "; + if(!$this->iAppId || $oVendor->objectGetState() != 'accepted') + { + if(!$this->iAppId) + { + $sVendorHelp .= "If it is not on the list please add it ". + "using the form below."; + } else + { + if($this->iSubmitterId != $_SESSION['current']->iUserId) + { + $sVendorHelp .= "The user added a new one; review ". + "it in the Developer form below or ". + "replace it with an existing one."; + } else + { + $sVendorHelp .= 'You added a new one; it can be edited '. + 'using the form below, or replaced with '. + 'one from this list.'; + } + } + } + // vendor name + echo '',"\n"; + echo "\n"; + + // alt vendor + $x = new TableVE("view"); + echo '',"\n"; + + // url + echo '',"\n"; + echo '',"\n"; + + echo '',"\n"; + echo '',"\n"; + + echo '',"\n"; + echo '',"\n"; + + // Allow user to apply as super maintainer if this is a new app + if(!$this->iAppId) + { + $sMaintainerOptions = + "". + "I would not like to become a maintainer
\n". + "". + "I would like to be a maintainer of the new version only
\n". + "". + "I would like to be a maintainer of the entire application
\n"; + + $sMaintainerOptionsSelected = str_replace( + "value=\"$this->iMaintainerRequest\"", + "value=\"$this->iMaintainerRequest\" checked=\"checked\"", + $sMaintainerOptions); + + echo html_tr(array( + array("Maintainer options", "class=\"color0\""), + $sMaintainerOptionsSelected), + "", "valign=\"top\""); + } + + echo "
Application name
Category',"\n"; + + $aCategories = category::getOrderedList(true); + $aCatNames = array(); + $aCatIds = array(); + + foreach($aCategories as $oCategory) + { + $aCatNames[] = $oCategory->sName; + $aCatIds[] = $oCategory->objectGetId(); + } + + echo html_select("iAppCatId",$aCatIds,$this->iCatId, $aCatNames); + + echo '
Developer$sVendorHelp
 ',"\n"; + echo $x->make_option_list("iAppVendorId", + $this->iVendorId,"vendor","vendorId","vendorName", + array('vendor.state', 'accepted')); + echo '
URL
Keywords
Application description (In your own words)

\n"; + + echo html_frame_end(); + } + + public function CheckOutputEditorInput($aValues) + { + $errors = ""; + + if (empty($aValues['iAppCatId'])) + $errors .= "
  • Please enter a category for your application.
  • \n"; + + if (strlen($aValues['sAppName']) > 200 ) + $errors .= "
  • Your application name is too long.
  • \n"; + + if (empty($aValues['sAppName'])) + $errors .= "
  • Please enter an application name.
  • \n"; + + // No vendor entered, and nothing in the list is selected + if (empty($aValues['sVendorName']) && !$aValues['iAppVendorId']) + $errors .= "
  • Please enter a developer.
  • \n"; + + if (empty($aValues['shAppDescription'])) + $errors .= "
  • Please enter a description of your application.
  • \n"; + + return $errors; + } + + /* retrieves values from $aValues that were output by outputEditor() */ + /* $aValues can be $_REQUEST or any array with the values from outputEditor() */ + public function GetOutputEditorValues($aValues) + { + if($aValues['iAppId']) + $this->iAppId = $aValues['iAppId']; + + $this->sName = $aValues['sAppName']; + $this->sDescription = $aValues['shAppDescription']; + $this->iCatId = $aValues['iAppCatId']; + $this->iVendorId = $aValues['iAppVendorId']; + $this->sWebpage = $aValues['sAppWebpage']; + $this->sKeywords = $aValues['sAppKeywords']; + $this->iMaintainerRequest = $aValues['iMaintainerRequest']; + } + + /** + * Displays the SUB apps that belong to this application. + */ + public function displayBundle() + { + $hResult = query_parameters("SELECT appFamily.appId, appName, description FROM appBundle, appFamily ". + "WHERE appFamily.state = 'accepted' AND bundleId = '?' AND appBundle.appId = appFamily.appId", + $this->iAppId); + if(!$hResult || query_num_rows($hResult) == 0) + { + return; // do nothing + } + + echo html_frame_start("","98%","",0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + for($c = 0; $ob = query_fetch_object($hResult); $c++) + { + $oApp = new application($ob->appId); + //set row color + $bgcolor = ($c % 2 == 0) ? "color0" : "color1"; + + //display row + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + } + + echo "
    Application NameDescription
    ".$oApp->objectMakeLink()."".util_trim_description($oApp->sDescription)."
    \n\n"; + echo html_frame_end(); + } + + public function objectGetCustomTitle($sAction) + { + switch($sAction) + { + case 'delete': + return 'Delete '.$this->sName; + case "view": + return $this->sName; + + default: + return null; + } + } + + /* display this application */ + public function display() + { + /* is this user supposed to view this version? */ + if(!$_SESSION['current']->canViewApplication($this)) + { + $sError = 'You do not have permission to view this entry'; + + objectManager::error_exit($sError); + } + + // cat display + $oCategory = new Category($this->iCatId); + $oCategory->displayPath($this->iAppId); + + // set developer + $oVendor = new Vendor($this->iVendorId); + + // set URL + $appLinkURL = ($this->sWebpage) ? trimmed_link($this->sWebpage,30) : " "; + + // start display application + echo html_frame_start("","98%","",0); + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "
    \n"; + + echo ' ',"\n"; + echo " \n"; + echo " \n"; + + // main URL + echo " \n"; + + // optional links + if($sUrls = url::display(NULL, $this->iAppId)) + echo $sUrls; + + // image + $img = Screenshot::get_random_screenshot_img($this->iAppId, null, false); + echo "\n"; + + echo "
    Name ".$this->sName."
    Developer ". + $oVendor->objectMakeLink()." \n"; + echo "
    URL".$appLinkURL."
    $img
    \n"; /* close of name/developer/bugs/url table */ + + echo "
    \n"; + + // Display all supermaintainers maintainers of this application + echo " \n"; + echo " \n"; + $other_maintainers = Maintainer::getSuperMaintainersUserIdsFromAppId($this->iAppId); + if($other_maintainers) + { + echo " \n"; + } else + { + echo " \n"; + } + + // Display the app maintainer button + echo ' \n"; + echo "
    Super maintainers:
      \n"; + while(list($index, $userIdValue) = each($other_maintainers)) + { + $oUser = new User($userIdValue); + echo "
    • ".$oUser->objectMakeLink()."
    • \n"; + } + echo "
    No maintainers.Volunteer today!
    '; + if($_SESSION['current']->isLoggedIn()) + { + /* are we already a maintainer? */ + if($_SESSION['current']->isSuperMaintainer($this->iAppId)) /* yep */ + { + echo '
    '; + } else /* nope */ + { + echo ' sName).'&sReturnTo='.urlencode($this->objectMakeUrl()).'">'; + } + + echo " iAppId."\">"; + echo " "; /* set superMaintainer to 1 because we are at the appFamily level */ + echo "
    "; + + if($_SESSION['current']->isSuperMaintainer($this->iAppId) || $_SESSION['current']->hasPriv("admin")) + { + echo '
    '; + echo '
    '; + echo ''; + echo '
    '; + } + if($_SESSION['current']->isLoggedIn()) + { + echo '
    '; + echo ''; + echo '
    '; + } + if($_SESSION['current']->hasPriv("admin")) + { + $url = BASE."objectManager.php?sClass=application&bIsQueue=false&sAction=delete&iId=".$this->iAppId; + echo "
    "; + echo '
    '; + } + } else + { + echo '
    '; + } + echo "
    \n"; /* close of super maintainers table */ + echo "
    \n"; /* close the table that contains the whole left hand side of the upper table */ + + // description + echo " \n"; + echo "
    \n"; + echo "\t
    \n"; + echo "\t\tDescription\n"; + echo "\t
    \n"; // close the 'title_class' div + echo "\t
    \n"; + echo "\t\t".$this->sDescription."\n"; + echo "\t
    \n"; // close the 'info_contents' div + echo "
    \n"; // close the 'info_container' div + + echo html_frame_end("For more details and user comments, view the versions of this application."); + + // display versions + Version::displayList($this->getVersions()); + + // display bundle + $this->displayBundle(); + + note::displayNotesForEntry(null, $this->iAppId); + } + + public static function lookup_name($appId) + { + if(!$appId) return null; + $result = query_parameters("SELECT appName FROM appFamily WHERE appId = '?'", + $appId); + if(!$result || query_num_rows($result) != 1) + return null; + $ob = query_fetch_object($result); + return $ob->appName; + } + + /* List applications submitted by a given user */ + public static function listSubmittedBy($iUserId, $bQueued = true) + { + $hResult = query_parameters("SELECT appId, appName, vendorId, description, + submitTime FROM appFamily + WHERE + submitterId = '?' + AND + state = '?' + ORDER BY appId", $iUserId, $bQueued ? 'queued' : 'accepted'); + + if(!$hResult || !query_num_rows($hResult)) + return false; + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetAlign("center"); + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("Application"); + $oTableRow->AddTextCell("Description"); + $oTableRow->AddTextCell("Developer"); + $oTableRow->AddTextCell("Submission Date"); + $oTableRow->SetClass("color4"); + $oTable->SetHeader($oTableRow); + + if($bQueued) + $oTableRow->addTextCell("Action"); + + for($i = 1; $oRow = query_fetch_object($hResult); $i++) + { + + $oVendor = new vendor($oRow->vendorId); + $oApp = new application($oRow->appId); + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell($oApp->objectMakeLink()); + $oTableRow->AddTextCell($oRow->description); + $oTableRow->AddTextCell($oVendor->objectMakeLink()); + $oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($oRow->submitTime))); + $oTableRow->SetClass(($i % 2) ? "color0" : "color1"); + + if($bQueued) + { + $oM = new objectManager('application_queue'); + $oM->setReturnTo(array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : ""); + $shDeleteLink = 'iAppId, "Delete entry").'">delete'; + $shEditLink = 'iAppId, "Edit entry").'">edit'; + $oTableRow->addTextCell("[ $shEditLink ]   [ $shDeleteLink ]"); + } + + $oTable->AddRow($oTableRow); + } + + return $oTable->GetString(); + } + + public function objectGetClassDisplayName() + { + return 'application'; + } + + public function objectMakeUrl() + { + $sUrl = APPDB_ROOT."objectManager.php?sClass=application&iId=$this->iAppId"; + return $sUrl; + } + + public function objectMakeLink() + { + $sLink = "objectMakeUrl()."\">". + $this->sName.""; + return $sLink; + } + + public static function objectGetDefaultSort() + { + return 'appId'; + } + + public static function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = 'default', $bAscending = TRUE, $oFilters = null) + { + $sLimit = ""; + $sOrdering = $bAscending ? "ASC" : "DESC"; + + if($sOrderBy == 'default') + { + if($sState == 'queued') + $sOrderBy = 'appId'; + else + $sOrderBy = 'appName'; + } + + $sExtraTables = ''; + $sWhereFilter = $oFilters ? $oFilters->getWhereClause() : ''; + $aOptions = $oFilters ? $oFilters->getOptions() : array('onlyDownloadable' => 'false', 'appCategory' => null); + + if($sWhereFilter || $aOptions['onlyDownloadable'] == 'true') + { + $sExtraTables = ",appVersion"; + $sBugzillaQuery = ''; + + /* We only query the bugzilla table when necessary; these queries + will hide apps without test results */ + if(strstr($sWhereFilter, 'versions.id')) + { + $sExtraTables .= ','.BUGZILLA_DB.'.versions'; + $sBugzillaQuery = ' AND versions.value = appVersion.ratingRelease + AND versions.product_id = '.BUGZILLA_PRODUCT_ID.' '; + } + + if($sWhereFilter) + $sWhereFilter = " AND $sWhereFilter"; + $sWhereFilter = " AND appVersion.state = 'accepted' + AND appVersion.appId = appFamily.appId + $sBugzillaQuery + $sWhereFilter"; + } + + if($aOptions['onlyDownloadable'] == 'true') + { + $sExtraTables .= ',appData'; + $sWhereFilter .= " AND appData.type = 'downloadurl' AND appData.versionId = appVersion.versionId AND appData.state = 'accepted'"; + } + if($aOptions['appCategory']) + { + $oCategory = new Category($aOptions['appCategory']); + $sWhereFilter .= ' AND ' . $oCategory->getSqlQueryPart(); + } + /* Should we add a limit clause to the query? */ + if($iRows || $iStart) + { + $sLimit = " LIMIT ?,?"; + + /* Selecting 0 rows makes no sense, so we assume the user wants to select all of them + after an offset given by iStart */ + if(!$iRows) + $iRows = application::objectGetEntriesCount($sState); + } + + $sQuery = "SELECT DISTINCT(appFamily.appId), appFamily.*, vendor.vendorName AS vendorName FROM appFamily, vendor$sExtraTables WHERE + appFamily.vendorId = vendor.vendorId + AND + appFamily.state = '?'$sWhereFilter"; + + if($sState != 'accepted' && !application::canEdit()) + { + /* Without global edit rights a user can only view his rejected apps */ + if($sState != 'rejected') + return FALSE; + + $sQuery .= " AND appFamily.submitterId = '?' ORDER BY ? ?$sLimit"; + if($sLimit) + { + $hResult = query_parameters($sQuery, $sState, + $_SESSION['current']->iUserId, $sOrderBy, + $sOrdering, $iStart, $iRows); + } else + { + $hResult = query_parameters($sQuery, $sState, + $_SESSION['current']->iUserId, $sOrderBy, + $sOrdering); + } + } else + { + $sQuery .= " ORDER BY ? ?$sLimit"; + if($sLimit) + { + $hResult = query_parameters($sQuery, $sState, $sOrderBy, $sOrdering, + $iStart, $iRows); + } else + { + $hResult = query_parameters($sQuery, $sState, $sOrderBy, $sOrdering); + } + } + + if(!$hResult) + return FALSE; + + return $hResult; + } + + public static function objectGetFilterInfo() + { + $oFilter = new FilterInterface(); + $aCategories = category::getOrderedList(); + $aCatNames = array(); + $aCatIds = array(); + + foreach($aCategories as $oCategory) + { + $aCatNames[] = $oCategory->sName; + $aCatIds[] = $oCategory->objectGetId(); + } + + $aLicenses = version::getLicenses(); + $aWineVersions = get_bugzilla_versions(); + $aWineVersionIds = get_bugzilla_version_ids(); + + $oFilter->AddFilterInfo('appVersion.rating', 'Rating', array(FILTER_EQUALS), FILTER_VALUES_ENUM, array('Platinum', 'Gold', 'Silver', 'Bronze', 'Garbage')); + $oFilter->AddFilterInfo('versions.id', 'Wine version', array(FILTER_EQUALS,FILTER_LESS_THAN,FILTER_GREATER_THAN), FILTER_VALUES_ENUM, $aWineVersionIds, $aWineVersions); + $oFilter->AddFilterInfo('appCategory', 'Category', array(FILTER_OPTION_ENUM), FILTER_VALUES_OPTION_ENUM, $aCatIds, $aCatNames); + $oFilter->AddFilterInfo('appVersion.license', 'License', array(FILTER_EQUALS), FILTER_VALUES_ENUM, $aLicenses); + $oFilter->AddFilterInfo('appFamily.appName', 'Name', array(FILTER_CONTAINS, FILTER_STARTS_WITH, FILTER_ENDS_WITH), FILTER_VALUES_NORMAL); + $oFilter->AddFilterInfo('onlyDownloadable', 'Only show downloadable apps', array(FILTER_OPTION_BOOL), FILTER_VALUES_OPTION_BOOL, array('false','true')); + return $oFilter; + } + + public static function objectGetSortableFields() + { + return array('submitTime', 'appName', 'appId', 'userName', 'vendorName'); + } + + public static function objectGetHeader($sState) + { + $oTableRow = new TableRowSortable(); + + if($sState == 'accepted') + { + $oTableRow->AddSortableTextCell('Application', 'appName'); + $oTableRow->AddSortableTextCelL('Entry#', 'appId'); + $oTableRow->AddTextCell('Description'); + } else + { + $oTableRow->AddSortableTextCell('Submission Date', 'submitTime'); + + /* Only show submitter when processing queued entries */ + $oTableRow->AddTextCell('Submitter'); + $oTableRow->AddSortableTextCell('Developer', 'vendorName'); + $oTableRow->AddSortableTextCell('Application', 'appName'); + } + return $oTableRow; + } + + public function objectGetTableRow() + { + $oUser = new user($this->iSubmitterId); + $oVendor = new vendor($this->iVendorId); + + $sVendor = $oVendor->objectMakeLink(); + + $oTableRow = new TableRow(); + + if($this->sState == 'accepted') + { + $oTableRow->AddTextCell($this->objectMakeLink()); + $oTableRow->AddTextCell($this->iAppId); + $oTableRow->AddTextCell(util_trim_description($this->sDescription)); + } else + { + $oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($this->sSubmitTime))); + $oTableRow->AddTextCell($oUser->objectMakeLink()); + $oTableRow->AddTextCell($sVendor); + $oTableRow->AddTextCell( $this->sName); + } + + $oOMTableRow = new OMTableRow($oTableRow); + return $oOMTableRow; + } + + public function objectGetState() + { + return $this->sState; + } + + public function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + return TRUE; + + if(isset($this) && is_object($this) && $this->iAppId) + { + if(maintainer::isUserSuperMaintainer($_SESSION['current'], + $this->iAppId)) + return TRUE; + + if($this->sState != 'accepted' && $this->iSubmitterId == + $_SESSION['current']->iUserId) + { + return TRUE; + } + + return FALSE; + } else + { + return FALSE; + } + } + + public function mustBeQueued() + { + if($_SESSION['current']->hasPriv("admin")) + return FALSE; + else + return TRUE; + } + + public function objectDisplayQueueProcessingHelp() + { + echo "

    This is the list of application entries waiting to be processed.

    \n"; + echo "

    To view and process an entry, use the links under ‘Action’

    "; + } + + public function objectDisplayAddItemHelp() + { + /* We don't display the full help on the page where you only input the app name */ + if(!$this->sName) + { + echo "

    First, please enter the name of the application you wish to add. "; + echo "This will allow you to determine whether there is already "; + echo "an entry for it in the database.

    \n"; + } else + { + echo "

    This page is for submitting new applications to be added to the\n"; + echo "database. The application will be reviewed by an AppDB Administrator,\n"; + echo "and you will be notified via e-mail if it is added to the database or rejected.

    \n"; + echo "

    Before continuing, please ensure that you have

    \n"; + echo "
      \n"; + echo "
    • Entered a valid version for this application. This is the application\n"; + echo " version, NOT the Wine version (which goes in the test results section of the template)
    • \n"; + echo "
    • Tested this application under Wine. There are tens of thousands of applications\n"; + echo " for Windows, we do not need placeholder entries in the database. Please enter as complete \n"; + echo " as possible test results in the version template provided below
    • \n"; + echo "

    "; + echo "

    Having app descriptions just sponsoring the app\n"; + echo "(yes, some vendors want to use the appdb for this) or saying ‘I haven't tried this app with Wine’ "; + echo "will not help Wine development or Wine users. Application descriptions should be exactly that and only that, \n"; + echo "they should not contain any information about how well the app works, just what the app is. The same applies to the \n"; + echo "version information, it should be only information on what is unique or different about that version of the application, \n"; + echo "not how well that version works or how great you think a new feature is.

    \n"; + echo "

    When you reach the \"Test Form\" part (What works, What doesn't work, etc) please be detailed \n"; + echo "about how well it worked and if any workarounds were needed but do NOT paste chunks of terminal output.

    \n"; + echo "

    Please write information in proper English with correct grammar and punctuation!

    \n"; + echo "Please only submit applications/versions that you have tested.\n"; + echo "Submissions without test information or not using the provided template will be rejected.\n"; + echo "If you are unable to see the in-browser editors below, please try Firefox, Mozilla or Opera browsers.\n"; + echo "

    After your application has been added, you will be able to submit screenshots for it, post"; + echo " messages in its forums or become a maintainer to help others trying to run the application.

    "; + } + } + + public static function objectGetEntriesCount($sState, $oFilters = null) + { + $sExtraTables = ''; + $sWhereFilter = $oFilters ? $oFilters->getWhereClause() : ''; + $aOptions = $oFilters ? $oFilters->getOptions() : array('onlyDownloadable' => 'false', 'appCategory' => null); + + if($sWhereFilter || $aOptions['onlyDownloadable'] == 'true') + { + $sExtraTables = ',appVersion'; + $sBugzillaQuery = ''; + + /* We only query the bugzilla table when necessary; these queries + will hide apps without test results */ + if(strstr($sWhereFilter, 'versions.id')) + { + $sExtraTables .= ','.BUGZILLA_DB.'.versions'; + $sBugzillaQuery = ' AND versions.value = appVersion.ratingRelease + AND versions.product_id = '.BUGZILLA_PRODUCT_ID.' '; + } + + if($sWhereFilter) + $sWhereFilter = " AND $sWhereFilter"; + $sWhereFilter = " AND appVersion.appId = appFamily.appId + $sBugzillaQuery + $sWhereFilter"; + } + + if($aOptions['onlyDownloadable'] == 'true') + { + $sExtraTables .= ',appData'; + $sWhereFilter .= " AND appData.type = 'downloadurl' AND appData.versionId = appVersion.versionId"; + } + if($aOptions['appCategory']) + { + $oCategory = new Category($aOptions['appCategory']); + $sWhereFilter .= ' AND ' . $oCategory->getSqlQueryPart(); + } + + if($sState != 'accepted' && !application::canEdit()) + { + /* Without edit rights users can only resubmit their rejected entries */ + if(!$bRejected) + return FALSE; + + $sQuery = "SELECT COUNT(DISTINCT(appFamily.appId)) as count FROM appFamily$sExtraTables WHERE + submitterId = '?' + AND + appFamily.state = '?'$sWhereFilter"; + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sState); + } else + { + $sQuery = "SELECT COUNT(DISTINCT(appFamily.appId)) as count FROM appFamily$sExtraTables WHERE appFamily.state = '?'$sWhereFilter"; + $hResult = query_parameters($sQuery, $sState); + } + + if(!$hResult) + return FALSE; + + if(!$oRow = query_fetch_object($hResult)) + return FALSE; + + return $oRow->count; + } + + public function getVersions($bOnlyAccepted = false, $bIncludeObsolete = TRUE, $bIncludeDeleted = false) + { + /* If no id is set we cannot query for the versions, but perhaps objects are already cached? */ + if(!$this->iAppId) + return $this->aVersions; + + $aVersions = array(); + + $hResult = $this->_internal_retrieve_all_versions($bOnlyAccepted, $bIncludeObsolete, $bIncludeDeleted); + + while($oRow = mysql_fetch_object($hResult)) + $aVersions[] = new version($oRow->versionId); + + return $aVersions; + } + + /* Make a drop-down list of this application's versions. Optionally set the default + versionId, a version to exclude and whether to not show obsolete versions */ + public function makeVersionDropDownList($sVarName, $iCurrentId = null, $iExclude = null, $bIncludeObsolete = TRUE) + { + $sMsg = "\n"; + + return $sMsg; + } + + public function objectAllowCreatingParents() + { + return true; + } + + public function objectSetParent($iNewId, $sClass = '') + { + $this->iVendorId = $iNewId; + } + + public function objectGetParent($sClass = '') + { + return new vendor($this->iVendorId); + } + + public function objectGetChildren($bIncludeDeleted = false) + { + return $this->objectGetChildrenClassSpecific('', $IncludeDeleted); + } + + public function objectGetChildrenClassSpecific($sClass = '', $bIncludeDeleted = false) + { + $aChildren = array(); + + /* Get versions */ + foreach($this->getVersions(false, true, $bIncludeDeleted) as $oVersion) + { + if($sClass != 'version') + $aChildren += $oVersion->objectGetChildren($bIncludeDeleted); + $aChildren[] = $oVersion; + } + + if($sClass == 'version') + return $aChildren; + + /* Get urls */ + $sQuery = "SELECT * FROM appData WHERE type = '?' AND appId = '?'"; + $hResult = query_parameters($sQuery, "url", $this->iAppId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oUrl = new url(0, $oRow); + $aChildren += $oUrl->objectGetChildren($bIncludeDeleted); + $aChildren[] = $oUrl; + } + + /* Get maintainers */ + $sQuery = "SELECT * FROM appMaintainers WHERE appId = '?' AND superMaintainer = '?'"; + $hResult = query_parameters($sQuery, $this->iAppId, '1'); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oMaintainer = new maintainer(0, $oRow); + $aChildren += $oMaintainer->objectGetChildren($bIncludeDeleted); + $aChildren[] = $oMaintainer; + } + + return $aChildren; + } + + public function objectMoveChildren($iNewId) + { + /* Keep track of how many children we have moved */ + $iCount = 0; + + foreach($this->aVersionsIds as $iVersionId) + { + $oVersion = new version($iVersionId); + $oVersion->iAppId = $iNewId; + if($oVersion->update()) + $iCount++; + else + return FALSE; + } + + /* If no errors occurred we return the number of moved children */ + return $iCount; + } + + public static function objectAllowMovingToNewParent() + { + return TRUE; + } + + public static function allowAnonymousSubmissions() + { + return FALSE; + } + + function objectAllowPurgingRejected() + { + return TRUE; + } + + public function objectGetSubmitTime() + { + return mysqltimestamp_to_unixtimestamp($this->sSubmitTime); + } + + public function objectGetId() + { + return $this->iAppId; + } + + public function objectShowAddEntry() + { + return TRUE; + } +} + +?> diff --git a/include/application_queue.php b/include/application_queue.php new file mode 100644 index 0000000..44d4901 --- /dev/null +++ b/include/application_queue.php @@ -0,0 +1,466 @@ +oApp = new application($iAppId, $oRow); + + $iVersionId = null; + $iVendorId = null; + + /* If this is an existing application then there must be a version + accompanying it */ + if($this->oApp->iAppId) + { + /* Normal users do not get a aVersionsIds property, so we have to fetch + the versionId manually. Normal users only have access to rejected + applications, unless they submitted them */ + if($_SESSION['current']->hasPriv("admin")) + { + $iVersionId = $this->oApp->aVersionsIds[0]; + } else if($this->oApp->objectGetState() == 'rejected' || + ($this->oApp->objectGetState() == 'queued' && + $this->oApp->objectGetSubmitterId() == $_SESSION['current']->iUserId)) + { + $sQuery = "SELECT versionId FROM appVersion WHERE appId = '?' LIMIT 1"; + $hResult = query_parameters($sQuery, $this->oApp->iAppId); + if($hResult) + { + if($oRow = query_fetch_object($hResult)) + $iVersionId = $oRow->versionId; + } + } + $iVendorId = $this->oApp->iVendorId; + } + + $this->oVendor = new vendor($iVendorId); + + $this->oVersionQueue = new version_queue($iVersionId); + } + + function create() + { + $bSuccess = TRUE; + + /* Create a new vendor if an existing one was not selected, and + assign the application to it */ + if(!$this->oApp->iVendorId) + { + $this->oVendor->create(); + $this->oApp->iVendorId = $this->oVendor->iVendorId; + } + + if(!$this->oApp->create()) + $bSuccess = FALSE; + + /* Assign the version to the new application */ + $this->oVersionQueue->oVersion->iAppId = $this->oApp->iAppId; + + if(!$this->oVersionQueue->create()) + $bSuccess = FALSE; + + return $bSuccess; + } + + function update() + { + $bSuccess = TRUE; + + /* If the vendor was already un-queued then the edit vendor form would not + have been displayed, and so the vendor name will not be set. Thus only + update the vendor if the name is set */ + if($this->oVendor->sName) + $this->oVendor->update(); + + if(!$this->oApp->update()) + $bSuccess = FALSE; + + if(!$this->oVersionQueue->update()) + $bSuccess = FALSE; + + return $bSuccess; + } + + function unQueue() + { + /* The vendor is not necessarily queued, as it could have existed on + beforehand */ + if($this->oVendor->objectGetState() != 'accepted') + $this->oVendor->unQueue(); + + $this->oApp->unQueue(); + $this->oVersionQueue->unQueue(); + + /* Has anyone submitted new versions while the app was queued? + If so we need to change their state from pending to queued */ + $aOtherVersions = $this->oApp->objectGetChildrenClassSpecific('version'); + foreach($aOtherVersions as $oVersion) + { + if($oVersion->objectGetState() == 'pending') + { + $oVersion->objectSetState('queued'); + $oVersion->update(); + } + } + } + + function reQueue() + { + $this->oApp->reQueue(); + $this->oVersionQueue->reQueue(); + } + + function reject() + { + $this->oVersionQueue->reject(); + $this->oApp->reject(); + } + + function purge() + { + $bSuccess = TRUE; + + if(!$this->oApp->purge()) + $bSuccess = FALSE; + + /* When deleting a duplicate app in the application queue, the version is moved + to another app and so when application_queue::delete() is called there is + no version child to delete, so check if the versionId is valid */ + if($this->oVersionQueue->oVersion->iVersionId) + { + if(!$this->oVersionQueue->purge()) + $bSuccess = FALSE; + } + + return $bSuccess; + } + + function delete() + { + $bSuccess = TRUE; + + if(!$this->oApp->delete()) + $bSuccess = FALSE; + + /* When deleting a duplicate app in the application queue, the version is moved + to another app and so when application_queue::delete() is called there is + no version child to delete, so check if the versionId is valid */ + if($this->oVersionQueue->oVersion->iVersionId) + { + if(!$this->oVersionQueue->delete()) + $bSuccess = FALSE; + } + + return $bSuccess; + } + + function objectGetChildren($bIncludeDeleted = false) + { + return $this->oApp->objectGetChildren($bIncludeDeleted); + } + + function objectGetSubmitterId() + { + return $this->oApp->objectGetSubmitterId(); + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return $this->oApp->objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + return $this->oApp->objectGetMail($sAction, $bMailSubmitter, $bParentAction); + } + + public function objectShowPreview() + { + if($this->oApp->sName) + return TRUE; + + return FALSE; + } + + function outputEditor($aClean = array()) + { + /* We ask the user for the application name first so as to avoid duplicate + submissons; a list of potential duplicates is displayed on the next page */ + if(!$this->oApp->sName) + { + echo "
    \n"; + echo "
    \n"; + echo "Application name:\n"; + echo "
    \n"; + echo "
    \n"; + echo "
    \n"; + echo "
    \n"; + echo "\n"; + echo "\n"; + echo "
    \n"; + } else + { + /* Show potential duplicates */ + echo html_frame_start("Potential duplicate applications in the ". + "database","90%","",0); + $this->displayDuplicates(); + echo html_frame_end(" "); + + $this->oApp->outputEditor(); + + /* Display the new vendor form for new applications or if we + are processing an application and the vendor is queued */ + if(!$this->oApp->iAppId || $this->oVendor->objectGetState() != 'accepted') + { + echo html_frame_start("New Developer", "90%"); + $this->oVendor->outputEditor(); + echo html_frame_end(); + } + + $this->oVersionQueue->oVersion->outputEditor(); + + global $aClean; + + echo $this->oVersionQueue->oDownloadUrl->outputEditorSingle( + $this->oVersionQueue->oVersion->iVersionId, $aClean); + + $this->oVersionQueue->oTestDataQueue->outputEditor(); + + /* Allow the user to choose whether to preview the application view + or the version view. Application view is default */ + echo html_frame_start("Select What to Preview"); + $sPreviewVersion = $aClean['bPreviewVersion'] ? $aClean['bPreviewVersion'] : ""; + + $shPreviewApp = ''; + $shPreviewVersion = ''; + + if($sPreviewVersion == "true") + $shPreviewVersion = ' checked="checked"'; + else + $shPreviewApp = ' checked="checked"'; + + echo " Preview application
    \n"; + echo " Preview version\n"; + echo html_frame_end(); + } + } + + function getOutputEditorValues($aClean) + { + $this->oApp->getOutputEditorValues($aClean); + $this->oVersionQueue->getOutputEditorValues($aClean); + $this->oVendor->getOutputEditorValues($aClean); + } + + function checkOutputEditorInput($aClean) + { + /* We want outputEditor() to be called again so we can display the main + app form. No erros are displayed since we only return TRUE */ + if($this->oApp->sName && !$aClean['bMainAppForm']) + return TRUE; + + $sErrors = $this->oApp->checkOutputEditorInput($aClean); + $sErrors .= $this->oVersionQueue->checkOutputEditorInput($aClean); + return $sErrors; + } + + function objectGetState() + { + return $this->oApp->objectGetState(); + } + + function canEdit() + { + return $this->oApp->canEdit(); + } + + function mustBeQueued() + { + return $this->oApp->mustBeQueued(); + } + + function displayDuplicates() + { + echo "Like matches
    \n"; + $this->displayDuplicateTable(searchForApplication($this->oApp->sName, $this->oApp->objectGetId())); + echo "
    \n"; + echo "Partial matches
    \n"; + $this->displayDuplicateTable(searchForApplicationPartial($this->oApp->sName, $this->oApp->objectGetId())); + } + + function displayDuplicateTable($hResult) + { + /* Exit if the MySQL handle is invalid */ + if($hResult === FALSE) + return FALSE; + + /* There's no point in displaying an empty table */ + if($hResult === null || (query_num_rows($hResult) == 0)) + { + echo "No matches.
    \n"; + return; + } + + $aHeader = array( + "Application name", + "Description", + "No. versions" + ); + + /* We can only move data if the current application already exists, and + we have admin privileges */ + if($this->oApp->iAppId && $_SESSION['current']->hasPriv("admin")) + { + $bCanMove = TRUE; + $aHeader[] = array("Move data", 'width="80"'); + } else + { + $bCanMove = FALSE; + } + + echo ""; + echo html_tr($aHeader, "color4"); + + for($i = 0; $oRow = query_fetch_object($hResult); $i++) + { + $oApp = new application($oRow->appId); + $aCells = array( + $oApp->objectMakeLink(), + util_trim_description($oApp->sDescription), + sizeof($oApp->aVersionsIds) + ); + + if($bCanMove) + { + $aCells[] = "oApp->iAppId."&iNewId=".$oApp->iAppId. + "\">Move data"; + } + echo html_tr($aCells, ($i % 2) ? "color0" : "color1"); + } + echo "
    "; + } + + function objectGetCustomVars($sAction) + { + switch($sAction) + { + case "preview": + return array("bPreviewVersion"); + + default: + return 0; + } + } + + function display($aClean = array()) + { + /* Cache the version object if it is not in the database */ + if(!$this->oVersionQueue->objectGetId()) + $this->oApp->aVersions = array($this->oVersionQueue->oVersion); + + $sPreviewVersion = $aClean['bPreviewVersion'] ? $aClean['bPreviewVersion'] : ""; + + if($sPreviewVersion == "true") + { + $this->oVersionQueue->oVersion->oApp = $this->oApp; + $this->oVersionQueue->display(); + } else + { + $this->oApp->display(); + } + } + + function objectMakeUrl() + { + return $this->oApp->objectMakeUrl(); + } + + function objectMakeLink() + { + return $this->oApp->objectMakeLink(); + } + + function objectGetItemsPerPage($sState = 'accepted') + { + return $this->oApp->objectGetItemsPerPage($sState); + } + + function objectGetEntriesCount($sState) + { + return $this->oApp->objectGetEntriesCount($sState); + } + + public static function objectGetDefaultSort() + { + return application::objectGetDefaultSort(); + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "appId", $bAscending = TRUE) + { + return $this->oApp->objectGetEntries($sState, $iRows, $iStart, + $sOrderBy, $bAscending); + } + + public static function objectGetSortableFields() + { + return application::objectGetSortableFields(); + } + + function objectGetHeader($sState) + { + return $this->oApp->objectGetHeader($sState); + } + + function objectGetTableRow() + { + return $this->oApp->objectGetTableRow(); + } + + function objectMoveChildren($iNewId) + { + return $this->oApp->objectMoveChildren($iNewId); + } + + function objectDisplayQueueProcessingHelp() + { + return application::objectDisplayQueueProcessingHelp(); + } + + function objectDisplayAddItemHelp() + { + $this->oApp->objectDisplayAddItemHelp(); + } + + function allowAnonymousSubmissions() + { + return application::allowAnonymousSubmissions(); + } + + function objectAllowPurgingRejected() + { + return $this->oApp->objectAllowPurgingRejected(); + } + + public function objectGetSubmitTime() + { + return $this->oApp->objectGetSubmitTime(); + } + + function objectGetId() + { + return $this->oApp->objectGetId(); + } +} + +?> diff --git a/include/bugs.php b/include/bugs.php new file mode 100644 index 0000000..4318c46 --- /dev/null +++ b/include/bugs.php @@ -0,0 +1,686 @@ +iLinkId = $oRow->linkId; + $this->iBug_id = $oRow->bug_id; + $this->iVersionId = $oRow->versionId; + $this->bQueued = ($oRow->state=='queued') ? true : false; + $this->sSubmitTime = $oRow->submitTime; + $this->iSubmitterId = $oRow->submitterId; + /* lets fill in some blanks */ + if ($this->iBug_id) + { + $sQuery = "SELECT * + FROM bugs + WHERE bug_id = ".$this->iBug_id; + if($hResult = query_bugzilladb($sQuery)) + { + $oRow = query_fetch_object($hResult); + if($oRow) + { + $this->sShort_desc = $oRow->short_desc; + $this->sBug_status = $oRow->bug_status; + $this->sResolution = $oRow->resolution; + } + } + } + } + } + + + /** + * Creates a new Bug. + */ + function create() + { + $oVersion = new Version($this->iVersionId); + + // Security, if we are not an administrator or a maintainer, + // the Bug must be queued. + if($this->mustBeQueued()) + { + $this->bQueued = true; + } else + { + $this->bQueued = false; + } + + /* lets check for a valid bug id */ + if(!is_numeric($this->iBug_id)) + { + addmsg($this->iBug_id." is not a valid bug number.", "red"); + return false; + } + + /* check that bug # exists in bugzilla*/ + $sQuery = "SELECT * + FROM bugs + WHERE bug_id = ".$this->iBug_id; + if(query_num_rows(query_bugzilladb($sQuery, "checking bugzilla")) == 0) + { + addmsg("There is no bug in Bugzilla with that bug number.", "red"); + return false; + } + + /* Check for duplicates */ + if($this->isDuplicate()) + { + addmsg("The Bug link has already been submitted.", "red"); + return false; + } + + /* passed the checks so lets insert the puppy! */ + $hResult = query_parameters("INSERT INTO buglinks (versionId, bug_id, ". + "submitTime, submitterId, state) ". + "VALUES('?', '?', ?, '?', '?')", + $this->iVersionId, $this->iBug_id, + "NOW()", + $_SESSION['current']->iUserId, + $this->bQueued ? 'queued' : 'accepted'); + if($hResult) + { + $this->iLinkId = query_appdb_insert_id(); + + $this->SendNotificationMail(); + + return true; + } else + { + addmsg("Error while creating a new Bug link.", "red"); + return false; + } + } + + function purge() + { + return $this->delete(); + } + + /** + * Deletes the Bug from the database. + * and request its deletion from the filesystem (including the thumbnail). + * + * Return true if successful, false if an error occurs + */ + function delete() + { + $sQuery = "DELETE FROM buglinks + WHERE linkId = '?'"; + if(!($hResult = query_parameters($sQuery, $this->iLinkId))) + return false; + + return true; + } + + /** + * Move Bug out of the queue. + */ + function unQueue() + { + // If we are not in the queue, we can't move the Bug out of the queue. + if(!$this->bQueued) + return false; + + if(query_parameters("UPDATE buglinks SET state = '?' WHERE linkId='?'", + 'accepted', $this->iLinkId)) + { + $this->bQueued = false; + // we send an e-mail to interested people + $this->mailSubmitter(); + $this->SendNotificationMail(); + // the Bug has been unqueued + addmsg("The Bug has been unqueued.", "green"); + } + } + + function update() + { + $oBug = new bug($this->iLinkId); + + // There is no need to have two links to a bug. The update is still + // considered successful + if($this->isDuplicate()) + return $this->delete(); + + if($this->iVersionId && $this->iVersionId != $oBug->iVersionId) + { + $hResult = query_parameters("UPDATE buglinks SET versionId = '?' + WHERE linkId = '?'", + $this->iVersionId, $this->iLinkId); + + if(!$hResult) + return false; + } + + return true; + } + + /* Checks whether the version already has a link for this bug */ + public function isDuplicate() + { + $sQuery = "SELECT COUNT(linkId) as count + FROM buglinks + WHERE versionId = '?' + AND bug_id = '?'"; + if($hResult = query_parameters($sQuery, $this->iVersionId, $this->iBug_id)) + { + if(($oRow = query_fetch_object($hResult))) + { + return $oRow->count > 0; + } + } + return false; + } + + function mailSubmitter($bRejected=false) + { + global $aClean; + if(!isset($aClean['sReplyText'])) + $aClean['sReplyText'] = ""; + + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + $sAppName = Version::fullName($this->iVersionId); + if(!$bRejected) + { + $sSubject = "Submitted Bug Link accepted"; + $sMsg = "The bug link you submitted between Bug ".$this->iBug_id." and ". + $sAppName." has been accepted."; + } else + { + $sSubject = "Submitted Bug Link rejected"; + $sMsg = "The bug link you submitted between Bug ".$this->iBug_id." and ". + $sAppName." has been deleted."; + } + $sMsg .= $aClean['sReplyText']."\n"; + $sMsg .= "We appreciate your help in making the Application Database better for all users."; + + mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg); + } + } + + + function SendNotificationMail($bDeleted=false) + { + $sAppName = version::fullName($this->iVersionId); + $oVersion = new version($this->iVersionId); + + //show the application version URL and the bug URL + $sMsg = $oVersion->objectMakeUrl()."\n\n"; + $sMsg .= BUGZILLA_ROOT."show_bug.cgi?id=".$this->iBug_id."\n"; + + if(!$bDeleted) + { + if(!$this->bQueued) + { + $sSubject = "Link between Bug ".$this->iBug_id." and ".$sAppName." added by ".$_SESSION['current']->sRealname; + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + $sMsg .= "This Bug Link has been submitted by ".$oSubmitter->sRealname.".\n"; + } + addmsg("The Bug Link was successfully added into the database.", "green"); + } else // Bug Link queued. + { + $sSubject = "Link between Bug ".$this->iBug_id." and ".$sAppName." submitted by ".$_SESSION['current']->sRealname; + $sMsg .= "This Bug Link has been queued.\n"; + addmsg("The Bug Link you submitted will be added to the database after being reviewed.", "green"); + } + } else // Bug Link deleted. + { + $sSubject = "Link between Bug ".$this->iBug_id." and ".$sAppName." deleted by ".$_SESSION['current']->sRealname; + addmsg("Bug Link deleted.", "green"); + } + + $sEmail = User::get_notify_email_address_list(null, $this->iVersionId); + if($sEmail) + { + mail_appdb($sEmail, $sSubject ,$sMsg); + } + } + + function objectGetSubmitterId() + { + return $this->iSubmitterId; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + /* We don't do this at the moment */ + return array(null, null, null); + } + + public function objectGetParent($sClass = '') + { + return new version($this->iVersionId); + } + + public function objectSetParent($iNewId, $sClass = '') + { + $this->iVersionId = $iNewId; + } + + function objectGetChildren($bIncludeDeleted = false) + { + return array(); + } + + /* Get a list of bugs submitted by a given user */ + function listSubmittedBy($iUserId, $bQueued = true) + { + $hResult = query_parameters("SELECT appFamily.appName, buglinks.versionId, appVersion.versionName, buglinks.submitTime, buglinks.bug_id, buglinks.linkId FROM buglinks, appFamily, appVersion WHERE appFamily.appId = appVersion.appId AND buglinks.versionId = appVersion.versionId AND buglinks.state = '?' AND buglinks.submitterId = '?' ORDER BY buglinks.versionId", $bQueued ? 'queued' : 'accepted', $iUserId); + + if(!$hResult || !query_num_rows($hResult)) + return FALSE; + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetAlign("center"); + + // setup the table header + $oTableRow = new TableRow(); + $oTableRow->AddTextCell('Version'); + $oTableRow->AddTextCell('Bug #', 'width="50"'); + $oTableRow->AddTextCell('Status', 'width="80"'); + $oTableRow->AddTextCell('Resolution', 'width="110"'); + $oTableRow->AddTextCell('Description', 'Submit time'); + $oTableRow->AddTextCell('Submit time'); + + if($bQueued) + $oTableRow->addTextCell('Action'); + + $oTableRow->SetClass('color4'); + $oTable->AddRow($oTableRow); + + for($i = 1; $oRow = query_fetch_object($hResult); $i++) + { + $oTableRow = new TableRow(); + + $oTableRow->AddTextCell(version::fullNameLink($oRow->versionId)); + $oTableRow->AddTextCell(''.$oRow->bug_id.''); + $oTableRow->AddTextCell($oBug->sBug_status); + $oTableRow->AddTextCell($oBug->sResolution); + $oTableRow->AddTextCell($oBug->sShort_desc); + $oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($oRow->submitTime))); + + if($bQueued) + { + $oM = new objectManager('bug'); + $oM->setReturnTo(array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : ""); + $shDeleteLink = 'delete'; + $oTableRow->addTextCell(" [ $shDeleteLink ]"); + } + + $oTableRow->SetClass(($i % 2 ) ? 'color0' : 'color1'); + $oTable->AddRow($oTableRow); + } + + return $oTable->GetString(); + } + + function isOpen() + { + return ($this->sBug_status != 'RESOLVED' && $this->sBug_status != 'CLOSED'); + } + + function allowAnonymousSubmissions() + { + return false; + } + + function mustBeQueued() + { + $oVersion = new version($this->iVersionId); + + if($_SESSION['current']->hasPriv("admin") || + $_SESSION['current']->isMaintainer($oVersion->iVersionId) || + $_SESSION['current']->isSuperMaintainer($oVersion->iAppId)) + { + return false; + } + + return true; + } + + function objectGetId() + { + return $this->iLinkId; + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true) + { + $sLimit = ""; + + /* Selecting 0 rows makes no sense, so we assume the user + wants to select all of them + after an offset given by iStart */ + if(!$iRows) + $iRows = bug::objectGetEntriesCount($sState); + + $sQuery = "select * from buglinks where state = '?' LIMIT ?, ?"; + $hResult = query_parameters($sQuery, $sState, $iStart, $iRows); + return $hResult; + } + + function objectGetEntriesCount($sState) + { + $sQuery = "select count(*) as cnt from buglinks where state = '?'"; + $hResult = query_parameters($sQuery, $sState); + $oRow = mysql_fetch_object($hResult); + return $oRow->cnt; + } + + function objectGetHeader() + { + $oTableRow = new TableRow(); + + $oTableRow->AddTextCell("Bug #"); + + $oTableCell = new TableCell("Status"); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + $oTableRow->AddTextCell("Bug Description"); + + $oTableCell = new TableCell("Application Name"); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell("Application Description"); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell("Version"); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + return $oTableRow; + } + + // returns a table row + function objectGetTableRow() + { + $oTableRow = new TableRow(); + + $oVersion = new version($this->iVersionId); + $oApp = new application($oVersion->iAppId); + + $oTableCell = new TableCell($this->iBug_id); + $oTableCell->SetAlign("center"); + $oTableCell->SetCellLink(BUGZILLA_ROOT.'show_bug.cgi?id='.$this->iBug_id); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell($this->sBug_status); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + $oTableRow->AddTextCell($this->sShort_desc); + + $oTableRow->AddTextCell($oApp->objectMakeLink()); + + $oTableRow->AddTextCell(util_trim_description($oApp->sDescription)); + + $oTableRow->AddTextCell($oVersion->objectMakeLink()); + + $oOMTableRow = new OMTableRow($oTableRow); + + // enable the deletion link, the objectManager will check + // for appropriate permissions before adding the link + $oOMTableRow->SetHasDeleteLink(true); + + return $oOMTableRow; + } + + function objectMakeUrl() + { + $oManager = new objectManager("bug", "View Bug"); + return $oManager->makeUrl("view", $this->objectGetId()); + } + + function objectMakeLink() + { + $sLink = "objectMakeUrl()."\">". + $this->sShort_desc.""; + return $sLink; + } + + function objectGetState() + { + return ($this->bQueued) ? 'queued' : 'accepted'; + } + + function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + { + return true; + } else if($this->iVersionId) + { + if(maintainer::isUserMaintainer($_SESSION['current'], + $this->iVersionId)) + { + return true; + } + + if($this->iSubmitterId == $_SESSION['current']->iUserId) + return true; + } + + return false; + } + + function objectGetItemsPerPage($sState = 'accepted') + { + $aItemsPerPage = array(25, 50, 100, 200); + $iDefaultPerPage = 25; + return array($aItemsPerPage, $iDefaultPerPage); + } + + function display() + { + $oTable = new Table(); + $oTable->SetAlign("center"); + $oTable->SetClass("color0"); + $oTable->SetCellPadding(2); + + $oHeaderRow = $this->objectGetHeader(); + $oHeaderRow->SetClass("color4"); + $oTable->AddRow($oHeaderRow); + + $oDataRow = $this->objectGetTableRow(); + $oDataRow->GetTableRow()->SetClass("color0"); + $oTable->AddRow($oDataRow); + + echo $oTable->GetString(); + } + + function objectHideReject() + { + return TRUE; + } + + // NOTE: we don't have any editing support for this entry at this time + // so output the entry and a field to identify the bug id + function outputEditor() + { + $this->display(); + echo ''; + echo ''; + } + + function getOutputEditorValues($aClean) + { + $this->iBug_id = $aClean['iBuglinkId']; + + if($aClean['iVersionId']) + $this->iVersionId = $aClean['iVersionId']; + } +} + + +/* + * Bug Link functions that are not part of the class + */ + +function view_version_bugs($iVersionId = null, $aBuglinkIds) +{ + global $aClean; + + $bCanEdit = FALSE; + $oVersion = new Version($iVersionId); + + // Security, if we are an administrator or a maintainer, we can remove or ok links. + if(($_SESSION['current']->hasPriv("admin") || + $_SESSION['current']->isMaintainer($oVersion->iVersionId) || + $_SESSION['current']->isSuperMaintainer($oVersion->iAppId))) + { + $bCanEdit = TRUE; + } + + //start format table + if($_SESSION['current']->isLoggedIn()) + { + echo "
    \n"; + } + echo html_frame_start("Known bugs","98%",'',0); + echo "\n\n"; + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + + if($bCanEdit == true) + { + echo " \n"; + echo " \n"; + } + echo "\n\n"; + + $c = 0; + foreach($aBuglinkIds as $iBuglinkId) + { + $oBuglink = new Bug($iBuglinkId); + + if ( + (!isset($aClean['sAllBugs']) && $oBuglink->isOpen() ) + || + isset($aClean['sAllBugs']) + ) + { + // set row color + $bgcolor = ($c % 2 == 0) ? "color0" : "color1"; + + //display row + echo "\n"; + echo "\n"; + echo "\n"; + echo "","\n"; + echo "","\n"; + echo "\n"; + + + if($bCanEdit == true) + { + $oM = new objectManager("bug"); + $oM->setReturnTo($oVersion->objectMakeUrl()); + echo "\n"; + if ($oBuglink->bQueued) + { + echo "\n"; + } else + { + echo "\n"; + } + + } + echo "\n\n"; + + + $c++; + } + } + + if($_SESSION['current']->isLoggedIn()) + { + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + } + echo '
    Bug #DescriptionStatusResolutionOther apps affectedDeleteChecked
    ".$oBuglink->iBug_id."".$oBuglink->sShort_desc."".$oBuglink->sBug_status."".$oBuglink->sResolution."View[delete][OK]Yes
    ',"\n"; + $sBuglinkId = isset($aClean['buglinkId']) ? $aClean['buglinkId'] : ''; + echo '
    ',"\n"; + + // show only open link + if ( isset( $aClean['sAllBugs'] ) ) + { + $sURL = str_replace( '&sAllBugs', '', $_SERVER['REQUEST_URI'] ); + $sLink = 'Show open bugs'; + } + // show all link + else + { + $sURL = $_SERVER['REQUEST_URI'] . '&sAllBugs'; + $sLink = 'Show all bugs'; + } + + echo '
    ' . $sLink .'
    '; + echo html_frame_end(); +} + +?> diff --git a/include/category.php b/include/category.php new file mode 100644 index 0000000..6156d1a --- /dev/null +++ b/include/category.php @@ -0,0 +1,576 @@ +iCatId = $iCatId; + $this->iParentId = $oRow->catParent; + $this->sName = $oRow->catName; + $this->sDescription = $oRow->catDescription; + } + } + + /* + * We fetch applicationsIds. + */ + $sQuery = "SELECT appId + FROM appFamily + WHERE catId = '?' + AND state = 'accepted' ORDER BY appName"; + if($hResult = query_parameters($sQuery, $iCatId)) + { + while($oRow = query_fetch_object($hResult)) + { + $this->aApplicationsIds[] = $oRow->appId; + } + } + + /* + * We fetch subcatIds. + */ + $sQuery = "SELECT catId + FROM appCategory + WHERE catParent = '?' ORDER BY catName;"; + if($hResult = query_parameters($sQuery, $iCatId)) + { + while($oRow = query_fetch_object($hResult)) + { + $this->aSubcatsIds[] = $oRow->catId; + } + } + } + } + + + /** + * Creates a new category. + */ + function create() + { + $hResult = query_parameters("INSERT INTO appCategory (catName, catDescription, catParent) ". + "VALUES('?', '?', '?')", + $this->sName, $this->sDescription, $this->iParentId); + if($hResult) + { + $this->iCatId = query_appdb_insert_id(); + $this->category($this->iCatId); + return true; + } + + return false; + } + + /** + * Update category. + * Returns true on success and false on failure. + */ + function update() + { + if(!query_parameters("UPDATE appCategory SET catName = '?', catDescription = '?', catParent = '?' WHERE catId = '?'", + $this->sName, $this->sDescription, $this->iParentId, $this->iCatId)) + return false; + + return true; + } + + + /** + * Deletes the category from the database. + */ + function delete() + { + if(!$this->canEdit()) + return false; + + if(sizeof($this->aApplicationsIds)>0) + return FALSE; + + $sQuery = "DELETE FROM appCategory + WHERE catId = '?' + LIMIT 1"; + query_parameters($sQuery, $this->iCatId); + + return true; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetChildren() + { + /* We don't have any (or we do, sort of, but we don't use them for anything at the moment) */ + return array(); + } + + /* Get a category's subcategory objects. Names are indented according + to subcategory level */ + function getSubCatList($iLevel = 0) + { + $aOut = array(); + $iId = $this->iCatId ? $this->iCatId : 0; + + $sIndent = ''; + for($i = 0; $i < $iLevel; $i++) + $sIndent .= '   '; + + $hResult = query_parameters("SELECT * FROM appCategory WHERE catParent = '?' + ORDER BY catName", $iId); + + while($oRow = mysql_fetch_object($hResult)) + { + $oCat = new category($oRow->catId); + $oCat->sName = $sIndent.$oCat->sName; + $aOut[] = $oCat; + $aOut = array_merge($aOut, $oCat->getSubCatList($iLevel + 1)); + } + return $aOut; + } + + /* Get all category objects, ordered and with category names indented + according to subcategory level. + Optionally includes the 'Main' top category. */ + static function getOrderedList($bIncludeMain = false) + { + $oCat = new category(); + + if(!$bIncludeMain) + return $oCat->getSubCatList(0); + + $oCat->sName = 'Main'; + $aCats = array($oCat); + $aCats = array_merge($aCats, $oCat->getSubCatList(1)); + + return $aCats; + } + + /* Returns an SQL statement that will match items in the current category + and all sub-categories */ + public function getSqlQueryPart() + { + $sRet = ''; + $aSubCats = $this->getSubCatList(); + $sRet .= " ( catId = '{$this->iCatId}' "; + foreach($aSubCats as $oCat) + { + $iCatId = $oCat->objectGetId(); + $sRet .= " OR catId = '$iCatId' "; + } + $sRet .= ") "; + + return $sRet; + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + /* We don't send notification mails */ + return array(null, null, null); + } + + /** + * returns a path like: + * + * { ROOT, Games, Simulation } + */ + function getCategoryPath() + { + $aPath = array(); + $iCatId = $this->iCatId; + + /* loop, working up through categories until we have no parent */ + while($iCatId != 0) + { + $hResult = query_parameters("SELECT catName, catId, catParent FROM appCategory WHERE catId = '?'", + $iCatId); + if(!$hResult || query_num_rows($hResult) != 1) + break; + $oCatRow = query_fetch_object($hResult); + $aPath[] = array($oCatRow->catId, $oCatRow->catName); + $iCatId = $oCatRow->catParent; + } + $aPath[] = array(0, "ROOT"); + return array_reverse($aPath); + } + + /* return the total number of applications in this category */ + function getApplicationCount($depth = null) + { + $MAX_DEPTH = 5; + + if($depth) + $depth++; + else + $depth = 0; + + /* if we've reached our max depth, just return 0 and stop recursing */ + if($depth >= $MAX_DEPTH) + return 0; + + $totalApps = 0; + + /* add on all apps in each category this category includes */ + if($this->aSubcatsIds) + { + while(list($i, $iSubcatId) = each($this->aSubcatsIds)) + { + $subCat = new Category($iSubcatId); + $totalApps += $subCat->getApplicationCount($depth); + } + } + + $totalApps += sizeof($this->aApplicationsIds); /* add on the apps at this category level */ + + return $totalApps; + } + + /** + * create the Category: line at the top of appdb pages$ + */ + function make_cat_path($aPath, $iAppId = '', $iVersionId = '') + { + $sStr = ""; + $iCatCount = 0; + while(list($iCatIdx, list($iCatId, $sName)) = each($aPath)) + { + if($sName == "ROOT") + $sCatname = "Main"; + else + $sCatname = $sName; + + if ($iCatCount > 0) $sStr .= " > "; + $sStr .= html_ahref($sCatname,"objectManager.php?sClass=category&iId=$iCatId&sAction=view&sTitle=Browse+Applications"); + $iCatCount++; + } + + if($iAppId) + { + $oApp = new Application($iAppId); + if($iVersionId) + { + $oVersion = new Version($iVersionId); + $sStr .= " > ".$oApp->objectMakeLink(); + $sStr .= " > ".$oVersion->sName; + } else + { + $sStr .= " > ".$oApp->sName; + } + } + + return $sStr; + } + + public function objectGetState() + { + // We currenly don't queue categories + return 'accepted'; + } + + function objectGetId() + { + return $this->iCatId; + } + + public function objectMakeLink() + { + return '{$this->sName}'"; + } + + public function objectMakeUrl() + { + return BASE."objectManager.php?sClass=category&sAction=view&iId={$this->iCatId}&sTitle=Browse+Applications"; + } + + public function objectAllowNullId($sAction) + { + switch($sAction) + { + case 'view': + return true; + + default: + return false; + } + } + + function objectGetSubmitterId() + { + /* We don't log that */ + return 0; + } + + function objectGetCustomVars($sAction) + { + switch($sAction) + { + case 'add': + return array('iParentId'); + + default: + return null; + } + } + + function outputEditor($aValues = null) + { + $aCategories = category::getOrderedList(true); + $aCatNames = array(); + $aCatIds = array(); + + $iParentId = $this->iParentId; + if(!$iParentId && $aValues) + $iParentId = getInput('iParentId', $aValues); + + foreach($aCategories as $oCategory) + { + $aCatNames[] = $oCategory->sName; + $aCatIds[] = $oCategory->objectGetId(); + } + + echo " + + + + + + + + + + + + +
    Category name + sName."\"> +
    Description + sDescription."\"> +
    Parent + ".html_select("iParentId",$aCatIds,$iParentId, $aCatNames)." +
    "; + } + + function allowAnonymousSubmissions() + { + return FALSE; + } + + function getOutputEditorValues($aClean) + { + $this->sName = $aClean['sName']; + $this->iParentId = $aClean['iParentId']; + $this->sDescription = $aClean['sDescription']; + } + + function mustBeQueued() + { + return $_SESSION['current']->hasPriv('admin'); + } + + function canEdit() + { + return $_SESSION['current']->hasPriv('admin'); + } + + /** + * display the full path of the Category we are looking at + */ + function displayPath($appId, $versionId = '') + { + $sCatFullPath = Category::make_cat_path($this->getCategoryPath(), $appId, $versionId); + echo html_frame_start("",'98%','',2); + echo "

    Category: ". $sCatFullPath ."
    \n"; + echo html_frame_end(); + } + + public function display() + { + // list sub categories + $sCatFullPath = Category::make_cat_path($this->getCategoryPath()); + $aSubs = $this->aSubcatsIds; + + echo "

    \n"; + + // Allow editing categories + if($this->canEdit()) + { + $oM = new objectManager('category', '', $this->iCatId); + $oM->setReturnTo($this->objectMakeUrl()); + echo "

    \n"; + echo 'iCatId}\">Add";; + if($this->iCatId) // We can't edit the 'Main' category + { + echo '     '; + echo 'Edit'; + echo '     '; + echo 'Delete'; + } + echo "

    \n"; + } + + // Output sub-categories + if($aSubs) + { + echo html_frame_start("",'98%','',2); + echo "

    Category: ". $sCatFullPath ."
    \n"; + echo html_frame_end(); + + echo html_frame_start("","98%","",0); + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetBorder(0); + $oTable->SetCellPadding(3); + $oTable->SetCellSpacing(1); + + $oTableRow = new TableRow(); + $oTableRow->SetClass("color4"); + $oTableRow->AddTextCell("Sub Category"); + $oTableRow->AddTextCell("Description"); + $oTableRow->AddTextCell("No. Apps"); + $oTable->SetHeader($oTableRow); + + while(list($i,$iSubcatId) = each($aSubs)) + { + $oSubCat= new Category($iSubcatId); + + //set row color + $sColor = ($i % 2) ? "color0" : "color1"; + + $oTableRowHighlight = GetStandardRowHighlight($i); + + $sUrl = $oSubCat->objectMakeUrl(); + + $oTableRowClick = new TableRowClick($sUrl); + $oTableRowClick->SetHighlight($oTableRowHighlight); + + //get number of apps in this sub-category + $iAppcount = $oSubCat->getApplicationCount(); + + //format desc + $sDesc = substr(stripslashes($oSubCat->sDescription),0,70); + + //display row + $oTableRow = new TableRow(); + $oTableRow->SetClass($sColor); + $oTableRow->SetRowClick($oTableRowClick); + + $oTableCell = new TableCell($oSubCat->sName); + $oTableCell->SetCellLink($sUrl); + $oTableRow->AddCell($oTableCell); + $oTableRow->AddTextCell("$sDesc  "); + $oTableRow->AddTextCell("$iAppcount  "); + + $oTable->AddRow($oTableRow); + } + + // output the table + echo $oTable->GetString(); + + echo html_frame_end( count($aSubs) . ' categories'); + } + + + // list applications in this category + $aApps = $this->aApplicationsIds; + if($aApps) + { + echo html_frame_start("",'98%','',2); + echo "

    Category: ". $sCatFullPath ."
    \n"; + echo html_frame_end(); + + echo html_frame_start("","98%","",0); + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetBorder(0); + $oTable->SetCellPadding(3); + $oTable->SetCellSpacing(1); + + $oTableRow = new TableRow(); + $oTableRow->SetClass("color4"); + $oTableRow->AddTextCell("Application name"); + $oTableRow->AddTextCell("Description"); + $oTableRow->AddTextCell("No. Versions"); + + $oTable->SetHeader($oTableRow); + + while(list($i, $iAppId) = each($aApps)) + { + $oApp = new Application($iAppId); + + //set row color + $sColor = ($i % 2) ? "color0" : "color1"; + + $oTableRowHighlight = GetStandardRowHighlight($i); + + $sUrl = $oApp->objectMakeUrl(); + + $oTableRowClick = new TableRowClick($sUrl); + $oTableRowClick->SetHighlight($oTableRowHighlight); + + //format desc + $sDesc = util_trim_description($oApp->sDescription); + + //display row + $oTableRow = new TableRow(); + $oTableRow->SetRowClick($oTableRowClick); + $oTableRow->SetClass($sColor); + $oTableRow->AddTextCell($oApp->objectMakeLink()); + $oTableRow->AddTextCell("$sDesc  "); + $oTableRow->AddTextCell(sizeof($oApp->aVersionsIds)); + + $oTable->AddRow($oTableRow); + } + + // output table + echo $oTable->GetString(); + + echo html_frame_end( count($aApps) . " applications in this category"); + } + + // Show a message if this category is empty + if(!$aApps && !$aSubs) + { + echo html_frame_start("",'98%','',2); + echo "

    Category: ". $sCatFullPath ."
    \n"; + echo html_frame_end(); + + echo html_frame_start('','90%','',2); + echo 'This category has no sub-categories or applications'; + echo html_frame_end(); + } + } +} + +?> diff --git a/include/comment.php b/include/comment.php new file mode 100644 index 0000000..a999e41 --- /dev/null +++ b/include/comment.php @@ -0,0 +1,796 @@ +iCommentId = $oRow->commentId; + $this->iParentId = $oRow->parentId; + + $oVersion = new version($this->iVersionId); + $this->iAppId = $oVersion->iAppId; + + $this->iVersionId = $oRow->versionId; + $this->sSubject = $oRow->subject; + $this->sBody = $oRow->body; + $this->sDateCreated = $oRow->time; + $this->sHostname = $oRow->hostname; + $this->oOwner = new User($oRow->userId); + } + } + + + /* + * Creates a new comment. + * Informs interested people about the creation. + * Returns true on success, false on failure + */ + function create() + { + $hResult = query_parameters("INSERT INTO appComments + (parentId, versionId, subject, ". + "body, userId, time, hostname) + VALUES ('?', '?', '?', '?', '?', ?, '?')", + $this->iParentId, $this->iVersionId, + $this->sSubject, $this->sBody, + $_SESSION['current']->iUserId, + "NOW()", get_remote()); + + if($hResult) + { + $this->comment(query_appdb_insert_id()); + $sEmail = User::get_notify_email_address_list($this->iAppId, $this->iVersionId); + $sEmail .= $this->oOwner->sEmail." "; + + // fetches e-mails from parent comments, all parents are notified that a + // comment was added to the thread + $iParentId = $this->iParentId; + while($iParentId) + { + $oParent = new Comment($iParentId); + $sEmail .= $oParent->oOwner->sEmail." "; + $iParentId = $oParent->iParentId; + } + if($sEmail) + { + $aEmailArray = explode(" ", $sEmail); /* break the long email string into parts by spaces */ + $aEmailArray = array_unique($aEmailArray); /* remove duplicates */ + + /* build the single string of all emails up */ + $sEmail = ""; + foreach($aEmailArray as $key=>$value) + { + $sEmail.="$value "; + } + + $sSubject = "Comment for '".Application::lookup_name($this->iAppId)." ".Version::lookup_name($this->iVersionId)."' added by ".$_SESSION['current']->sRealname; + $sMsg = "To reply to this email please use the link provided below.\n"; + $sMsg .= "DO NOT reply via your email client as it will not reach the person who wrote the comment\n"; + $sMsg .= $this->objectMakeUrl()."\n"; + $sMsg .= "\n"; + $sMsg .= "Subject: ".$this->sSubject."\r\n"; + $sMsg .= "\n"; + $sMsg .= $this->sBody."\r\n"; + mail_appdb($sEmail, $sSubject ,$sMsg); + } + addmsg("Comment created.", "green"); + return true; + } + else + { + addmsg("Error while creating a new comment", "red"); + return false; + } + } + + + /** + * Update comment. + * FIXME: Informs interested people about the modification. + * Returns true on success and false on failure. + */ + function update($sSubject=null, $sBody=null, $iParentId=null, $iVersionId=null) + { + $oComment = new comment($this->iCommentId); + + if(!$iVersionId && $this->iVersionId != $oComment->iVersionId) + $iVersionId = $this->iVersionId; + if(!$iParentId && $this->iParentId != $oComment->iParentId) + $iParentId = $this->iParentId; + + if ($iParentId) + { + if (!query_parameters("UPDATE appComments SET parentId = '?' WHERE commentId = '?'", + $iParentId, $this->iCommentId)) + return false; + $this->iParentId = $iParentId; + } + + if ($iVersionId) + { + if (!query_parameters("UPDATE appComments SET versionId = '?' WHERE commentId = '?'", + $iVersionId, $this->iCommentId)) + return false; + $this->iVersionId = $iVersionId; + // FIXME: we need to refetch $this->iAppId. + } + + if ($sSubject) + { + if (!query_parameters("UPDATE appComments SET subject = '?' WHERE commentId = '?'", + $sSubject, $this->iCommentId)) + return false; + $this->sSubject = $sSubject; + } + + if ($sBody) + { + if (!query_parameters("UPDATE appComments SET body = '?' WHERE commentId = '?'", + $sBody, $this->iCommentId)) + return false; + $this->sBody = $sBody; + } + return true; + } + + function purge() + { + return $this->delete(); + } + + /** + * Removes the current comment from the database. + * Informs interested people about the deletion. + * Returns true on success and false on failure. + */ + function delete() + { + $hResult = query_parameters("DELETE FROM appComments WHERE commentId = '?'", $this->iCommentId); + if ($hResult) + { + $aChildren = $this->objectGetChildren(); + + foreach($aChildren as $oComment) + $oComment->delete(); + + return true; + } + + return false; + } + + function get_comment_count_for_versionid($iVersionId) + { + $sQuery = "SELECT count(*) as cnt from appComments where versionId = '?'"; + $hResult = query_parameters($sQuery, $iVersionId); + if(!$hResult) return 0; + + $oRow = query_fetch_object($hResult); + return $oRow->cnt; + } + + function getOutputEditorValues($aClean) + { + $this->sSubject = $aClean['sSubject']; + $this->sBody = $aClean['sBody']; + $this->iParentId = $aClean['iThread']; + + if($aClean['iVersionId']) + $this->iVersionId = $aClean['iVersionId']; + + if(!$this->oOwner) + $this->oOwner = $_SESSION['current']; + + if(!$this->sDateCreated) + $this->sDateCreated = date("l F jS Y, H:i"); + } + + /** + * Displays the body of one comment. + */ + function view_comment_body($iCommentId) + { + $hResult = Comment::grab_comment($iCommentId); + + if ($hResult) + { + $oRow = query_fetch_object($hResult); + Comment::view_app_comment($oRow); + } + } + + /** + * display a single comment (in $oRow) + */ + function view_app_comment($oRow, $bShowAppName = false) + { + $oComment = new comment(null, $oRow); + $oComment->output_comment($bShowAppName); + } + + private function output_comment($bShowAppName = false) + { + echo html_frame_start('','98%'); + echo '',"\n"; + + // message header + echo "\n"; + + // delete message button, for admins + if ($this->canEdit()) + { + echo ""; + echo ""; + } + + echo "
    iCommentId.">\n"; + echo " ".$this->sSubject."
    \n"; + + if($bShowAppName) + echo 'Application: ' . version::fullNameLink($this->iVersionId) . "
    \n"; + + echo " by ".forum_lookup_user($this->oOwner->iUserId)." on ".$this->sDateCreated."
    \n"; + echo "
    \n"; + + // body + echo htmlify_urls($this->sBody), "

    \n"; + + $oVersion = new version($this->iVersionId); + $oM = new objectManager("comment", "Post new comment"); + $oM->setReturnTo($oVersion->objectMakeUrl()); + // reply post buttons + echo " [makeUrl("add")."&iVersionId=$this->iVersionId\">post new] \n"; + echo " [makeUrl("add")."&iVersionId=$this->iVersionId". + "&iThread=$this->iCommentId\">reply to this] \n"; + + echo "
    \n"; + echo "iCommentId\">"; + echo ""; + echo ""; + echo ""; + echo ""; + echo "objectMakeUrl()."\">"; + echo "
    \n"; + echo "
    \n"; + + echo html_frame_end(); + } + + function display() + { + $this->output_comment(); + } + + /** + * grab single comment for commentId + */ + function grab_comment($iCommentId) + { + $iCommentId = query_escape_string($iCommentId); + + if($iCommentId) + { + $sQuery = "SELECT from_unixtime(unix_timestamp(appComments.time), \"%W %M %D %Y, %k:%i\") as time, ". + "appComments.commentId, appComments.parentId, appComments.versionId, appComments.userId, appComments.subject, appComments.body, appVersion.appId ". + "FROM appComments, appVersion WHERE appComments.commentId = '$iCommentId'"; + + $hResult = query_appdb($sQuery); + + return $hResult; + } + + return null; + } + + /** + * grab comments for appId / versionId + * if parentId is not -1 only comments for that thread are returned + */ + function grab_comments($iVersionId, $iParentId = null) + { + /* TODO: remove the logging when we figure out where the */ + /* invalid $iVersionId is coming */ + /* if $iVersionId is invalid we should log where we came from */ + /* so we can debug the problem */ + if($iVersionId == "") + { + error_log::logBackTrace("logging iVersionId oddity"); + return NULL; + } + + /* escape input so we can use query_appdb() without concern */ + $iVersionId = query_escape_string($iVersionId); + $iParentId = query_escape_string($iParentId); + + /* NOTE: we must compare against NULL here because $iParentId of 0 is valid */ + if($iParentId) + { + $sExtra = "AND parentId = '".$iParentId."' "; + $sOrderingMode = "ASC"; + } else + { + $sExtra = "AND parentId = '0'"; + $sOrderingMode = "DESC"; + } + + $sQuery = "SELECT from_unixtime(unix_timestamp(appComments.time), \"%W %M %D %Y, %k:%i\") as time, ". + "appComments.commentId, appComments.parentId, appComments.versionId, appComments.userId, appComments.subject, appComments.body, appVersion.appId ". + "FROM appComments, appVersion WHERE appComments.versionId = appVersion.versionId AND appComments.versionId = '".$iVersionId."' ". + $sExtra. + "ORDER BY appComments.time $sOrderingMode"; + + $hResult = query_appdb($sQuery); + + return $hResult; + } + + /** + * display nested comments + * handle is a db result set + */ + function do_display_comments_nested($hResult) + { + while($oRow = query_fetch_object($hResult)) + { + Comment::view_app_comment($oRow); + $hResult2 = Comment::grab_comments($oRow->versionId, $oRow->commentId); + if($hResult && query_num_rows($hResult2)) + { + echo "

    \n"; + Comment::do_display_comments_nested($hResult2); + echo "
    \n"; + } + } + } + + function display_comments_nested($versionId, $threadId) + { + $hResult = Comment::grab_comments($versionId, $threadId); + Comment::do_display_comments_nested($hResult); + } + + /** + * Generates the link to show the comment. + */ + function comment_link($oRow) + { + $sLink = "commentview.php?iAppId={$oRow->appId}&iVersionId=". + "{$oRow->versionId}&iThreadId={$oRow->parentId}"; + + $sOnClick = "showComment('{$oRow->commentId}');"; + + /** + * The return false line in the onClick is used to handle javascript + * being disabled so we can fail gracefully to the old style. + */ + return "
  • $oRow->subject". + ' by '.forum_lookup_user($oRow->userId)." on + {$oRow->time}
    commentId}\">
  • \n"; + } + + /** + * display threaded comments + * handle is a db result set + */ + function do_display_comments_threaded($hResult, $is_main) + { + if (!$is_main) + echo "
      \n"; + + while ($oRow = query_fetch_object($hResult)) + { + if ($is_main) + { + Comment::view_app_comment($oRow); + } else + { + $link = Comment::comment_link($oRow); + echo "$link"; + } + + $hResult2 = Comment::grab_comments($oRow->versionId, $oRow->commentId); + if ($hResult2 && query_num_rows($hResult2)) + { + echo "
      \n"; + Comment::do_display_comments_threaded($hResult2, 0); + echo "
      \n"; + } + } + + if (!$is_main) + echo "
    \n"; + } + + function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + return TRUE; + + $oVersion = new version($this->iVersionId); + return $oVersion->canEdit(); + } + + function objectGetId() + { + return $this->iCommentId; + } + + function objectGetSubmitterId() + { + return $this->oOwner->iUserId; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + $oOptions = new mailOptions(); + + if($sAction == "delete" && $bParentAction) + $oOptions->bMailOnce = TRUE; + + return $oOptions; + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + $sSubject = ""; + $sMessage = ""; + $aRecipients = null; + + $oVersion = new version($this->iVersionId); + $sVerName = version::fullName($this->iVersionId); + + if($bMailSubmitter) + { + switch($sAction) + { + case "delete": + if($bParentAction) + { + $sSubject = "Comments for $sVerName deleted"; + $sMessage = "Your comments for $sVerName were deleted because the"; + $sMessage .= "version was removed from the database"; + } else + { + $sSubject = "Comment for $sVerName deleted"; + $sMessage = $oVersion->objectMakeUrl()."\n"; + $sMessage .= "\n"; + $sMessage .= "This comment was made on ".substr($this->sDateCreated,0,10)."\n"; + $sMessage .= "\n"; + $sMessage .= "Subject: ".$this->sSubject."\r\n"; + $sMessage .= "\n"; + $sMessage .= $this->sBody."\r\n"; + } + break; + } + } else + { + switch($sAction) + { + case "delete": + if(!$bParentAction) + { + $sSubject = "Comment for $sVerName deleted"; + $sMessage = $oVersion->objectMakeUrl()."\n"; + $sMessage .= "\n"; + $sMessage .= "This comment was made on ".substr($this->sDateCreated,0,10)." by ".$this->oOwner->sRealname."\n"; + $sMessage .= "\n"; + $sMessage .= "Subject: ".$this->sSubject."\r\n"; + $sMessage .= "\n"; + $sMessage .= $this->sBody."\r\n"; + } + break; + } + $aRecipients = User::get_notify_email_address_list($this->iAppId, $this->iVersionId); + } + return array($sSubject, $sMessage, $aRecipients); + } + + public function objectGetParent($sClass = '') + { + switch($sClass) + { + case 'version': + return new version($this->iVersionId); + + case 'comment': + return new comment($this->iParentId); + } + } + + public function objectSetParent($iNewId, $sClass = '') + { + switch($sClass) + { + case 'version': + $this->iVersionId = $iNewId; + break; + + case 'comment': + $this->iParentId = $iNewId; + break; + } + } + + function objectGetChildren($bIncludeDeleted = false) + { + $aObjects = array(); + $hResult = comment::grab_comments($this->iVersionId, $this->iCommentId); + + if(!$hResult) + return $aObjects; + + while($oRow = mysql_fetch_object($hResult)) + { + $oComment = new comment(null, $oRow); + $aObjects += $oComment->objectGetChildren(); + $aObjects[] = $oComment; + } + + return $aObjects; + } + + function display_comments_threaded($versionId, $threadId = 0) + { + $hResult = Comment::grab_comments($versionId, $threadId); + + Comment::do_display_comments_threaded($hResult, 1); + } + + /** + * display flat comments + */ + function display_comments_flat($versionId) + { + $hResult = Comment::grab_comments($versionId); + if ($hResult) + { + while($oRow = query_fetch_object($hResult)) + { + Comment::view_app_comment($oRow); + } + } + } + + function view_app_comments($versionId, $threadId = 0) + { + global $aClean; + + // count posts + $hResult = query_parameters("SELECT commentId FROM appComments WHERE versionId = '?'", $versionId); + $messageCount = query_num_rows($hResult); + + //start comment format table + echo html_frame_start("","98%",'',0); + echo '',"\n"; + + echo '',"\n"; + echo '
    ',"\n"; + + $oVersion = new version($versionId); + + // message display mode changer + if ($_SESSION['current']->isLoggedIn()) + { + // FIXME we need to change this so not logged in users can change current view as well + if (!empty($aClean['sCmode'])) + $_SESSION['current']->setPref("comments:mode", $aClean['sCmode']); + + $sel[$_SESSION['current']->getPref("comments:mode", "threaded")] = 'selected'; + echo '',"\n"; + } + + // blank space + echo '',"\n"; + + $oM = new objectManager("comment", "Add comment"); + $oM->setReturnTo($oVersion->objectMakeUrl()); + + // post new message button + echo '',"\n"; + + //end comment format table + echo '
    ',"\n"; + echo "Application comments: $messageCount total comments "; + echo 'Mode: ',"\n"; + echo '
     
    '; + echo ''; + echo $oM->makeUrlFormData(); + echo ' ',"\n"; + echo '
    ',"\n"; + echo html_frame_end(); + + if( $messageCount > 0 ) + { + echo '

    The following comments are owned by whoever posted them. WineHQ is not responsible for what they say.

    '."\n"; + } + + //start comments + echo '
    ',"\n"; + + //hide or display depending on pref + if ($_SESSION['current']->isLoggedIn()) + $mode = $_SESSION['current']->getPref("comments:mode", "threaded"); + else + $mode = "threaded"; /* default non-logged in users to threaded comment display mode */ + + if ( isset($aClean['sMode']) && $aClean['sMode']=="nested") + $mode = "nested"; + + switch ($mode) + { + case "flat": + Comment::display_comments_flat($versionId); + break; + case "nested": + Comment::display_comments_nested($versionId, $threadId); + break; + case "threaded": + Comment::display_comments_threaded($versionId, $threadId); + break; + } + + echo '
    ',"\n"; + } + + function allowAnonymousSubmissions() + { + return FALSE; + } + + function objectGetCustomVars($sAction) + { + switch($sAction) + { + case "add": + return array("iThread", "iVersionId"); + + default: + return null; + } + } + + function checkOutputEditorInput($aClean) + { + $sErrors = ""; + + if(!$aClean['iVersionId']) + $sErrors .= "
  • No version id defined; something may have gone wrong with the URL
  • \n"; + + if(!$aClean['sBody']) + $sErrors .= "
  • You need to enter a message!
  • \n"; + + return $sErrors; + } + + function outputEditor($aClean) + { + $sMesTitle = "Post New Comment"; + + if($aClean['iThread'] > 0) + { + $hResult = query_parameters("SELECT * FROM appComments WHERE commentId = '?'", + $aClean['iThread']); + $oRow = query_fetch_object($hResult); + if($oRow) + { + $sMesTitle = "Replying To ... $oRow->subject\n"; + echo html_frame_start($oRow->subject,500); + echo htmlify_urls($oRow->body), "

    \n"; + echo html_frame_end(); + + /* Set default reply subject */ + if(!$this->sSubject) + { + // Only add RE: once + if(eregi("RE:", $oRow->subject)) + $this->sSubject = $oRow->subject; + else + $this->sSubject = "RE: ".$oRow->subject; + } + + } + } + + echo "

    Enter your comment in the box below."; + echo "
    Please do not paste large terminal or debug outputs here.

    "; + + echo html_frame_start($sMesTitle,500,"",0); + + echo '',"\n"; + echo "\n"; + echo " \n"; + echo "\n"; + echo " \n"; + echo "\n"; + + echo "
    From:  ".$_SESSION['current']->sRealname."
    Subject:  sSubject."\">
    \n"; + + echo html_frame_end(); + + echo "\n"; + echo "\n"; + } + + function objectShowPreview() + { + return TRUE; + } + + function objectMakeUrl() + { + $oVersion = new version($this->iVersionId); + $sUrl = $oVersion->objectMakeUrl()."#Comment-".$this->iCommentId; + return $sUrl; + } +} + + +/* + * Comment functions that are not part of the class + */ + +function forum_lookup_user($iUserId) +{ + if ($iUserId > 0) + { + $oUser = new User($iUserId); + if($_SESSION['current']->isLoggedIn()) + $sMailto = '' .$oUser->sRealname . ''; + else + $sMailto = $oUser->sRealname; + } + if (!$iUserId || !$oUser->isLoggedIn()) + { + $sMailto = 'Anonymous'; + } + return $sMailto; +} + +?> diff --git a/include/config.php b/include/config.php new file mode 100644 index 0000000..50e5220 --- /dev/null +++ b/include/config.php @@ -0,0 +1,57 @@ + diff --git a/include/config.php.sample b/include/config.php.sample new file mode 100644 index 0000000..86f924a --- /dev/null +++ b/include/config.php.sample @@ -0,0 +1,57 @@ + diff --git a/include/db_filter.php b/include/db_filter.php new file mode 100644 index 0000000..538a534 --- /dev/null +++ b/include/db_filter.php @@ -0,0 +1,233 @@ + + * +*/ + +define('FILTER_LIKE', 1); +define('FILTER_CONTAINS', 2); // Same as LIKE, but value is wrapped by wildcards +define('FILTER_STARTS_WITH', 3); // Same as LIKE, but with a prepended wildcard +define('FILTER_ENDS_WITH', 4); // Same as LIKE, but with an appended wildcard +define('FILTER_EQUALS', 5); +define('FILTER_GREATER_THAN', 6); +define('FILTER_LESS_THAN', 7); +define('FILTER_NOT_EQUALS', 8); +define('FILTER_NOT_LIKE', 9); +define('FILTER_OPTION_BOOL', 10); +define('FILTER_OPTION_ENUM', 11); + +/* A filter as part of an SQL query, such as something = 'somevalue' */ +class Filter +{ + private $sColumn; // The table column the filter is for + private $iType; // The type of filter, like EQUALS, LIKE + private $sData; // What the column is to be compared to */ + + public function Filter($sColumn, $iType, $sData) + { + $this->sColumn = $sColumn; + $this->iType = $iType; + $this->sData = $sData; + } + + public function getColumn() + { + return $this->sColumn; + } + + public function setData($sData) + { + $this->sData = $sData; + } + + public function getOperatorId() + { + return $this->iType; + } + + public function getData() + { + return $this->sData; + } + + public function getOperator() + { + switch($this->iType) + { + case FILTER_LIKE: + case FILTER_CONTAINS: + case FILTER_STARTS_WITH: + case FILTER_ENDS_WITH: + return 'LIKE'; + case FILTER_EQUALS: + return '='; + case FILTER_LESS_THAN: + return '<'; + case FILTER_GREATER_THAN: + return '>'; + case FILTER_NOT_EQUALS: + return '!='; + case FILTER_NOT_LIKE: + return 'NOT LIKE'; + + default: + return 0; // error + } + } + + /* Gets an SQL expression representing the current filter, for use in a WHERE clause */ + public function getExpression() + { + /* We let callers handle options themselves, so don't include them in the WHERE clause */ + if($this->isOption()) + return ''; + + $sData = $this->sData; + + /* Add wildcards if required */ + switch($this->iType) + { + case FILTER_CONTAINS: + $sData = "%$sData%"; + break; + case FILTER_STARTS_WITH: + $sData = "$sData%"; + break; + case FILTER_ENDS_WITH: + $sData = "%$sData"; + break; + } + + $sOp = $this->getOperator(); + + return "{$this->sColumn} $sOp '$sData'"; + } + + public function IsOption() + { + switch($this->iType) + { + case FILTER_OPTION_BOOL: + case FILTER_OPTION_ENUM: + return true; + + default: + return false; + } + } +} + +/* Class handling tables where the user can filter contents */ +class FilterSet +{ + private $aFilters; // Array of filters for this table + + public function FilterSet($sTableName = '') + { + $this->aFilters = array(); + + if($sTableName) + $this->loadTable($sTableName); + } + + public function loadTable($sTableName) + { + $sQuery = "SELECT * FROM $sTableName"; + $hResult = query_appdb($sQuery); + + while($oRow = mysql_fetch_object($hResult)) + { + $this->addFilterObject(new Filter($oRow->sColumn, $oRow->iType, $oRow->sData)); + } + } + + public function saveTable($sTableName) + { + $hResult = query_appdb("DROP TABLE IF EXISTS $sTableName"); + + $hResult = query_appdb("CREATE TABLE $sTableName ( + sColumn VARCHAR(255) NOT NULL, + iType INT(3) NOT NULL, + sData VARCHAR(255) NOT NULL DEFAULT '' + )"); + + if(!$hResult) + return false; + + $bSuccess = true; + foreach($this->aFilters as $oFilter) + { + $hResult = query_appdb("INSERT INTO $sTableName (sColumn,iType,sData) + VALUES('{$oFilter->getColumn()}','{$oFilter->getOperatorId()}','{$oFilter->getData()}')"); + if(!$hResult) + $bSuccess = false; + } + return $bSuccess; + } + + public function addFilterObject(Filter $oFilter) + { + $this->aFilters[] = $oFilter; + } + + public function AddFilter($sColumn, $iType, $sData) + { + $this->aFilters[] = new Filter($sColumn, $iType, $sData); + } + + public function getFilterCount() + { + return sizeof($this->aFilters); + } + + public function getFilters() + { + return $this->aFilters; + } + + public function getWhereClause() + { + $aFilters = array(); + for($i = 0; $i < sizeof($this->aFilters); $i++) + { + $oFilter = $this->aFilters[$i]; + + $sThisFilter = $oFilter->getExpression(); + + if($sThisFilter) + $aFilters[] = $sThisFilter; + } + + return implode($aFilters, ' AND '); + } + + function getQuery($sTable, $iLimit = 0) + { + $sWhere = $this->getFilterCount() ? 'WHERE '.$this->getWhereClause() : ''; + $sQuery = "SELECT * FROM $sTable $sWhere"; + + $iLimit = mysql_real_escape_string($iLimit); + + if($iLimit) + $sQuery .= " LIMIT 0,$iLimit"; + + return $sQuery; + } + + function getMatchedItems($sTable, $iLimit = 0) + { + return query_appdb($this->getQuery($sTable, $iLimit)); + } + + function getMatchedItemsCount($sTable) + { + return mysql_num_rows($this->getMatchedItems($sTable)); + } + +} + +?> diff --git a/include/db_filter_ui.php b/include/db_filter_ui.php new file mode 100644 index 0000000..9df1f63 --- /dev/null +++ b/include/db_filter_ui.php @@ -0,0 +1,567 @@ + + * +*/ + +require_once('db_filter.php'); + +define('FILTER_VALUES_NORMAL', 1); +define('FILTER_VALUES_ENUM', 2); +define('FILTER_VALUES_OPTION_BOOL', 3); +define('FILTER_VALUES_OPTION_ENUM', 4); + +define('MAX_FILTERS', 50); + +/* Info describing an available filter: what column it applies to, + and what comparison options are available */ +class FilterInfo +{ + private $sColumn; + private $sDisplayName; + private $aTypes; // Available filters for this column + private $iValueType; // Normal, enum ... + private $aValueTypeData; // List of enums + private $aValueTypeDataDisplay; // Optional display names for enums + + public function FilterInfo($sColumn, $sDisplayName, $aTypes, $iValueType = FILTER_VALUES_NORMAL, $aValueTypeData = array(), $aValueTypeDisplay = array()) + { + $this->sColumn = $sColumn; + $this->sDisplayName = $sDisplayName; + $this->aTypes = $aTypes; + $this->iValueType = $iValueType; + $this->aValueTypeData = $aValueTypeData; + + if(sizeof($aValueTypeData) && !sizeof($aValueTypeDisplay)) + $this->aValueTypeDataDisplay = $aValueTypeData; + else + $this->aValueTypeDataDisplay = $aValueTypeDisplay; + } + + public function getColumn() + { + return $this->sColumn; + } + + public function getDisplayName() + { + return $this->sDisplayName; + } + + public function getValueType() + { + return $this->iValueType; + } + + public function getValueTypeData() + { + return $this->aValueTypeData; + } + + public function getValueTypeDataDisplay() + { + return $this->aValueTypeDataDisplay; + } + + public function getTypes() + { + return $this->aTypes; + } + + public function isOption() + { + switch($this->iValueType) + { + case FILTER_VALUES_OPTION_BOOL: + case FILTER_VALUES_OPTION_ENUM: + return true; + + default: + return false; + } + } + + public static function getOpName($iOpId) + { + switch($iOpId) + { + case FILTER_EQUALS: + return 'equal to'; + case FILTER_LIKE: + return 'like'; + case FILTER_CONTAINS: + return 'contains'; + case FILTER_STARTS_WITH: + return 'starts with'; + case FILTER_ENDS_WITH: + return 'ends with'; + case FILTER_NOT_LIKE: + return 'not like'; + case FILTER_NOT_EQUALS: + return 'not equal to'; + case FILTER_LESS_THAN: + return 'less than'; + case FILTER_GREATER_THAN: + return 'greater than'; + } + } +} + +/* Class handling tables where the user can filter contents */ +class FilterInterface +{ + private $aFilterInfo; + private $oFilterSet; + private $aEscapeChars; + private $aEscapeCharsWith; + private $sErrors; // Used to inform the user about errors (and to give advice) + + public function FilterInterface($sTableName = '') + { + $this->aFilterInfo = array(); + $this->oFilterSet = new FilterSet(query_escape_string($sTableName)); + $this->aEscapeChars = array('.'); + $this->aEscapeCharsWith = array('-'); + $this->sErrors = ''; + } + + public function AddFilterObject(Filter $oFilter) + { + $this->oFilterSet->AddFilterObject($oFilter); + } + + public function setFilterSet(FilterSet $oSet) + { + $this->oFilterSet = $oSet; + } + + /* Convenience function to add a filter option */ + public function AddFilterInfo($sColumn, $sDisplayName, $aTypes, $iValueType = VALUE_TYPE_NORMAL, $aValueTypeData = array(), $aValueTypeDisplay = array()) + { + $this->aFilterInfo[$sColumn] = new FilterInfo($sColumn, $sDisplayName, $aTypes, $iValueType, $aValueTypeData, $aValueTypeDisplay); + } + + /* We can't use some special chars in variable names, such as '.' */ + public function escapeChars($sIn) + { + return str_replace($this->aEscapeChars, $this->aEscapeCharsWith, $sIn); + } + + public function unescapeChars($sIn) + { + return str_replace($this->aEscapeWith, $this->aEscape, $sIn); + } + + public function getUrlElement($iId, Filter $oFilter) + { + $sColumn = $this->escapeChars($oFilter->getColumn()); + + $sId = $iId; + + $shEditor = "&i{$sColumn}Op$sId={$oFilter->getOperatorId()}"; + $shEditor .= "&s{$sColumn}Data$sId={$oFilter->getData()}"; + + return $shEditor; + } + + public function getHiddenInputTag($iId, Filter $oFilter) + { + $sColumn = $this->escapeChars($oFilter->getColumn()); + $sId = $iId; + + $shEditor = "getOperatorId()}\">"; + $shEditor .= "getData()}\" />"; + + return $shEditor; + } + + public function getOptionBoolEditor($iId, Filter $oFilter) + { + $sColumn = $this->escapeChars($oFilter->getColumn()); + $oColumn = $this->aFilterInfo[$oFilter->getColumn()]; + $sId = ($iId == -1) ? '' : $iId; + + $aTypes = $oColumn->getTypes(); + $iOp = $aTypes[0]; + + if($iId == -1) + { + /* The first entry in the list of choices is the default */ + $aValues = $oColumn->getValueTypeData(); + $sData = $aValues[0]; + } else + { + $sData = $oFilter->getData(); + } + + $shRet = ""; + + if($sData == 'true') + $sChecked = ' checked="checked"'; + else + $sChecked = ''; + + $shRet .= ""; + $shRet .= ' '.$oColumn->getDisplayName(); + + return $shRet; + } + + public function getItemEditor($iId, Filter $oFilter) + { + $sColumn = $this->escapeChars($oFilter->getColumn()); + $oColumn = $this->aFilterInfo[$oFilter->getColumn()]; + + $sId = ($iId == -1) ? '' : $iId; + $shEditor = $oColumn->getDisplayName().' '; + + $aTypes = $oColumn->getTypes(); + + /* It doesn't make sense to show a dropdown menu of choices if there is only one + If the filter is already active then there are more than one; one to remove */ + if($iId == -1 && sizeof($aTypes) == 1) + { + echo ""; + + /* Printing 'equal to' sounds weird if it is the only choice */ + if($aTypes[0] != FILTER_EQUALS) + $shEditor .= $oColumn->getOpName($aTypes[0]); + } else if ($aTypes[0] != FILTER_OPTION_ENUM) + { + $shEditor .= " '; + } else + { + echo ""; + } + + switch($oColumn->getValueType()) + { + case FILTER_VALUES_NORMAL: + $shEditor .= "getData()}\" name='s{$sColumn}Data$sId' size='30' />"; + break; + case FILTER_VALUES_ENUM: + case FILTER_VALUES_OPTION_ENUM: + $shEditor .= $this->getEnumEditor($oColumn, $oFilter, $sId); + break; + } + + return $shEditor; + } + + public function getEnumEditor($oColumn, $oFilter, $sId) + { + $sColumn = $this->escapeChars($oFilter->getColumn()); + $aOptions = $oColumn->getValueTypeData(); + $aOptionNames = $oColumn->getValueTypeDataDisplay(); + + $sData = $oFilter->getData(); + + $shEditor = ""; + + return $shEditor; + } + + /* Get filter data formatted to fit in a URL */ + public function getUrlData() + { + $shEditor = ''; + $aCounts = array(); + + foreach($this->oFilterSet->getFilters() as $oFilter) + { + $sColumn = $oFilter->getColumn(); + + if(!array_key_exists($sColumn, $aCounts)) + $aCounts[$sColumn] = 0; + + $shEditor .= $this->getUrlElement($aCounts[$sColumn], $oFilter); + + $shEditor .= '
    '; + + $aCounts[$sColumn]++; + } + + return $shEditor; + } + + /* Get a list of hidden input tags to preserve form data */ + public function getHiddenFormData() + { + $shEditor = ''; + $aCounts = array(); + + foreach($this->oFilterSet->getFilters() as $oFilter) + { + $sColumn = $oFilter->getColumn(); + + if(!array_key_exists($sColumn, $aCounts)) + $aCounts[$sColumn] = 0; + + $shEditor .= $this->getHiddenInputTag($aCounts[$sColumn], $oFilter); + + $shEditor .= '
    '; + + $aCounts[$sColumn]++; + } + + return $shEditor; + } + + public function getEditor() + { + $shNewItemsEditor = ''; + $shCurrentItemsEditor = ''; + $aCounts = array(); + + if(sizeof($this->oFilterSet->getFilters())) + $shCurrentItemsEditor .= '
    Active filters
    '; + foreach($this->oFilterSet->getFilters() as $oFilter) + { + $sColumn = $oFilter->getColumn(); + + if(!array_key_exists($sColumn, $aCounts)) + $aCounts[$sColumn] = 0; + + if($oFilter->getOperatorId() == FILTER_OPTION_BOOL) + $shCurrentItemsEditor .= $this->getOptionBoolEditor($aCounts[$sColumn], $oFilter); + else + $shCurrentItemsEditor .= $this->getItemEditor($aCounts[$sColumn], $oFilter); + $shCurrentItemsEditor .= '
    '; + + $aCounts[$sColumn]++; + } + + $shNewItemsEditor .= 'Add new filter (You don’t have to fill out all rows.)
    '; + + /* Show errors, if any */ + if($this->sErrors) + $shNewItemsEditor .= "{$this->sErrors}"; + + foreach($this->aFilterInfo as $oOption) + { + $oDummyFilter = new Filter($oOption->getColumn(), 0, ''); + $aTypes = $oOption->getTypes(); + + if($oOption->getValueType() == FILTER_VALUES_OPTION_BOOL) + { + if(!array_key_exists($oOption->getColumn(), $aCounts)) + $shNewItemsEditor .= $this->getOptionBoolEditor(-1, $oDummyFilter); + $shNewItemsEditor .= '
    '; + } else + { + /* Make necessary checks for filters that are only supposed to be shown once */ + if($oOption->getValueType() != FILTER_VALUES_OPTION_ENUM || !array_key_exists($oOption->getColumn(), $aCounts)) + { + $shNewItemsEditor .= $this->getItemEditor(-1, $oDummyFilter); + $shNewItemsEditor .= '
    '; + } + } + } + + return $shNewItemsEditor.$shCurrentItemsEditor; + } + + public function getFilterInfo() + { + return $this->aFilterInfo; + } + + /* Reads all input related to filters for the given table column */ + public function readInputForColumn($aClean, FilterInfo $oOption) + { + $aReturn = array(); + $bChangedOption = false; + + for($i = 0; array_key_exists('i'.$this->escapeChars($oOption->getColumn())."Op$i", $aClean); $i++) + { + $sColumn = $this->escapeChars($oOption->getColumn()); + $sData = query_escape_string(getInput("s{$sColumn}Data$i", $aClean)); + $iOp = $aClean["i{$sColumn}Op$i"]; + + if(!$iOp) + continue; + + $oFilter = new Filter($oOption->getColumn(), $iOp, $sData); + + /* Only show an option as an active filter if it has been changed + from the default */ + if($oOption->getValueType() == FILTER_VALUES_OPTION_BOOL || $oOption->getValueType() == FILTER_VALUES_OPTION_ENUM) + { + if($oOption->getValueType() == FILTER_VALUES_OPTION_BOOL) + { + /* The default option is the first entry in the list of choices */ + $aChoices = $oOption->getValueTypeData(); + $sDefault = $aChoices[0]; + if(!$sData) + $sData = 'false'; + + if($sData == $sDefault) + continue; + } + if($i > 0) + continue; + $bChangedOption = true; + } + + if(!$sData) + continue; + + $aReturn[] = $oFilter; + } + + if(array_key_exists('i'.$this->escapeChars($oOption->getColumn())."Op", $aClean)) + { + $sColumn = $this->escapeChars($oOption->getColumn()); + $i = sizeof($aReturn); + $sData = query_escape_string($aClean["s{$sColumn}Data"]); + $iOp = $aClean["i{$sColumn}Op"]; + + + if($iOp && $sData && ($oOption->getValueType() != FILTER_VALUES_OPTION_BOOL || !$bChangedOoption)) + { + $oFilter = new Filter($oOption->getColumn(), $iOp, $sData); + $aReturn[] = $oFilter; + } else if(!$iOp && $sData) + { + /* The user probably meant to add a filter, but forgot to seelect + a filter criterion */ + $this->sErrors .= 'You need to select a filter criterion from the drop-down list
    '; + } + } + + return $aReturn; + } + + /* Reads an input array get enabled filters from form data. + The given TableFilterSet defines available options */ + public function readInput($aClean) + { + $iCount = 0; // We set a maximum for how many filters a user can add, + // otherwise we may get a too long SQL query + + foreach($this->getFilterInfo() as $oOption) + { + foreach($this->readInputForColumn($aClean, $oOption) as $oNewFilter) + { + $iCount ++; + $this->AddFilterObject($oNewFilter); + if($iCount > MAX_FILTERS) + break; + } + } + } + + public function loadTable($sTableName) + { + $this->oFilterSet->loadTable($sTableName); + } + + public function saveTable($sTableName) + { + $this->oFilterSet->saveTable($sTableName); + } + + public function getFilterCount() + { + return $this->oFilterSet->getFilterCount(); + } + + /* Returns an array of options, where the keys are the columns and the members + are the settings themselves */ + public function getOptions() + { + $aOptions = array(); + foreach($this->oFilterSet->getFilters() as $oFilter) + { + if($oFilter->isOption()) + $aOptions[$oFilter->getColumn()] = $oFilter->getData(); + } + foreach($this->aFilterInfo as $oFilterInfo) + { + if($oFilterInfo->isOption() && + !array_key_exists($oFilterInfo->getColumn(), $aOptions)) + { + $aTypes = $oFilterInfo->getTypes(); + + if($oFilterInfo->getValueType() == FILTER_VALUES_OPTION_BOOL) + $sDefault = $aTypes[0]; + else + $sDefault = ''; + + $aOptions[$oFilterInfo->getColumn()] = $sDefault; + } + } + return $aOptions; + } + + public function getWhereClause() + { + return $this->oFilterSet->getWhereClause(); + } + + public function getTable($sTable, $iLimit = 0) + { + $hResult = $this->oFilterSet->getMatchedItems($sTable, $iLimit); + + if(!$hResult) + return; + + echo 'Selected '.$this->oFilterSet->getMatchedItemsCount($sTable).' rows

    '; + + $oTable = new Table(); + + while($aRow = mysql_fetch_row($hResult)) + { + $oRow = new TableRow(); + + foreach($aRow as $sCell) + { + $oRow->AddTextCell($sCell); + } + + $oTable->AddRow($oRow); + } + + return $oTable->getString(); + } +} + +?> diff --git a/include/distribution.php b/include/distribution.php new file mode 100644 index 0000000..354e585 --- /dev/null +++ b/include/distribution.php @@ -0,0 +1,789 @@ +aTestingIds = array(); + // we are working on an existing distribution. + if(!$iDistributionId && !$oRow) + return; + + // We fetch the data related to this distribution. + if(!$oRow) + { + $sQuery = "SELECT * + FROM distributions + WHERE distributionId = '?'"; + if($hResult = query_parameters($sQuery, $iDistributionId)) + $oRow = query_fetch_object($hResult); + } + + if($oRow) + { + $this->iDistributionId = $oRow->distributionId; + $this->sName = $oRow->name; + $this->sUrl = $oRow->url; + $this->sSubmitTime = $oRow->submitTime; + $this->iSubmitterId = $oRow->submitterId; + $this->sState = $oRow->state; + } + + /* + * We fetch Test Result Ids. + */ + + if($_SESSION['current']->hasPriv("admin")) + { + $sQuery = "SELECT testingId + FROM testResults, ?.versions + WHERE + versions.value = testResults.testedRelease + AND + versions.product_id = '?' + AND + distributionId = '?' + ORDER BY testedRating,bugs.versions.id DESC"; + } else /* only let users view test results that aren't queued and for apps that */ + /* aren't queued or versions that aren't queued */ + { + $sQuery = "SELECT testingId + FROM testResults, appFamily, appVersion, ?.versions + WHERE testResults.state = 'accepted' AND + versions.value = testResults.testedRelease + AND + versions.product_id = '?' + AND + testResults.versionId = appVersion.versionId AND + appFamily.appId = appVersion.appId AND + appFamily.state = 'accepted' AND + appVersion.state = 'accepted' AND + distributionId = '?' + ORDER BY testedRating,bugs.versions.id DESC"; + } + + if($hResult = query_parameters($sQuery, BUGZILLA_DB, BUGZILLA_PRODUCT_ID, $this->iDistributionId)) + { + while($oRow = query_fetch_object($hResult)) + { + $this->aTestingIds[] = $oRow->testingId; + } + } + } + + // Creates a new distribution. + function create() + { + //Let's not create a duplicate + $sQuery = "SELECT * + FROM distributions + WHERE name = '?'"; + $hResult = query_parameters($sQuery, $this->sName); + + if($hResult && $oRow = query_fetch_object($hResult)) + { + if(query_num_rows($hResult)) + { + addmsg("There was an existing distribution called ".$this->sName.".", "red"); + $this->distribution($oRow->distributionId); + + /* Even though we did not create a new distribution, the caller is provided + with a valid distribution object. Thus no special handling is necessary, + so we return TRUE */ + return TRUE; + } + } + + $hResult = query_parameters("INSERT INTO distributions (name, url, submitTime, ". + "submitterId, state) ". + "VALUES ('?', '?', ?, '?', '?')", + $this->sName, $this->sUrl, + "NOW()", + $_SESSION['current']->iUserId, + $this->mustBeQueued() ? 'queued' : 'accepted'); + if($hResult) + { + $this->iDistributionId = query_appdb_insert_id(); + $this->distribution($this->iDistributionId); + $this->SendNotificationMail(); + return true; + } + else + { + addmsg("Error while creating Distribution.", "red"); + return false; + } + } + + // Update Distribution. + function update() + { + // is the current user allowed to update this Distribution? + if(!$_SESSION['current']->hasPriv("admin") && + !($_SESSION['current']->iUserId == $this->iSubmitterId)) + { + return; + } + if(query_parameters("UPDATE distributions SET name = '?', url = '?' WHERE distributionId = '?'", + $this->sName, $this->sUrl, $this->iDistributionId)) + { + $this->SendNotificationMail("edit"); + return true; + } else + { + addmsg("Error while updating Distribution", "red"); + return false; + } + } + + function purge() + { + /* Is the current user allowed to delete this distribution? We allow + everyone to delete a queued, empty distribution, because it should be + deleted along with the last testData associated with it */ + if(!($this->canEdit() || (!sizeof($this->aTestingIds) && + $this->sState != 'accepted'))) + return false; + + // if the distribution has test results only enable an admin to delete + // the distribution + if(sizeof($this->aTestingIds) && !$_SESSION['current']->hasPriv("admin")) + return FALSE; + + $bSuccess = TRUE; + + foreach($this->objectGetChildren(true) as $oChild) + { + if(!$oChild->purge()) + $bSuccess = FALSE; + } + + // now delete the Distribution + $sQuery = "DELETE FROM distributions + WHERE distributionId = '?' + LIMIT 1"; + if(!($hResult = query_parameters($sQuery, $this->iDistributionId))) + $bSuccess = FALSE; + + return $bSuccess; + } + + // Delete Distributution. + function delete() + { + /* Is the current user allowed to delete this distribution? We allow + everyone to delete a queued, empty distribution, because it should be + deleted along with the last testData associated with it */ + if(!($this->canEdit() || (!sizeof($this->aTestingIds) && + $this->sState != 'accepted'))) + return false; + + // if the distribution has test results only enable an admin to delete + // the distribution + if(sizeof($this->aTestingIds) && !$_SESSION['current']->hasPriv("admin")) + return FALSE; + + $bSuccess = TRUE; + + foreach($this->objectGetChildren() as $oChild) + { + if(!$oChild->delete()) + $bSuccess = FALSE; + } + + // now delete the Distribution + $sQuery = "UPDATE distributions SET state = 'deleted' + WHERE distributionId = '?' + LIMIT 1"; + if(!($hResult = query_parameters($sQuery, $this->iDistributionId))) + $bSuccess = FALSE; + + return $bSuccess; + } + + // Move Distribution out of the queue. + function unQueue() + { + /* Check permissions */ + if($this->mustBeQueued()) + return FALSE; + + // If we are not in the queue, we can't move the Distribution out of the queue. + if($this->sState != 'queued') + return false; + + if(query_parameters("UPDATE distributions SET state = '?' WHERE distributionId = '?'", + 'accepted', $this->iDistributionId)) + { + $this->sState = 'accepted'; + // we send an e-mail to interested people + $this->mailSubmitter("add"); + $this->SendNotificationMail(); + return true; + } else + { + addmsg("Error while unqueueing Distribution", "red"); + return false; + } + } + + function Reject($bSilent=false) + { + // is the current user allowed to reject this Distribution? + if(!$_SESSION['current']->hasPriv("admin")) + { + return false; + } + + // If we are not in the queue, we can't move the Distribution out of the queue. + if($this->sState != 'queued') + return false; + + return $this->delete(); + } + + function getTestResults($bIncludeDeleted = false) + { + if($bIncludeDeleted) + $sExcludeDeleted = ""; + else + $sExcludeDeleted = " AND state != 'deleted'"; + + $aTests = array(); + $sQuery = "SELECT * FROM testResults WHERE distributionId = '?'$sExcludeDeleted"; + $hResult = query_parameters($sQuery, $this->iDistributionId); + + while($oRow = mysql_fetch_object($hResult)) + $aTests[] = new testData(null, $oRow); + + return $aTests; + } + + function objectGetChildren($bIncludeDeleted = false) + { + $aChildren = array(); + + foreach($this->getTestResults($bIncludeDeleted) as $oTest) + { + $aChildren += $oTest->objectGetChildren($bIncludeDeleted); + $aChildren[] = $oTest; + } + + return $aChildren; + } + + function ReQueue() + { + // is the current user allowed to requeue this data + if(!$_SESSION['current']->hasPriv("admin") && + !($_SESSION['current']->iUserId == $this->iSubmitterId)) + { + return false; + } + + if(query_parameters("UPDATE testResults SET state = '?' WHERE testingId = '?'", + 'queued', $this->iTestingId)) + { + if(query_parameters("UPDATE distribution SET state = '?' WHERE distributionId = '?'", + 'queued', $this->iDistributionId)) + { + $this->sState = 'queued'; + // we send an e-mail to interested people + $this->SendNotificationMail(); + + // the test data has been resubmitted + addmsg("The Distribution has been resubmitted", "green"); + return true; + } + } + + /* something has failed if we fell through to this point without */ + /* returning */ + addmsg("Error requeueing Distribution", "red"); + return false; + } + + function objectGetSubmitterId() + { + return $this->iSubmitterId; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + $oSubmitter = new user($this->iSubmitterId); + + if($bMailSubmitter) + { + switch($sAction) + { + case "delete": + $sSubject = "Submitted distribution deleted"; + $sMsg = "The distribution you submitted (".$this->sName.") has been ". + "deleted.\n"; + break; + } + $aMailTo = null; + } else + { + switch($sAction) + { + case "delete": + $sSubject = "Distribution ".$this->sName." deleted"; + $sMsg = ""; + break; + } + $aMailTo = User::get_notify_email_address_list(null, null); + } + + return array($sSubject, $sMsg, $aMailTo); + } + + function mailSubmitter($sAction="add") + { + global $aClean; + + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + switch($sAction) + { + case "add": + { + $sSubject = "Submitted Distribution accepted"; + $sMsg = "The Distribution you submitted (".$this->sName.") has been accepted.\n"; + } + break; + case "delete": + { + $sSubject = "Submitted Distribution deleted"; + $sMsg = "The Distribution you submitted (".$this->sName.") has been deleted."; + $sMsg .= "Reason given:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + break; + } + $sMsg .= "We appreciate your help in making the Application Database better for all users."; + + mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg); + } + } + + + function SendNotificationMail($sAction="add",$sMsg=null) + { + global $aClean; + + switch($sAction) + { + case "add": + if($this->sState == 'accepted') + { + $sSubject = "Distribution ".$this->sName." added by ". + $_SESSION['current']->sRealname; + $sMsg = $this->objectMakeUrl()."\n"; + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + $sMsg .= "This Distribution has been submitted by ".$oSubmitter->sRealname."."; + $sMsg .= "\n"; + $sMsg .= "Appdb admin reply text:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + addmsg("The Distribution was successfully added into the database.", "green"); + } else // test data queued. + { + $sSubject = "Distribution ".$this->sName." submitted by ".$_SESSION['current']->sRealname; + $sMsg .= "This test data has been queued."; + $sMsg .= "\n"; + addmsg("The Distribution you submitted will be added to the database after being reviewed.", "green"); + } + break; + case "edit": + $sSubject = "Distribution ".$this->sName." has been modified by ".$_SESSION['current']->sRealname; + $sMsg = $this->objectMakeUrl()."\n"; + addmsg("Distribution modified.", "green"); + break; + case "delete": + $sSubject = "Distribution ".$this->sName." has been deleted by ".$_SESSION['current']->sRealname; + + // if sReplyText is set we should report the reason the data was deleted + if($aClean['sReplyText']) + { + $sMsg .= "Reason given:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + + addmsg("Distribution deleted.", "green"); + break; + case "reject": + $sSubject = "Distribution '".$this->sName." has been rejected by ". + $_SESSION['current']->sRealname; + $sMsg = $this->objectMakeUrl()."\n"; + + // if sReplyText is set we should report the reason the data was rejected + if($aClean['sReplyText']) + { + $sMsg .= "Reason given:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + + addmsg("Distribution rejected.", "green"); + break; + } + $sEmail = User::get_notify_email_address_list(null, null); + if($sEmail) + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + function outputEditor() + { + echo "\n"; + + $this->sName = str_replace('"', '"', $this->sName); + // Name + echo html_tr(array( + array("Distribution Name:", 'align=right class="color0"'), + array('', 'class="color0"') + )); + + // URL + echo html_tr(array( + array("Distribution URL:", 'align=right class="color0"'), + array('', 'class="color0"') + )); + + + echo "
    \n"; + + if($this->iDistributionId) + { + echo '',"\n"; + } + } + + /* retrieves values from $_REQUEST that were output by outputEditor() */ + /* $aValues can be $_REQUEST or any array with the values from outputEditor() */ + function GetOutputEditorValues($aValues) + { + if($aClean['iDistributionId']) + $this->iDistributionId = $aValues['iDistributionId']; + + $this->sName = $aValues['sDistribution']; + $this->sUrl = $aValues['sUrl']; + } + + function objectGetFilterInfo() + { + $oFilter = new FilterInterface(); + + $oFilter->AddFilterInfo('name', 'Name', array(FILTER_CONTAINS, FILTER_STARTS_WITH, FILTER_ENDS_WITH), FILTER_VALUES_NORMAL); + return $oFilter; + } + + /* Get the total number of Distributions in the database */ + function objectGetEntriesCount($sState, $oFilter = null) + { + /* Not implemented */ + if($sState == 'rejected') + return FALSE; + + $sWhereFilter = $oFilter ? $oFilter->getWhereClause() : ''; + + if($sWhereFilter) + $sWhereFilter = " AND $sWhereFilter"; + + $hResult = query_parameters("SELECT count(distributionId) as num_dists FROM + distributions WHERE state='?' $sWhereFilter", + $sState); + + if($hResult) + { + $oRow = query_fetch_object($hResult); + return $oRow->num_dists; + } + return 0; + } + + /* Make a dropdown list of distributions */ + function make_distribution_list($varname, $cvalue) + { + $sQuery = "SELECT name, distributionId FROM distributions + WHERE state = 'accepted' + ORDER BY name"; + $hResult = query_parameters($sQuery); + if(!$hResult) return; + + echo "\n"; + } + + function objectGetHeader() + { + $oTableRow = new TableRowSortable(); + + $oTableRow->AddSortableTextCell("Distribution name", "name"); + + $oTableCell = new TableCell("Test reports"); + $oTableRow->AddCell($oTableCell); + + $oTableRow->AddTextCell("Distribution url"); + + return $oTableRow; + } + + public static function objectGetSortableFields() + { + return array('name'); + } + + public static function objectGetDefaultSort() + { + return 'name'; + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "name", $bAscending = TRUE, $oFilter = null) + { + /* Not implemented */ + if($sState == 'rejected') + return FALSE; + + /* Only users with edit privileges are allowed to view queued + items, so return NULL in that case */ + if($sState != 'accepted' && !distribution::canEdit()) + return NULL; + + $sOrder = $bAscending ? "ASC" : "DESC"; + + /* If row limit is 0 we want to fetch all rows */ + if(!$iRows) + $iRows = distribution::objectGetEntriesCount($sState, $oFilter); + + $sWhereFilter = $oFilter ? $oFilter->getWhereClause() : ''; + + if($sWhereFilter) + $sWhereFilter = " AND $sWhereFilter"; + + $sQuery = "SELECT * FROM distributions + WHERE state = '?' $sWhereFilter ORDER BY $sOrderBy $sOrder LIMIT ?,?"; + + return query_parameters($sQuery, $sState, + $iStart, $iRows); + } + + function objectGetTableRow() + { + $oTableRow = new TableRow(); + + $oTableRow->AddTextCell($this->objectMakeLink()); + + $oTableCell = new TableCell(sizeof($this->aTestingIds)); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell("$this->sUrl"); + $oTableCell->SetCellLink($this->sUrl); + $oTableRow->AddCell($oTableCell); + + + // enable the 'delete' action if this distribution has no test results + $bDeleteLink = sizeof($this->aTestingIds) ? FALSE : TRUE; + + $oOMTableRow = new OMTableRow($oTableRow); + $oOMTableRow->SetHasDeleteLink($bDeleteLink); + return $oOMTableRow; + } + + public function objectGetState() + { + return $this->sState; + } + + // Whether the user has permission to edit distributions + function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + return TRUE; + + /* Maintainers are allowed to process queued test results and therefore also + queued distributions */ + if(is_object($this) && $this->sState != 'accepted' && + maintainer::isUserMaintainer($_SESSION['current'])) + return TRUE; + + return FALSE; + } + + function mustBeQueued() + { + if($_SESSION['current']->hasPriv("admin") || + maintainer::isUserMaintainer($_SESSION['current'])) + return FALSE; + else + return TRUE; + } + + function objectHideDelete() + { + return TRUE; + } + + function display() + { + echo "Distribution Name:"; + + if($this->sUrl) + echo ""; + + echo $this->sName; + + if ($this->sUrl) + { + echo " (".$this->sUrl.")"; + echo "
    \n"; + } else + { + echo "
    \n"; + } + + if($this->aTestingIds) + { + echo '

    Test Results for '.$this->sName.'
    ',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + foreach($this->aTestingIds as $iTestingId) + { + $oTest = new testData($iTestingId); + + if($oTest->objectGetState() != $this->objectGetState()) + continue; + + $oVersion = new Version($oTest->iVersionId); + $oApp = new Application($oVersion->iAppId); + $oSubmitter = new User($oTest->iSubmitterId); + $bgcolor = $oTest->sTestedRating; + + /* make sure the user can view the versions we list in the table */ + /* otherwise skip over displaying the entries in this table */ + if(!$_SESSION['current']->canViewApplication($oApp)) + continue; + if(!$_SESSION['current']->canViewVersion($oVersion)) + continue; + + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + if ($_SESSION['current']->hasAppVersionModifyPermission($oVersion)) + { + echo '',"\n"; + } + echo '',"\n"; + } + echo '
    Application VersionSubmitterDate SubmittedWine versionInstalls?Runs?Rating
    ',"\n"; + echo version::fullName($oVersion->iVersionId).'',"\n"; + + echo $oSubmitter->objectMakeLink(); + + echo ''.date("M d Y", mysqldatetime_to_unixtimestamp($oTest->sSubmitTime)).''.$oTest->sTestedRelease.' '.$oTest->sInstalls.' '.$oTest->sRuns.' '.$oTest->sTestedRating.' ',"\n"; + echo 'Edit
    ',"\n"; + } + } + + /* Make a URL for viewing the specified distribution */ + function objectMakeUrl() + { + $oObject = new objectManager("distribution", "View Distribution"); + return $oObject->makeUrl("view", $this->iDistributionId); + } + + /* Make an HTML link for viewing the specified distirbution */ + function objectMakeLink() + { + return "objectMakeUrl()."\">$this->sName"; + } + + function objectMoveChildren($iNewId) + { + /* Keep track of how many children we modified */ + $iCount = 0; + + foreach($this->aTestingIds as $iTestId) + { + $oTest = new testData($iTestId); + $oTest->iDistributionId = $iNewId; + if($oTest->update(TRUE)) + $iCount++; + else + return FALSE; + } + + return $iCount; + } + + function objectGetItemsPerPage($sState = 'accepted') + { + $aItemsPerPage = array(25, 50, 100, 200); + $iDefaultPerPage = 25; + return array($aItemsPerPage, $iDefaultPerPage); + } + + function objectGetid() + { + return $this->iDistributionId; + } + + function allowAnonymousSubmissions() + { + return FALSE; + } + + function objectShowAddEntry() + { + return TRUE; + } +} + +?> diff --git a/include/downloadurl.php b/include/downloadurl.php new file mode 100644 index 0000000..d4d4b03 --- /dev/null +++ b/include/downloadurl.php @@ -0,0 +1,486 @@ +iId = $oRow->id; + $this->iVersionId = $oRow->versionId; + $this->sDescription = $oRow->description; + $this->sUrl = $oRow->url; + $this->sSubmitTime = $oRow->submitTime; + $this->iSubmitterId = $oRow->submitterId; + $this->bQueued = ($oRow->state == 'queued') ? TRUE : FALSE; + } + } + + /* Display download links for a given version */ + function display($iVersionId) + { + if(!($hResult = appData::getData($iVersionId, "downloadurl"))) + return FALSE; + + // we're appending, so initialize it + $sReturn = ''; + for($i = 0; $oRow = query_fetch_object($hResult); $i++) + { + $sReturn .= html_tr(array( + "Free Download", + "url\">$oRow->description"), + "color1"); + } + + return $sReturn; + } + + public function objectGetParent($sClass = '') + { + $oAppData = new appData($this->iId, null, $this); + return $oAppData->objectGetParent(); + } + + public function objectSetParent($iNewId, $sClass = '') + { + if($this->iVersionId || !$this->iAppId) + $this->iVersionId = $iNewId; + else + $this->iAppId = $iNewId; + } + + function objectGetChildren($bIncludeDeleted = false) + { + /* We have none */ + return array(); + } + + /* Output an editor for Download URL fields */ + function outputEditor($oVersion = null, $sFormAction = null) + { + /* If we do not get any parameters we try to behave like a proper objectManager + object, by only showing an editor for one entry instead of several. This + code is sort of hacky, and should be fixed once the rest of the downloadurl + code is fully adapted to the objectManager */ + if(!$oVersion && !$sFormAction) + { + global $aClean; + echo downloadurl::outputEditorSingle($this->iVersionId); + } + + if(!$oVersion || !$sFormAction) + return FALSE; + + /* Check for correct permissions */ + if(!downloadurl::canEdit($oVersion->iVersionId)) + return FALSE; + + $hResult = appData::getData($oVersion->iVersionId, "downloadurl"); + + $sReturn .= html_frame_start("Download URL", "90%", "", 0); + $sReturn .= "

    \n"; + $sReturn .= html_table_begin("border=0 cellpadding=5 cellspacing=0 width=100%"); + $sReturn .= html_tr(array( + array("Remove", "width=\"90\""), + "Description", + "URL" + ), + "color0"); + + $sReturn .= html_tr(array( + " ", + "", + ""), + "color4"); + + if($hResult) + { + for($i = 1; $oRow = query_fetch_object($hResult); $i++) + { + $sReturn .= html_tr(array( + "id\" ". + "value=\"true\">", + "id\" value=\"$oRow->description\">", + "id\" ". + "value=\"$oRow->url\">"), + ($i % 2) ? "color0" : "color4"); + } + } + + $sReturn .= html_table_end(); + $sReturn .= "
    \n"; + $sReturn .= "iVersionId\">\n"; + $sReturn .= "iAppId\">\n"; + $sReturn .= "
    \n"; + $sReturn .= html_frame_end(" "); + + return $sReturn; + } + + function objectGetSubmitterId() + { + return $this->iSubmitterId; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + /* We don't do this at the moment */ + return array(null, null, null); + } + + /* Process data from a Download URL form */ + function ProcessForm($aValues) + { + /* Check that we are processing a Download URL form */ + if($aValues["sSubmit"] != "Update Download URLs") + return FALSE; + + /* Check permissions */ + if(!downloadurl::canEdit($aValues["iVersionId"])) + return FALSE; + + if(!($hResult = query_parameters("SELECT COUNT(*) as num FROM appData + WHERE TYPE = '?' AND versionId = '?' AND state = 'accepted'", + "downloadurl", $aValues["iVersionId"]))) + return FALSE; + + if(!($oRow = query_fetch_object($hResult))) + return FALSE; + + $num = $oRow->num; + + /* Update URLs. Nothing to do if none are present in the database */ + if($num) + { + if(!$hResult = appData::getData($aValues["iVersionId"], "downloadurl")) + return FALSE; + + while($oRow = query_fetch_object($hResult)) + { + $oDownloadurl = new downloadurl($oRow->id); + + /* Remove URL */ + if($aValues["bRemove$oRow->id"]) + { + if(!$oDownloadurl->delete()) + return FALSE; + + $sWhatChangedRemove .= "Removed\nURL: $oRow->url\n". + "Description: $oRow->description\n\n"; + } + + /* Change description/URL */ + if(($aValues["sDescription$oRow->id"] != $oRow->description or + $aValues["sUrl$oRow->id"] != $oRow->url) && + $aValues["sDescription$oRow->id"] && $aValues["sUrl$oRow->id"]) + { + $oDownloadurl->sDescription = + $aValues["sDescription$oRow->id"]; + $oDownloadurl->sUrl = $aValues["sUrl$oRow->id"]; + + if(!$oDownloadurl->update()) + return FALSE; + + $sWhatChangedModify .= "Modified\nOld URL: $oRow->url\nOld ". + "Description: $oRow->description\nNew URL: ". + $aValues["sUrl$oRow->id"]."\nNew Description: ". + $aValues["sDescription$oRow->id"]."\n\n"; + } + } + } + + /* Insert new URL */ + if($aValues["sDescriptionNew"] && $aValues["sUrlNew"]) + { + $oDownloadurl = new downloadurl(); + $oDownloadurl->iVersionId = $aValues["iVersionId"]; + $oDownloadurl->sUrl = $aValues["sUrlNew"]; + $oDownloadurl->sDescription = $aValues["sDescriptionNew"]; + + if(!$oDownloadurl->create()) + return FALSE; + + $sWhatChanged = "Added\nURL: ".$aValues["sUrlNew"]."\nDescription: ". + $aValues["sDescriptionNew"]."\n\n"; + } + + $sWhatChanged .= "$sWhatChangedRemove$sWhatChangedModify"; + + if($sWhatChanged && $sEmail = + User::get_notify_email_address_list($aValues['iVersionId'])) + { + $oVersion = new Version($aValues["iVersionId"]); + + $sSubject = "Download URLs for ".version::fullName($oVersion->iVersionId). + " updated by ".$_SESSION['current']->sRealname; + + $sMsg = $oVersion->objectMakeUrl(); + $sMsg .= "\n\n"; + $sMsg .= "The following changed were made\n\n"; + $sMsg .= "$sWhatChanged\n\n"; + + mail_appdb($sEmail, $sSubject, $sMsg); + } + + return TRUE; + } + + function objectGetState() + { + return ($this->bQueued) ? 'queued' : 'accepted'; + } + + function canEdit($iVersionId = NULL) + { + if($_SESSION['current']->hasPriv("admin") || + ($iVersionId && + maintainer::isUserMaintainer($_SESSION['current'], $iVersionId))) + { + return TRUE; + } else + { + $oVersion = new version($this->iVersionId); + + return $oVersion->canEdit(); + } + } + + /* Output an editor for a single new URL */ + function outputEditorSingle($iVersionId = NULL, $aValues = NULL) + { + if($aValues["sDownloadUrlUrl"] && + $aValues["sDownloadUrlDescription"]) + { + $sDownloadUrlUrl = $aValues["sDownloadUrlUrl"]; + $sDownloadUrlDescription = $aValues["sDownloadUrlDescription"]; + } else if($iVersionId) + { + /* This illustrates the importance of converting downloadurl completely + to the objectManager model. If we don't get a match searching for + a queued entry, try finding a rejected one. */ + if(($hResult = appData::getData($iVersionId, "downloadurl", + TRUE, TRUE, FALSE)) || + $hResult = appData::getData($iVersionId, "downloadurl", + TRUE, TRUE, TRUE)) + { + $oRow = query_fetch_object($hResult); + $sDownloadUrlUrl = $oRow->url; + $sDownloadUrlDescription = $oRow->description; + } + } + + + $sReturn .= html_frame_start("Download URL","90%"); + $sReturn .= html_table_begin("width='100%' border=0 cellpadding=2 cellspacing=0"); + + $sReturn .= "A place where this version can be downloaded for free". + " (if applicable). You can add more links later.
    "; + + $sReturn .= html_tr(array( + array("Download URL:", "align=right"), + array("", + "class=\"color4\"")), + "color0"); + + $sReturn .= html_tr(array( + array("Download URL Description:", "align=right"), + array("", + "class=\"color4\"")), + "color0"); + + $sReturn .= html_table_end(); + $sReturn .= html_frame_end("nbsp;"); + + return $sReturn; + } + + function create() + { + if(!$this->sUrl or !$this->sDescription or !$this->iVersionId) + return FALSE; + + $hResult = query_parameters("INSERT INTO appData (versionId, type, + description, url, state, submitTime, submitterId) + VALUES('?', '?', '?', '?', '?', ?, '?')", + $this->iVersionId, "downloadurl", $this->sDescription, + $this->sUrl, + $this->mustBeQueued() ? 'queued' : 'accepted', + "NOW()", + $_SESSION['current']->iUserId); + + $this->iId = query_appdb_insert_id(); + if(!$hResult) + return FALSE; + + return TRUE; + } + + function update() + { + if(!$this->bQueued && !$this->canEdit($this->iVersionId)) + return FALSE; + + if(!$this->sDescription && !$this->sUrl) + { + $this->delete(); + return true; + } + + $hResult = query_parameters("UPDATE appData SET + description = '?', url = '?', versionId = '?' WHERE id = '?'", + $this->sDescription, $this->sUrl, $this->iVersionId, $this->iId); + + if(!$hResult) + return FALSE; + + return TRUE; + } + + function unQueue() + { + if($this->mustBeQueued()) + return FALSE; + + $hResult = query_parameters("UPDATE appData SET state = '?' + WHERE id = '?'", + 'accepted', $this->iId); + + if(!$hResult) + return FALSE; + + return TRUE; + } + + function purge() + { + return $this->delete(); + } + + function delete() + { + if(!downloadurl::canEdit($this->iVersionId)) + return FALSE; + + if(!query_parameters("DELETE FROM appData WHERE id = '?'", $this->iId)) + return FALSE; + + return TRUE; + } + + function reQueue() + { + $oAppData = new AppData($this->iId); + + return $oAppData->reQueue(); + } + + function reject() + { + $oAppData = new AppData($this->iId); + + return $oAppData->reject(); + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true) + { + return appData::objectGetEntries($sState, $iRows, $iStart, $sOrderBy, $bAscending, 'downloadurl'); + } + + function objectGetEntriesCount($sState) + { + return appData::objectGetEntriesCount($sState, 'downloadurl'); + } + + function objectGetHeader() + { + return appData::objectGetHeader("downloadurl"); + } + + function objectGetTableRow() + { + $oAppData = new AppData(); + return $oAppData->objectGetTableRow(); + } + + function getOutputEditorValues($aClean) + { + $this->sUrl = $aClean['sDownloadUrlUrl']; + $this->sDescription = $aClean['sDownloadUrlDescription']; + } + + function mustBeQueued() + { + if($this) + { + $oAppData = new appData(); + $oAppData->iVersionId = $this->iVersionId; + $oAppData->iAppId = NULL; + return $oAppData->mustBeQueued(); + } else + return appData::mustBeQueued(); + } + + function allowAnonymousSubmissions() + { + return FALSE; + } + + function objectMakeLink() + { + /* FIXME: not implemented */ + return TRUE; + } + + function objectMakeUrl() + { + /* FIXME: not implemented */ + return TRUE; + } + + function objectGetId() + { + return $this->iId; + } +} + +?> diff --git a/include/error_log.php b/include/error_log.php new file mode 100644 index 0000000..1bbbd0f --- /dev/null +++ b/include/error_log.php @@ -0,0 +1,104 @@ +iUserId : 0); + $hResult = query_parameters($sQuery, + "NOW()", + $iUser, + $sErrorType, + $sLogText, + $sRequestText, + '0'); + } + + /* get a backtrace and log it to the database */ + function logBackTrace($sDescription) + { + ob_start(); + print_r(debug_backtrace()); + $sDebugOutput = ob_get_contents(); + ob_end_clean(); + + error_log::log_error("general_error", $sDescription.' '.$sDebugOutput); + } + + function getEntryCount() + { + $sQuery = "SELECT count(*) as cnt FROM error_log WHERE deleted = '0'"; + $hResult = query_parameters($sQuery); + $oRow = query_fetch_object($hResult); + return $oRow->cnt; + } + + /* purge all of the current entries from the error log */ + function flush() + { + $sQuery = "UPDATE error_log SET deleted='1'"; + $hResult = query_parameters($sQuery); + + if($hResult) return true; + else return false; + } + + function mail_admins_error_log($sSubject = "") + { + $sSubject .= "Database Error log\r\n"; + $sEmail = User::get_notify_email_address_list(null, null); /* get list admins */ + + $sQuery = "SELECT * from error_log WHERE deleted='0' ORDER BY submitTime"; + $hResult = query_parameters($sQuery); + + $bEmpty = false; + if(query_num_rows($hResult) == 0) + $bEmpty = true; + + $sMsg = "Log entries:\r\n"; + $sMsg.= "\r\n"; + + $sMsg.= "Submit time userid type\r\n"; + $sMsg.= "log_text\r\n"; + $sMsg.= "request_text\r\n"; + $sMsg.="----------------------------------\r\n\r\n"; + + /* append each log entry to $sMsg */ + while($oRow = query_fetch_object($hResult)) + { + $sMsg.=$oRow->submitTime." ".$oRow->userid." ".$oRow->type."\r\n"; + $sMsg.= "---------------------\r\n"; + $sMsg.=$oRow->log_text."\r\n"; + $sMsg.= "---------------------\r\n"; + $sMsg.=$oRow->request_text."\r\n\r\n"; + } + + /* if we had no entries we should indicate */ + /* that the error log is empty */ + if($bEmpty) + $sMsg = "The error log is empty.\r\n"; + + if($sEmail) + mail_appdb($sEmail, $sSubject, $sMsg); + } +} + +?> diff --git a/include/filter.php b/include/filter.php new file mode 100644 index 0000000..404e3a1 --- /dev/null +++ b/include/filter.php @@ -0,0 +1,117 @@ +')=="") + $aClean[$aKeys[$i]] = ""; + break; + default: // normal string (no HTML) + $aClean[$aKeys[$i]] = trim(strip_tags($_REQUEST[$aKeys[$i]])); + break; + } + break; + case "a": // array + // store the value if it is an array + if(is_array($_REQUEST[$aKeys[$i]])) + $aClean[$aKeys[$i]] = $_REQUEST[$aKeys[$i]]; + break; + default: + // type not recognized, skip it + break; + } + } + + /* null out all input data so we can be assured that */ + /* no unfiltered values are being used */ + $_REQUEST = array(); + $_POST = array(); + $_GET = array(); + if(APPDB_DONT_CLEAR_COOKIES_VAR != "1") + $_COOKIES = array(); + + return null; +} +?> diff --git a/include/footer.php b/include/footer.php new file mode 100644 index 0000000..39a12a9 --- /dev/null +++ b/include/footer.php @@ -0,0 +1,15 @@ + +
    + + + + + + + + + diff --git a/include/form_edit.php b/include/form_edit.php new file mode 100644 index 0000000..099c008 --- /dev/null +++ b/include/form_edit.php @@ -0,0 +1,42 @@ +AddTextCell("  Email Address"); + $oTableRow->AddTextCell(''); + $aTableRows[] = $oTableRow; + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("  Password"); + $oTableRow->AddTextCell(''); + $aTableRows[] = $oTableRow; + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("  Password (again)"); + $oTableRow->AddTextCell(''); + $aTableRows[] = $oTableRow; + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("  Real Name"); + $oTableRow->AddTextCell(''); + $aTableRows[] = $oTableRow; + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell(" "); + $oTableRow->AddTextCell(" "); + $aTableRows[] = $oTableRow; + + return $aTableRows; +} + +?> diff --git a/include/form_login.php b/include/form_login.php new file mode 100644 index 0000000..0afa3f7 --- /dev/null +++ b/include/form_login.php @@ -0,0 +1,63 @@ +\n"; +echo '
    ',"\n"; +echo html_frame_start("Login to Application DB","400","",0); +/* Pass on the URL we should return to after log-in */ +global $aClean; +echo ''; +?> + + + + + + + + + + + + + + + + +
    E-mail '>
    Password
    + +
    + + + +',"\n"; +echo '',"\n"; +echo '
    ',"\n"; +echo "\n"; + +?> + +

    Don't have an account yet?
    + [Create a New Account]

    + +

    Lost your password?
    + [Email a New Password]

    + + diff --git a/include/form_new.php b/include/form_new.php new file mode 100644 index 0000000..1906225 --- /dev/null +++ b/include/form_new.php @@ -0,0 +1,49 @@ +\n"; +echo '
    ',"\n"; +echo html_frame_start("Create New Application DB Account","400","",0) +?> + + +The password will be sent to your e-mail + + + + + + + + + +"; + +?> + + + + +
    E-mail '>
    Real Name '>
      Wine version "; + echo make_bugzilla_version_list("sWineRelease", isset($aClean['sWineRelease']) ? $aClean['sWineRelease'] : ''); + echo "
    + +
    + + +',"\n"; +echo '
    ',"\n"; +echo "\n"; + +echo p(),p(),p(); + +?> diff --git a/include/header.php b/include/header.php new file mode 100644 index 0000000..99941e9 --- /dev/null +++ b/include/header.php @@ -0,0 +1,61 @@ + + + + WineHQ <?php echo $title; ?> + + + + + + + + + + + + + + + + + + + + + +
    +
    WineHQ
    + +
    + + + +
    + +
    + +
    + +
    + +
    + diff --git a/include/html.php b/include/html.php new file mode 100644 index 0000000..22a2861 --- /dev/null +++ b/include/html.php @@ -0,0 +1,340 @@ + 0) + $str = str_repeat(" ", $_indent_level) . $str; + + if($v > 0) + $_indent_level += $v; + + return $str . "\n"; +} + +function do_html_tr($t, $arr, $class, $extra) +{ + if(strlen($class)) + $class = " class=\"$class\""; + + /* $extra contains parameters to , such as valign="top" */ + if(strlen($extra)) + $extra = " $extra"; + + $str = do_indent("", 1); + for($i = 0; $i < sizeof($arr); $i++) + { + /* If it is not an array, it contains the entire table cell. If it + is an array, [0] holds the main content and [1] the options like + valign="top" */ + if(is_array($arr[$i])) + { + $val = $arr[$i][0]; + $extra = " ".$arr[$i][1]; + } + else + { + $val = $arr[$i]; + $extra = ""; + } + + if (! $val) + { + $val = " "; + } + + if(stristr($val, "<$t")) + { + $str .= do_indent($val); + } + else + { + $str .= do_indent("<$t$class$extra> ".trim($val)." ", 0); + } + } + $str .= do_indent("", -1); + + return $str; +} + +// HTML TR +function html_tr($arr, $class = "", $extra = "") +{ + return do_html_tr("td", $arr, $class, $extra); +} + +// HTML TABLE +function html_table_begin($extra = "") +{ + return do_indent("", 1); +} + +function html_table_end() +{ + return do_indent("
    ", -1); +} + + +// HTML HTML +function html_begin() +{ + return do_indent("", 1); +} + +function html_end() +{ + return do_indent("", -1); +} + + +// HTML HEAD +function html_head($title, $stylesheet = 0) +{ + $str = do_indent("", 1); + $str .= do_indent(" $title ", 0); + if($stylesheet) + $str .= do_indent("", 0); + $str .= do_indent("", -1); + + return $str; +} + + +// HTML BODY +function html_body_begin() +{ + return do_indent("", 1); +} + +function html_body_end() +{ + return do_indent("", -1); +} + +// HTML A HREF +function html_ahref($label, $url, $extra = "") +{ + $label = stripslashes($label); + if (!$label and $url) + { + return do_indent(" $url "); + } + else if (!$label) + { + return do_indent("   "); + } + else + { + return do_indent(" $label "); + } +} + +function html_imagebutton($text, $url, $extra = "") +{ + static $i = 1; + + $i++; + $img1 = apidb_url("util/button.php?text=".urlencode($text)."&pressed=0"); + $img2 = apidb_url("util/button.php?text=".urlencode($text)."&pressed=1"); + + $java = "onMouseDown = 'document.img$i.src = \"$img2\"; return true;' "; + $java .= "onMouseUp = 'document.img$i.src = \"$img1\"; return true;' "; + + return "\n\n \"$text\" \n"; +} + + +function html_frame_start($title = "", $width = "", $extra = "", $innerPad = 0) +{ + + if ($width) { $width = 'width="'.$width.'"'; } + +$str = ''."\n"; + +if ($title) +{ +$str .= ' + +'; +} + +$str .= ' + + + + + +
    + +
    + + + + +
    '.$title.'
    +
    + +
    +
    +'; + + return $str; +} + +function html_frame_end($text = "") +{ + +$str = ' +
    +
    +
    +'; + + return $str; +} + + +function html_select($name, $values, $default = null, $descs = null) +{ + $str = "\n"; + + return $str; +} + +function html_back_link($howmany = 1, $url = "") +{ + if (!$url) + { + $url = 'javascript:history.back('.$howmany.');'; + } + return '

       << Back

    '."\n"; +} + + +function p() +{ + return "\n

     

    \n"; +} + +function add_br($text = "") +{ + $text = ereg_replace("\n","
    \n",$text); + return $text; +} + +function make_dll_option_list($varname, $dllid = -1) +{ + $db = new ApiDB(); + + echo "\n"; +} + + +function make_inx_option_list($varname, $inx = null) +{ + $list = array("yes", "no", "stub", "unknown"); + echo "\n"; + +} + +/* Displays a note box */ +function html_note($shTitle, $shBody) +{ + $shRet = '
    '; + $shRet .= '
    '; + $shRet .= $shTitle; + $shRet .= '
    '; + $shRet .= '
    '; + $shRet .= $shBody; + $shRet .= '
    '; + + return $shRet; +} + +function html_radiobuttons($aIds, $aOptions, $sName, $sDefault = '') +{ + $shRet = ''; + + for($i = 0; $i < sizeof($aIds); $i++) + { + if($aIds[$i] == $sDefault) + $shChecked = ' checked="checked"'; + else + $shChecked = ''; + + $shRet .= ' " . $aOptions[$i].'
    '; + } + + return $shRet; +} + +function html_checkbox($sName, $sValue, $shText, $bChecked) +{ + if($bChecked) + $sSelected = ' checked="checked"'; + else + $sSelected = ''; + + return " $shText\n"; +} + +function html_checkboxes($sName, $aValues, $aTexts, $aSelected) +{ + $shRet = ''; + + for($i = 0; $i < sizeof($aValues); $i++) + $shRet .= html_checkbox($sName.$i, $aValues[$i], $aTexts[$i], $aSelected[$i]).'
    '; + + return $shRet; +} + +function html_read_input_series($sName, $aInput, $iCount) +{ + $aRet = array(); + + for($i = 0; $i < $iCount; $i++) + { + $aRet[] = getInput($sName.$i, $aInput); + } + + return $aRet; +} + +?> diff --git a/include/image.php b/include/image.php new file mode 100644 index 0000000..16e45dc --- /dev/null +++ b/include/image.php @@ -0,0 +1,439 @@ +isLoaded() + * should really be checked after making a new object. + */ + function Image($sPath, $bAbsolutePath=false) + { + /* if $bAbsolutePath is true we should use the $sPath without modification */ + /* otherwise use appdb_fullpath() to convert the relative $sPath into a absolute path */ + if($bAbsolutePath) + $this->sFile = $sPath; + else /* relative path */ + $this->sFile = appdb_fullpath($sPath); + + $oInfo = @getimagesize($this->sFile); + + if( empty($oInfo) ) + { + $this->set_debuglog("Failed to load file ".$this->sFile); + return; + } + + switch( $oInfo[2] ) + { + case 2: + $oImage = imagecreatefromjpeg($this->sFile); + break; + + case 3: + $oImage = imagecreatefrompng($this->sFile); + break; + + default; + $this->set_debuglog("Image type ({$oInfo[2]}) unknown"); + return; + return; + } + + $this->oImage = $oImage; + $this->iWidth = $oInfo[0]; + $this->iHeight = $oInfo[1]; + $this->iType = $oInfo[2]; + + $this->set_debuglog("New image class created with as $this->sFile as" + ." file and {$oInfo[2]} as type. Dimensions" + ." {$oInfo[0]}x{$oInfo[1]}"); + } + + /** + * isLoaded() + * This function should always be checked after loading a file + * with the constructor. Returns true if the image has been + * successfully loaded. + */ + function isLoaded() + { + if($this->iWidth > 0 AND $this->iHeight > 0) + return true; + else + return false; + } + + /** + * Returns the latest debug log made for the last function. If $bFull is + * set it will return the full log as array of the object. + */ + function get_debuglog($bFull = 0) + { + if($bFull) + return $this->aDebugLog; + else + return end($this->aDebugLog); + } + + function get_width() + { + return $this->iWidth; + } + + function get_height() + { + return $this->iHeight; + } + + /** + * Returns the image resource identifier. + */ + function get_image_resource() + { + return $this->oImage; + } + + /** + * make_thumb() + * + * Calculates resize based on one parameter and calculates the other + * with the right aspect ratio. If you want to use $iNewHeight set + * $iNewWidth to 0. + * + * If none are set APPDB_THUMBNAIL_WIDTH is used. If both are set + * $iNewWidth is used. + * + * If you want to make a border, look at resize_image_border() comment + * and set $iBorderWidth and $sBorderColor as appropriate. + * + */ + function make_thumb($iNewWidth, $iNewHeight, $iBorderWidth = 0, $sBorderColor = '') + { + + if($iNewWidth == 0 AND $iNewHeight == 0) + { + $iNewWidth = APPDB_THUMBNAIL_WIDTH; + $iNewHeight = $this->calculate_proportions($this->iWidth, $this->iHeight,$iNewWidth); + } + else if($iNewWidth > 0) + { + $iNewHeight = $this->calculate_proportions($this->iWidth, $this->iHeight,$iNewWidth); + } + else if($iNewHeight > 0) + { + $iNewWidth = $this->calculate_proportions($this->iWidth, $this->iHeight, 0, $iNewHeight); + } + + $this->set_debuglog("Resizing image to $iNewWidth x $iNewHeight"); + + if(!empty($sBorderColor) and $iBorderWidth > 0) + $this->resize_image_border($sBorderColor,$iBorderWidth,$iNewHeight,$iNewWidth); + else + $this->resize_image($iNewWidth,$iNewHeight); + } + + /** + * make_full() + * + * Function will make sure your image is as big or smaller than the sizes + * set here with $max_width and $max_height. Aspect ratio will be mantained. + * + * If none are set APPDB_SCREENSHOT_MAXWIDTH and APPDB_SCREENSHOT_MAXHEIGHT + * are used. + */ + function make_full($iMaxWidth = 0, $iMaxHeight = 0) + { + if(!$iMaxWidth > 0) + $iMaxWidth = APPDB_SCREENSHOT_MAXWIDTH; + + if(!$iMaxHeight > 0) + $iMaxHeight = APPDB_SCREENSHOT_MAXHEIGHT; + + if($this->iWidth > $iMaxWidth) + { + /* The width is too much */ + $iNewWidth = $iMaxWidth; + $iNewHeight = $this->calculate_proportions($this->iWidth,$this->iHeight,$iNewWidth); + + /* Check if the height is also within the limits */ + if($iNewHeight > $iMaxHeight ) + { + $iNewWidth = $this->calculate_proportions($iNewWidth,$iNewHeight,0,$iMaxHeight); + $iNewHeight = $iMaxHeight; + } + } + else if($this->iHeight > $iMaxHeight) + { + /* Width was ok, height not */ + $iNewWidth = $this->calculate_proportions($this->iWidth,$this->iHeight,0,$iMaxHeight); + $iNewHeight = $iMaxHeight; + } + else + { + /* All ok */ + $iNewWidth = $this->iWidth; + $iNewHeight = $this->iHeight; + } + + $this->set_debuglog("Resizing image to $iNewWidth x $iNewHeight"); + + $this->resize_image($iNewWidth, $iNewHeight); + } + + /** + * resize_image() + * + * Resizes the image with the width and height specified with + * $iNewHeight and $iNewWidth. + */ + function resize_image($iNewWidth, $iNewHeight) + { + // GD 2.x + if(function_exists("imagecreatetruecolor")) + { + $oNewImage = imagecreatetruecolor($iNewWidth, $iNewHeight); + imagecopyresampled($oNewImage,$this->oImage,0,0,0,0, + $iNewWidth,$iNewHeight,$this->iWidth,$this->iHeight); + } else // GD 1.x + { + $oNewImage = imagecreate($iNewWidth, $iNewHeight); + imagecopyresized($oNewImage,$this->oImage,0,0,0,0, + $iNewWidth,$iNewHeight,$this->iWidth,$this->iHeight); + } + + $this->set_debuglog("imagecopyresized($oNewImage,$this->oImage,0,0,0,0,$iNewWidth," + ."$iNewHeight,$this->iWidth,$this->iHeight);"); + imagedestroy($this->oImage); + $this->oImage = $oNewImage; + $this->iWidth = $iNewWidth; + $this->iHeight= $iNewHeight; + } + + /** + * resize_image_border() + * + * Resizes the image. With the $iNewWidth + $iBorderWidth*2 + * and $iNewHeight + $iBorderWidth*2 as size. $sBorderColor is a + * HTML hexadecimal color (like #0000FF) + */ + function resize_image_border($sBorderColor, $iBorderWidth, $iNewHeight, $iNewWidth) + { + $r = hexdec(substr($sBorderColor, 1, 2)); + $g = hexdec(substr($sBorderColor, 3, 2)); + $b = hexdec(substr($sBorderColor, 5, 2)); + + /* We multiply the border width by two because there are borders + on both sides */ + // GD 2.x + if(function_exists("imagecreatetruecolor")) + { + $new = imagecreatetruecolor($iNewWidth + ($iBorderWidth*2), $iNewHeight + ($iBorderWidth*2)); + } else // GD 1.x + { + $new = imagecreate($iNewWidth + ($iBorderWidth*2), $iNewHeight + ($iBorderWidth*2)); + } + + /* Make the border by filling it completely, + later on we will overwrite everything except the border */ + $color = ImageColorAllocate( $new, $r, $g, $b ); + imagefill($new,0,0,$color); + + // GD 2.x + if(function_exists("imagecopyresampled")) + { + imagecopyresampled($new,$this->oImage,$iBorderWidth,$iBorderWidth, + 0,0, $iNewWidth,$iNewHeight, + $this->iWidth,$this->iHeight); + } else // GD 1.x + { + imagecopyresized($new,$this->oImage,$iBorderWidth,$iBorderWidth, + 0,0,$iNewWidth,$iNewHeight, + $this->iWidth,$this->iHeight); + } + + $this->set_debuglog("imagecopyresized($new,$this->oImage,$iBorderWidth,$iBorderWidth,0,0," + ." $iNewWidth,$iNewHeight,$this->iWidth,$this->iHeight); with a $iBorderWidth px border" + ." in $sBorderColor"); + imagedestroy($this->oImage); + $this->oImage = $new; + $this->iWidth = $iNewWidth; + $this->iHeight= $iNewHeight; + } + + /** + * add_watermark() + * + * $watermark is an image resource identifier to any image resource. + * + * $min_mark_wwidth and $min_mark_height are the minimum sizes of the + * destination image before the watermark is added. If none are set + * both will be 0. + * + * A warning for transparency. If you resize an image down with make_thumb() + * you loose the transparency on png images. + */ + function add_watermark($oWatermark, $iMinMarkWidth = 0, $iMinMarkHeight = 0) + { + $iWatermarkWidth = imagesx($oWatermark); + $iWatermarkHeight = imagesy($oWatermark); + + if($this->iWidth > $iMinMarkWidth AND + $this->iHeight > $iMinMarkHeight) + { + $iWatermark_x = $this->iWidth - $iWatermarkWidth; + $iWatermark_y = $this->iHeight - $iWatermarkHeight; + + imagecopy($this->oImage, $oWatermark, $iWatermark_x, $iWatermark_y, + 0, 0, $iWatermarkWidth, $iWatermarkHeight); + + $this->set_debuglog("imagecopy($this->oImage, $oWatermark," + ."$iWatermark_x, $iWatermark_y, 0, 0," + ."$iWatermarkWidth, $iWatermarkHeight);"); + } + } + + /** + * Save the image to a file set with $store. + * + * $iType is optional and is set like the second index of getimagesize(). + * If none (or 0) is set the original type of the file is used. + * If $store is not give, the current file name will be used. + * $quality is the jpeg output quality (100 best, 0 worst). Default is 75 + */ + function output_to_file($sOutputFilename=null, $iType = 0, $iQuality = 75) + { + if(!$sOutputFilename) + $sOutputFilename = $this->sFile; + if($iType == 0) + $iType = $this->iType; + + switch($iType) + { + case 2: + imagejpeg($this->oImage, $sOutputFilename, $iQuality); + $this->set_debuglog("Saved file as jpeg to $sOutputFilename"); + break; + + case 3: + imagepng($this->oImage, $sOutputFilename); + $this->set_debuglog("Saved file as png to $sOutputFilename"); + break; + + default: + $this->set_debuglog("Unknown output type"); + return; + } + + return true; + } + + /** + * Output the files to the browser. + * + * If $bHeader is true a Content-type header with the correct type + * is set. + * $iType is optional and is set like the second index of getimagesize(). + * If none (or 0) is set the original type of the file is used. + * + * $iQuality is the jpeg output quality (100 best, 0 worst) + */ + function output_to_browser($bHeader, $iType = 0, $iQuality = 75) + { + if($iType == 0 ) + $iType = $this->iType; + + switch($iType) + { + case 2: + if($bHeader) + header('Content-type: image/jpeg'); + imagejpeg($this->oImage,'',$iQuality); + $this->set_debuglog("Outputed file as jpeg to browser"); + break; + + case 3: + if($bHeader) + header('Content-type: image/png'); + imagepng($this->oImage); + $this->set_debuglog("Outputed file as png to browser"); + break; + + default: + $this->set_debuglog("Unknown output type"); + } + } + + /** + * Destroys the image resource. Be sure to do this at the end of your + * actions with this object. + */ + function destroy() + { + if(is_resource($this->oImage)) + imagedestroy($this->oImage); + } + + /** + * Deletes the screenshot from the file system. + */ + function delete() + { + // if the file exists, delete it + if(is_file($this->sFile)) + unlink($this->sFile); + } + + + /*********************** + * PRIVATE FUNCTIONS + ************************/ + + function set_debuglog( $sLog ) + { + $this->aDebugLog[] = $sLog; + } + + function calculate_proportions($iWidth, $iHeight, + $iNewWidth, $iNewHeight = '0') + { + if($iNewWidth > 0) + // we want to calculate the new height + return ($iHeight * $iNewWidth) / $iWidth; + else if( $iNewHeight > 0 ) + return ($iWidth * $iNewHeight) / $iHeight; + else + return 0; + } + +} + + +class ImageResource extends Image { + + function ImageResource($oImage,$iType) + { + + $this->oImage = $oImage; + $this->iWidth = imagesx($oImage); + $this->iHeight = imagesy($oImage); + $this->iType = $iType; + + $this->set_debuglog("New image class created with $oImage as" + ." image resource and $iType as type. Dimensions" + ." {$this->iWidth}x{$this->iHeight}"); + } +} +?> diff --git a/include/incl.php b/include/incl.php new file mode 100644 index 0000000..624b7b1 --- /dev/null +++ b/include/incl.php @@ -0,0 +1,301 @@ +Please disable the magic quotes GPC PHP setting. See this page for more information

    "; + echo "AppDB php code assumes magic quotes are disabled.

    "; + echo "Magic quotes are a bad idea for a few reasons.

    "; + echo "First is that php calls addslashes() on all \$_POST, \$_REQUEST and cookie variables "; + echo "if magic quotes is enabled. "; + echo "Ooooooh you say.
    "; + echo "\"Aren't magic quotes a convienent way to protect my php code from sql injection attacks?\"

    "; + echo "No! addslashes() isn't adequate. You should use query_escape_string() or some other function"; + echo " that will handle multi-byte characters. See this article"; + echo " for a way to exploit addslash()ed parameters.

    "; + echo "A second reason is that with magic quotes enabled, due to the use of query_escape_string() to"; + echo " protect from sql injection attacks we'll end up with variables that have been addslash()ed and"; + echo " query_escape_string()ed. So you end up having to call stripslashes() on EVERY variable. "; + exit; +} + +/** + * rename $_REQUEST variables to preserve backwards compatibility + * with bugzilla links and urls in emails and on google from before our + * mass rename of GPC variables to use our coding standard prefixing + * + * NOTE: we may be able to remove these backwareds compatibility changes + * in a few years, check in mid 2007 to see how many old + * links are still poping up in google then + */ +if(isset($_REQUEST['versionId'])) +{ + $_REQUEST['iVersionId'] = $_REQUEST['versionId']; + unset($_REQUEST['versionId']); +} +if(isset($_REQUEST['appId'])) +{ + $_REQUEST['iAppId'] = $_REQUEST['appId']; + unset($_REQUEST['appId']); +} +if(isset($_REQUEST['bug_id'])) +{ + $_REQUEST['iBugId'] = $_REQUEST['bug_id']; + unset($_REQUEST['bug_id']); +} +if(isset($_REQUEST['catId'])) +{ + $_REQUEST['iCatId'] = $_REQUEST['catId']; + unset($_REQUEST['catId']); +} +if(isset($_REQUEST['sub'])) +{ + $_REQUEST['sSub'] = $_REQUEST['sub']; + unset($_REQUEST['sub']); +} +if(isset($_REQUEST['topic'])) +{ + $_REQUEST['sTopic'] = $_REQUEST['topic']; + unset($_REQUEST['topic']); +} +if(isset($_REQUEST['mode'])) +{ + $_REQUEST['sMode'] = $_REQUEST['mode']; + unset($_REQUEST['mode']); +} +/* End backwards compatibility code */ + +// create arrays +$sidebar_func_list = array(); +$help_list = array(); + +function apidb_help_add($desc, $id) +{ + global $help_list; + $help_list[] = array($desc, $id); +} + + +// return url with docroot prepended +function apidb_url($path) +{ + return BASE.$path; +} + +// return FULL url with docroot prepended +function apidb_fullurl($path = "") +{ + return BASE.$path; +} + +function appdb_fullpath($path) +{ + /* IE: we know this file is in /yyy/xxx/include, we want to get the /yyy/xxx + /* so we call dirname on this file path twice */ + $fullpath = dirname(dirname(__FILE__))."//".$path; + /* get rid of potential double slashes due to string concat */ + return str_replace("//", "/", $fullpath); +} + + +/* + * output the common apidb header + */ +function apidb_header($title = 0) +{ + $realname = $_SESSION['current']->sRealname; + + // Set Page Title + $page_title = $title; + if ($title) + $title = " - $title"; + + // grab the starting time + global $sPageGeneratingStartTime; + $sPageGeneratingStartTime = microtime(); + $aStartarray = explode(" ", $sPageGeneratingStartTime); + $sPageGeneratingStartTime = $aStartarray[1] + $aStartarray[0]; + + // Display Header + include(BASE."include/header.php"); + + // Display Sidebar + apidb_sidebar(); + + // Display Status Messages + dumpmsgbuffer(); +} + + +/* + * output the common apidb footer + */ +function apidb_footer() +{ + // grab the end of the page generating time + global $sPageGeneratingStartTime; + $sPageGeneratingEndTime = microtime(); + $aEndarray = explode(" ", $sPageGeneratingEndTime); + $sPageGeneratingEndTime = $aEndarray[1] + $aEndarray[0]; + $sTotaltime = $sPageGeneratingEndTime - $sPageGeneratingStartTime; + $sTotaltime = round($sTotaltime,5); + echo "
    Page loaded in $sTotaltime seconds.
    "; + + // Display Footer + if(!isset($header_disabled)) + include(BASE."include/"."footer.php"); +} + +/* + * output the sidebar, calls all functions registered with apidb_sidebar_add + */ +function apidb_sidebar() +{ + global $sidebar_func_list; + +echo ' + +'; + +} + + +/** + * register a sidebar menu function + * the supplied function is called when the sidebar is built + */ +function apidb_sidebar_add($funcname) +{ + global $sidebar_func_list; + array_unshift($sidebar_func_list, $funcname); +} + + +function apidb_image($name) +{ + return BASE."images/$name"; +} + + +/** + * format a date as required for HTTP by RFC 2068 sec 3.3.1 + */ +function fHttpDate($iDate) { + return gmdate("D, d M Y H:i:s",$iDate)." GMT"; +} + +/** + * parse all the date formats required by HTTP 1.1 into PHP time values + */ +function pHttpDate($sDate) { + $iDate = strtotime($sDate); + if ($iDate != -1) return $iDate; + /* the RFC also requires asctime() format... */ + $aTs = strptime($sDate,"%a %b %e %H:%M:%S %Y"); + $iDate = gmmktime($aTs[2],$aTs[1],$aTs[0],$aTs[4],$aTs[3],$aTs[5],0); + return $iDate; +} + +/** + * msgs will be displayed on the Next page view of the same user + */ +function addmsg($shText, $color = "black") +{ + $GLOBALS['session']->addmsg($shText, $color); +} + + +function purgeSessionMessages() +{ + $GLOBALS['session']->purgemsg(); +} + + +/** + * output msg_buffer and clear it. + */ +function dumpmsgbuffer() +{ + $GLOBALS['session']->dumpmsgbuffer(); + if (is_array($GLOBALS['session']->msg) and count($GLOBALS['session']->msg) > 0) + { + echo html_frame_start("","300","",5); + foreach ($GLOBALS['session']->msg as $msg) + { + if ($msg['color'] == "red") + $msg['color'] = "{$msg['color']}; text-decoration: blink;"; + echo "
    {$msg['msg']}
    "; + } + echo html_frame_end(" "); + echo "
    \n"; + } +} + +/** + * Init Session (stores user info in session) + */ +$session = new session("whq_appdb"); +$session->register("current"); + +if(!isset($_SESSION['current'])) +{ + $_SESSION['current'] = new User(); +} + +// if we are debugging we need to see all errors +if($_SESSION['current']->showDebuggingInfos()) error_reporting(E_ALL ^ E_NOTICE); + +// include filter.php to filter all REQUEST input +require(BASE."include/filter.php"); + +?> diff --git a/include/mail.php b/include/mail.php new file mode 100644 index 0000000..1c8fb65 --- /dev/null +++ b/include/mail.php @@ -0,0 +1,48 @@ +\r\n"; + $sHeaders .= "Reply-to: AppDB <".APPDB_SENDER_EMAIL.">\r\n"; + $sHeaders .= "Bcc: $sEmailListComma\r\n"; + $sHeaders .= "X-Priority: 3\r\n"; + $sHeaders .= "X-Mailer: ".APPDB_OWNER." mailer\r\n"; + $sMsg = trim(ereg_replace("\r\n","\n",$sMsg)); + $sMsg = $sSubject."\n-------------------------------------------------------\n".$sMsg."\n\n"; + $sMsg .= "Best regards.\n"; + $sMsg .= "The AppDB team\n"; + $sMsg .= APPDB_ROOT."\n"; + $sMsg .= "\n\nIf you don't want to receive any other e-mail, please change your preferences:\n"; + $sMsg .= APPDB_ROOT."preferences.php\n"; + + /* Print the message to the screen instead of sending it, if the PRINT_EMAIL + option is set. Output in purple to distinguish it from other messages */ + if(defined("PRINT_EMAIL")) + { + $sMsg = str_replace("\n", "
    ", $sMsg); + addmsg("This mail would have been sent

    ". + "To: $sEmailList
    ". + "Subject: $sSubject

    ". + "Body:
    $sMsg", "purple"); + return; + } + + $sMsg = html_entity_decode($sMsg); + $bResult = mail(APPDB_SENDER_EMAIL, "[AppDB] ".$sSubject, $sMsg, $sHeaders, + "-f".APPDB_SENDER_EMAIL); + if($bResult) + addmsg("E-mail sent", "green"); + else + addmsg("Error while sending e-mail", "red"); + return $bResult; +} +?> diff --git a/include/maintainer.php b/include/maintainer.php new file mode 100644 index 0000000..2acbd5f --- /dev/null +++ b/include/maintainer.php @@ -0,0 +1,1414 @@ +oMaintainer = $oMaintainer; + + $this->aVersionIds = array(); + $this->aScreenshotIds = array(); + $this->aTestDataIds = array(); + } + + // returns true if none of the arrays have any entries in them + function isEmpty() + { + if((count($this->aVersionIds) == 0) && + (count($this->aScreenshotIds) == 0) && + (count($this->aTestDataIds) == 0)) + { + return true; + } + + return false; + } + + function retrieveQueuedEntries() + { + $bDebugOutputEnabled = false; + + if($bDebugOutputEnabled) + echo "retrieveQueuedEntries() starting\n"; + + //////////////////////////////////// + // retrieve a list of versions to check for queued data + $aVersionsToCheck = array(); + if($this->oMaintainer->bSuperMaintainer) + { + if($bDebugOutputEnabled) + echo "maintainer is super maintainer\n"; + + $oApp = new Application($this->oMaintainer->iAppId); + + //TODO: would like to rely on the constructor but we might be a user with 'admin' + // privileges and that would mean we would end up retrieved queued versions for + // this application or unqueued versions depending on which user we were + $aVersions = $oApp->getVersions(); + + foreach($aVersions as $oVersion) + { + if($bDebugOutputEnabled) + { + echo "Processing version: "; + print_r($oVersion); + } + + if($oVersion->objectGetState() == 'queued') + { + $this->aVersions[] = $oVersion->objectGetId(); + } else if($oVersion->objectGetState() == 'accepted') // version isn't queued + { + // add the unqueued version to the list of versions to check for queued data + $aVersionsToCheck[] = $oVersion->iVersionId; + } + } + } else // just a normal maintainer + { + $aVersionsToCheck[] = $this->oMaintainer->iVersionId; + if($bDebugOutputEnabled) + echo "Normal maintainer of version ".$this->oMaintainer->iVersionId."\n"; + } + + // go through all of the verions to see what queued data they have + foreach($aVersionsToCheck as $iVersionId) + { + if($bDebugOutputEnabled) + echo "Processing iVersionId of ".$iVersionId."\n"; + + ////////////////// + // queued testdata + + // retrieve queued testdata for this version + $sQuery = "select * from testResults where versionId = '?' and state = '?'"; + $hResult = query_parameters($sQuery, $iVersionId, 'queued'); + + // go through the test results looking for the oldest queued data + while($oTestingRow = query_fetch_object($hResult)) + { + if($bDebugOutputEnabled) + echo "\tQueued TestData found\n"; + $oTestData = new TestData(null, $oTestingRow); + + $this->aTestDataIds[] = $oTestData->objectGetId(); + } + // queued testdata + ////////////////// + + + //////////////////// + // queued screenshots + $sQuery = "select * from appData where type = 'screenshot' and versionId = '?' and state = '?'"; + $hResult = query_parameters($sQuery, $iVersionId, 'queued'); + while($oScreenshotRow = query_fetch_object($hResult)) + { + $oScreenshot = new Screenshot(null, $oScreenshotRow); + + $this->aScreenshotIds[] = $oScreenshot->objectGetId(); + } + // queued screenshots + ////////////////////// + } + } +} + +// contains the results of a notification update so other logic +// can act on these results +class notificationUpdate +{ + var $sEmail; + var $sSubject; + var $sMsg; // contents of the email we will send to the maintainer + var $iTargetLevel; // the target notification level based upon the + // maintiners queued entries + + function notificationUpdate($sEmail, $sSubject, $sMsg, $iTargetLevel) + { + $this->sEmail = $sEmail; + $this->sSubject = $sSubject; + $this->sMsg = $sMsg; + $this->iTargetLevel = $iTargetLevel; + } +} + + +class maintainer +{ + var $iMaintainerId; + var $iAppId; + var $iVersionId; + var $iUserId; + var $sMaintainReason; + var $bSuperMaintainer; + var $aSubmitTime; //FIXME: should be 'sSubmitTime' + var $sState; + var $sReplyText; + + // parameters used in the queued data notification system + // that lets maintainers know that their applications/versions have + // queued data for them to process + var $iNotificationLevel; // the current warning level of this maintainer + var $sNotificationTime; // the time when we last warned this maintainer + + function maintainer($iMaintainerId = null, $oRow = null) + { + // set a default notification level of 0 + $this->iNotificationLevel = 0; + + if(!$iMaintainerId && !$oRow) + return; + + if(!$oRow) + { + $sQuery = "SELECT * FROM appMaintainers WHERE maintainerId = '?'"; + $hResult = query_parameters($sQuery, $iMaintainerId); + if($hResult) + $oRow = query_fetch_object($hResult); + } + + if($oRow) + { + $this->iMaintainerId = $oRow->maintainerId; + $this->iAppId = $oRow->appId; + $this->iVersionId = $oRow->versionId; + $this->iUserId = $oRow->userId; + $this->sMaintainReason = $oRow->maintainReason; + $this->bSuperMaintainer = $oRow->superMaintainer; + $this->aSubmitTime = $oRow->submitTime; + $this->sState = $oRow->state; + + $this->iNotificationLevel = $oRow->notificationLevel; + $this->sNotificationTime = $oRow->notificationTime; + } + } + + function create() + { + /* user id, appid, and maintain reason must be valid to continue */ + if(!$this->iAppId || !$this->sMaintainReason) + { + return NULL; + } + + if(!$this->iUserId) + $this->iUserId = $_SESSION['current']->iUserId; + + $oApp = new application($this->iAppId); + if(!$this->bSuperMaintainer) + $oVersion = new version($this->iVersionId); + + if($oApp->objectGetState() != 'accepted' || + (!$this->bSuperMaintainer && $oVersion->objectGetState() != 'accepted')) + $this->sState = "pending"; + else + $this->sState = $this->mustBeQueued() ? 'queued' : 'accepted'; + + $hResult = query_parameters("INSERT INTO appMaintainers (appId, versionId, ". + "userId, maintainReason, superMaintainer, submitTime, state) ". + "VALUES ('?', '?', '?', '?', '?', ?, '?')", + $this->iAppId, $this->iVersionId, + $this->iUserId, $this->sMaintainReason, + $this->bSuperMaintainer, "NOW()", $this->sState); + + /* this objects id is the insert id returned by the database */ + $this->iMaintainerId = query_appdb_insert_id(); + + /* If this is a non-queued maintainer submission, remove the user's non- + super maintainer entries for the application's versions. This check is + also done in unQueue() */ + if(!$this->mustBeQueued() & $this->bSuperMaintainer) + $this->removeUserFromAppVersions(); + + return $hResult; + } + + function unQueue() + { + /* if the user isn't already a supermaintainer of the application and */ + /* if they are trying to become a maintainer and aren't already a maintainer of */ + /* the version, then continue processing the request */ + + $oUser = new User($this->iUserId); + + if(!$oUser->isSuperMaintainer($this->iAppId) && + ((!$this->bSuperMaintainer && !$oUser->isMaintainer($this->iVersionId)) || $this->bSuperMaintainer)) + { + /* unqueue the maintainer entry */ + $hResult = query_parameters("UPDATE appMaintainers SET state='accepted' WHERE userId = '?' AND maintainerId = '?'", + $this->iUserId, $this->iMaintainerId); + + if($hResult) + { + $sStatusMessage = "

    The maintainer was successfully added into the database

    \n"; + + //Send Status Email + $sEmail = $oUser->sEmail; + if ($sEmail) + { + if($this->iVersionId) + { + $oVersion = new Version($this->iVersionId); + $sURL = $oVersion->objectMakeUrl(); + $sName = version::fullName($this->iVersionId); + } else + { + $oApp = new Application($this->iAppId); + $sURL = $oApp->objectMakeUrl(); + $sName = $oApp->sName; + } + + $sSubject = "Application Maintainer Request Report"; + $sMsg = "Your application to be the maintainer of $sName has been accepted.\n"; + $sMsg .= "$sURL\n"; + $sMsg .= "$this->sReplyText\n"; + $sMsg .= "We appreciate your help in making the Application Database better for all users.\n\n"; + + mail_appdb($sEmail, $sSubject ,$sMsg); + } + $this->sState = 'accepted'; + } + } else + { + /* Delete entry, but only if queued */ + query_parameters("DELETE from appMaintainers WHERE userId = '?' AND maintainerId = '?' AND state = 'queued'", $this->iUserId, $this->iMaintainerId); + + if($oUser->isSuperMaintainer($this->iAppId) && !$this->bSuperMaintainer) + $sStatusMessage = "

    User is already a super maintainer of this application

    \n"; + else + $sStatusMessage = "

    User is already a maintainer/super maintainer of this application/version

    \n"; + } + + /* Delete any maintainer entries the user had for the application's versions, + if this is a super maintainer request */ + if($this->bSuperMaintainer) + $this->removeUserFromAppVersions(); + + return $sStatusMessage; + } + + function reject() + { + $oUser = new User($this->iUserId); + $sEmail = $oUser->sEmail; + if ($sEmail) + { + $oApp = new Application($oRow->appId); + $oVersion = new Version($oRow->versionId); + $sSubject = "Application Maintainer Request Report"; + $sMsg = "Your application to be the maintainer of ".$oApp->sName." ".$oVersion->sName." was rejected. "; + $sMsg .= $this->sReplyText; + $sMsg .= ""; + $sMsg .= "-The AppDB admins\n"; + + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + //delete main item + $sQuery = "DELETE from appMaintainers where maintainerId = '?'"; + $hResult = query_parameters($sQuery, $this->iMaintainerId); + + return $hResult; + } + + function mustBeQueued() + { + /* In place for future fine-grained permisson system, only allow admins for now */ + if($_SESSION['current']->hasPriv("admin")) + return FALSE; + else + return TRUE; + } + + function purge() + { + return $this->delete(); + } + + function delete() + { + $sQuery = "DELETE from appMaintainers where maintainerId = '?'"; + $hResult = query_parameters($sQuery, $this->iMaintainerId); + + if(!$hResult) + return FALSE; + + return TRUE; + } + + function deleteMaintainer($oUser, $iAppId = null, $iVersionId = null) + { + /* remove supermaintainer */ + if($iAppId && ($iVersionId == null)) + { + $superMaintainer = 1; + $hResult = query_parameters("DELETE FROM appMaintainers WHERE userId = '?' + AND appId = '?' AND superMaintainer = '?'", + $oUser->iUserId, $iAppId, $superMaintainer); + } else if($iAppId && $iVersionId) /* remove a normal maintainer */ + { + $superMaintainer = 0; + $hResult = query_parameters("DELETE FROM appMaintainers WHERE userId = '?' + AND appId = '?' AND versionId = '?' AND superMaintainer = '?'", + $oUser->iUserId, $iAppId, $iVersionId, $superMaintainer); + } else if(($iAppId == null) && ($iVersionId == null)) /* remove all maintainership by this user */ + { + $hResult = query_parameters("DELETE FROM appMaintainers WHERE userId = '?'", + $oUser->iUserId); + } + + if($hResult) + return true; + + return false; + } + + function deleteMaintainersForVersion($oVersion) + { + if(!$oVersion->iVersionId) + return FALSE; + + $hResult = query_parameters("DELETE from appMaintainers WHERE versionId='?'", + $oVersion->iVersionId); + return $hResult; + } + + function deleteMaintainersForApplication($oApp) + { + $sQuery = "DELETE from appMaintainers WHERE appId='?'"; + $hResult = query_parameters($sQuery, $oApp->iAppId); + return $hResult; + } + + function getSubmitterEmails() + { + $sRecipients = ''; + $sQuery = "SELECT DISTINCT(user_list.email) FROM appMaintainers, user_list WHERE + appMaintainers.userId = user_list.userId + AND + appMaintainers.state = 'accepted'"; + $hResult = query_parameters($sQuery); + if(!$hResult) + return FALSE; + for($i = 0; $oRow = query_fetch_object($hResult); $i++) + { + if($i) + $sRecipients .= ' '; + $sRecipients .= $oRow->email; + } + return $sRecipients; + } + + function ObjectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true) + { + /* Not implemented */ + if($sState == 'rejected') + return FALSE; + + $sLimit = ""; + + /* Should we add a limit clause to the query? */ + if($iRows || $iStart) + { + $sLimit = " LIMIT ?,?"; + + /* Selecting 0 rows makes no sense, so we assume the user wants to select all of them + after an offset given by iStart */ + if(!$iRows) + $iRows = maintainer::objectGetEntriesCount($sState); + } + + /* Excluding requests for queued apps and versions, as these will be + handled automatically */ + $sQuery = "SELECT * FROM appMaintainers WHERE + appMaintainers.state = '?'$sLimit"; + + if($sState != 'accepted') + { + if($_SESSION['current']->hasPriv("admin")) + { + if($sLimit) + { + return query_parameters($sQuery, $sState, $iStart, $iRows); + } else + { + return query_parameters($sQuery, $sState); + } + } else + { + return NULL; + } + } else + { + if($sLimit) + { + return query_parameters($sQuery, $sState, $iStart, $iRows); + } else + { + return query_parameters($sQuery, $sState); + } + } + } + + /* retrieve a maintainer object from a row returned by */ + /* ObjectGetEntries() */ + function ObjectGetObjectFromObjectGetEntriesRow($oRow) + { + return new maintainer($oRow->maintainerId); + } + + // returns the number of applications/versions a particular user maintains + function getMaintainerCountForUser($oUser, $bSuperMaintainer) + { + $sQuery = "SELECT count(*) as cnt from appMaintainers WHERE userid = '?' AND superMaintainer = '?'". + " AND state ='?'"; + $hResult = query_parameters($sQuery, $oUser->iUserId, $bSuperMaintainer ? "1" : "0", 'accepted'); + if(!$hResult) + return 0; + $oRow = query_fetch_object($hResult); + return $oRow->cnt; + } + + /** + * get the applications and versions that this user maintains + */ + function getAppsMaintained($oUser) + { + /* retrieve the list of application and order them by application name */ + $hResult = query_parameters("SELECT appMaintainers.appId, versionId, superMaintainer, appName FROM ". + "appFamily, appMaintainers WHERE appFamily.appId = appMaintainers.appId ". + "AND userId = '?' AND appMaintainers.state = '?' ORDER BY appName", + $oUser->iUserId, 'accepted'); + if(!$hResult || query_num_rows($hResult) == 0) + return NULL; + + $aAppsMaintained = array(); + $c = 0; + while($oRow = query_fetch_object($hResult)) + { + $aAppsMaintained[$c] = array($oRow->appId, $oRow->versionId, $oRow->superMaintainer); + $c++; + } + + return $aAppsMaintained; + } + + function objectGetEntriesCount($sState) + { + /* Not implemented */ + if($sState == 'rejected') + return FALSE; + + /* Excluding requests for queued apps and versions, as these are handled + automatically. One SELECT for super maintainers, one for maintainers. */ + $sQuery = "SELECT COUNT(maintainerId) as count FROM appMaintainers WHERE + appMaintainers.state = '?'"; + + if(!($hResult = query_parameters($sQuery, $sState))) + return FALSE; + + if($oRow = query_fetch_object($hResult)) + $iCount = $oRow->count; + else + $iCount = 0; + + return $iCount; + } + + /* see how many unique maintainers we actually have */ + function getNumberOfMaintainers() + { + $hResult = query_parameters("SELECT DISTINCT userId FROM appMaintainers WHERE state='accepted';"); + return query_num_rows($hResult); + } + + function isUserMaintainer($oUser, $iVersionId = null) + { + /* if we are a super maintainer, we are a maintainer of this version as well */ + $oVersion = new Version($iVersionId); + if($oUser->isSuperMaintainer($oVersion->iAppId)) + return true; + + /* otherwise check if we maintain this specific version */ + if($iVersionId) + { + $sQuery = "SELECT * FROM appMaintainers WHERE userId = '?' AND versionId = '?' AND state = '?'"; + $hResult = query_parameters($sQuery, $oUser->iUserId, $iVersionId, 'accepted'); + } else // are we maintaining any version ? + { + $sQuery = "SELECT * FROM appMaintainers WHERE userId = '?' AND state = '?'"; + $hResult = query_parameters($sQuery, $oUser->iUserId, 'accepted'); + } + if(!$hResult) + return false; + + return query_num_rows($hResult); + } + + function isUserSuperMaintainer($oUser, $iAppId = null) + { + if($iAppId) + { + $sQuery = "SELECT * FROM appMaintainers WHERE userid = '?' AND appId = '?' AND superMaintainer = '1' AND state = '?'"; + $hResult = query_parameters($sQuery, $oUser->iUserId, $iAppId, 'accepted'); + } else /* are we super maintainer of any applications? */ + { + $sQuery = "SELECT * FROM appMaintainers WHERE userid = '?' AND superMaintainer = '1' AND state = '?'"; + $hResult = query_parameters($sQuery, $oUser->iUserId, 'accepted'); + } + if(!$hResult) + return false; + return query_num_rows($hResult); + } + + /* if given an appid or a version id return a handle for a query that has */ + /* the user ids that are maintainers for this particular appid or version id */ + function getMaintainersForAppIdVersionId($iAppId = null, $iVersionId = null) + { + $hResult = null; + + if($iVersionId) + { + $hResult = query_parameters("SELECT userId from appMaintainers, appVersion + WHERE + appMaintainers.state = 'accepted' + AND + appVersion.versionId = '?' + AND + ( + appMaintainers.versionId = appVersion.versionId + OR + ( + appMaintainers.appId = appVersion.appId + AND superMaintainer = '1' + ) + )", $iVersionId); + } + /* + * If versionId was not supplied we fetch supermaintainers of application and maintainer of all versions. + */ + elseif($iAppId) + { + $hResult = query_parameters("SELECT userId + FROM appMaintainers + WHERE appId = '?' AND state = 'accepted'", + $iAppId); + } + + return $hResult; + } + + /* + * get the userIds of super maintainers for this appId + */ + function getSuperMaintainersUserIdsFromAppId($iAppId) + { + $sQuery = "SELECT userId FROM ". + "appMaintainers WHERE appId = '?' " . + "AND superMaintainer = '1' AND state='?';"; + $hResult = query_parameters($sQuery, $iAppId, 'accepted'); + $aUserIds = array(); + $c = 0; + while($oRow = query_fetch_object($hResult)) + { + $aUserIds[$c] = $oRow->userId; + $c++; + } + + return $aUserIds; + } + + function ObjectGetHeader() + { + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("Submission Date"); + $oTableRow->AddTextCell("Application Name"); + $oTableRow->AddTextCell("Version"); + $oTableRow->AddTextCell("Super maintainer?"); + $oTableRow->AddTextCell("Submitter"); + return $oTableRow; + } + + function ObjectGetTableRow() + { + $oUser = new User($this->iUserId); + $oApp = new Application($this->iAppId); + $oVersion = new Version($this->iVersionId); + + $oTableRow = new TableRow(); + + $oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($this->aSubmitTime))); + $oTableRow->AddTextCell($oApp->objectMakeLink()); + $oTableRow->AddTextCell(($this->bSuperMaintainer) ? "N/A" : $oVersion->objectMakeLink()); + $oTableRow->AddTextCell(($this->bSuperMaintainer) ? "Yes" : "No"); + $oTableRow->AddTextCell($oUser->objectMakeLink()); + + $oOMTableRow = new OMTableRow($oTableRow); + return $oOMTableRow; + } + + function objectDisplayAddItemHelp($aClean) + { + echo "

    This page is for submitting a request to become an application maintainer.\n"; + echo "An application maintainer is someone who runs the application \n"; + echo "regularly and who is willing to be active in reporting regressions with newer \n"; + echo "versions of Wine and to help other users run this application under Wine.

    "; + echo "

    Being an application maintainer comes with new rights and new responsibilities; please be sure to read the maintainer's guidelines before to proceed.

    "; + echo "

    We ask that all maintainers explain why they want to be an application maintainer,\n"; + echo "why they think they will do a good job and a little about their experience\n"; + echo "with Wine. This is both to give you time to\n"; + echo "think about whether you really want to be an application maintainer and also for the\n"; + echo "appdb admins to identify people that are best suited for the job. Your request\n"; + echo "may be denied if there are already a handful of maintainers for this application or if you\n"; + echo "don't have the experience with Wine that is necessary to help other users out.

    \n"; + + if(!$aClean['iVersionId']) + { + echo "

    Super maintainers are just like normal maintainers but they can modify EVERY version of\n"; + echo "this application (and the application itself). We don't expect you to run every version but at least to help keep\n"; + echo "the forums clean of stale and out-of-date information.

    \n"; + + } + } + + function ObjectDisplayQueueProcessingHelp() + { + echo "
    \n\n"; + echo "Please enter an accurate and personalized reply anytime a maintainer request is rejected.\n"; + echo "Its not polite to reject someones attempt at trying to help out without explaining why.\n"; + echo "
    \n\n"; + } + + function objectGetState() + { + return $this->sState; + } + + function canEdit() + { + if($_SESSION['current']->hasPriv("admin") || $this->iUserId == $_SESSION['current']->iUserId) + return TRUE; + + return FALSE; + } + + function objectGetCustomVars($sAction) + { + switch($sAction) + { + case "add": + return array("iAppId","iVersionId"); + + case "addHelp": + return array("iVersionId"); + + default: + return null; + } + } + + function outputEditor($aClean = null) + { + if(!$this->iMaintainerId) + { + if($aClean['iVersionId']) + { + $oVersion = new version($aClean['iVersionId']); + $iAppId = $oVersion->iAppId; + } else + { + $iAppId = $aClean['iAppId']; + } + + $oApp = new application($iAppId); + + echo "\n"; + echo "',"\n"; + if($aClean['iVersionId']) + { + echo "',"\n"; + } + + $iSuperMaintainer = $aClean['iVersionId'] ? 0 : 1; + echo ""; + echo ""; + echo ""; + + if($iSuperMaintainer) + echo '',"\n"; + else + echo '',"\n"; + + echo '
    "; + echo 'Application'.$oApp->sName; + echo '
    "; + echo 'Version'.$oVersion->sName; + echo '
    Why you want to and should
    be an application super maintainer
    Why you want to and should
    be an application maintainer
    ',"\n"; + } else + { + + //view application details + echo html_frame_start("New Maintainer Form",600,"",0); + echo "\n"; + echo "iMaintainerId\">"; + + /* User name */ + $oSubmitter = new user($this->iUserId); + echo html_tr(array( + array("User name", 'style="text-align:right" class="color0"'), + $oSubmitter->objectMakeLink() + )); + + /** + * Show the other maintainers of this application, if there are any + */ + echo '\n"; + + // Show which other apps the user maintains + echo '\n"; + + $oApp = new Application($this->iAppId); + $oVersion = new Version($this->iVersionId); + + echo "iAppId."\">\n"; + echo "iVersionId."\">\n"; + + //app name + echo '',"\n"; + echo "\n"; + + //version + if($oVersion->iVersionId) + { + echo '',"\n"; + echo "\n"; + } + + //maintainReason + echo '',"\n"; + echo '',"\n"; + echo '
    Other maintainers'; + /* Fetch maintainers and super maintainers */ + $oVersion = new Version($this->iVersionId); + $aOtherMaintainers = $oVersion->getMaintainersUserIds(); + $aOtherSuperMaintainers = + Maintainer::getSuperMaintainersUserIdsFromAppId($this->iAppId); + + if($aOtherMaintainers || $aOtherSuperMaintainers) + $bFoundMaintainers = true; + else + $bFoundMaintainers = false; + + echo "\n"; + /* display maintainers for the version */ + if($aOtherMaintainers) + { + while(list($index, $iUserId) = each($aOtherMaintainers)) + { + $oUser = new User($iUserId); + + // because Version::getMaintainersUserIds() includes super maintainers + // we need to exclude these from the list of maintainers that we are + // building + if(!maintainer::isUserSuperMaintainer($oUser, $oVersion->iAppId)) + echo "$oUser->sRealname
    \n"; + } + } + + /* display super maintainers for the given app */ + + if($aOtherSuperMaintainers) + { + while(list($index, $iUserId) = each($aOtherSuperMaintainers)) + { + $oUser = new User($iUserId); + echo "$oUser->sRealname*
    \n"; + } + } + + if(!$bFoundMaintainers) + { + echo "No other maintainers"; + } + + echo "
    This user also maintains these apps:'; + echo "
    iUserId}&sTitle=Maintained+Apps\">Detailed view"; + echo '
    ',"\n"; + + $oUser = new User($this->iUserId); + $aOtherApps = Maintainer::getAppsMaintained($oUser); + if($aOtherApps) + { + while(list($index, list($iAppIdOther, $iVersionIdOther, $bSuperMaintainerOther)) = each($aOtherApps)) + { + $oApp = new Application($iAppIdOther); + + if($bSuperMaintainerOther) + echo $oApp->objectMakeLink()."*
    \n"; + else + echo $oVersion->fullNameLink($iVersionIdOther)."
    \n"; + } + } else + { + echo "User maintains no other applications"; + } + + echo "
    App Name:".$oApp->objectMakeLink()."
    App Version:".$oVersion->objectMakeLink()."
    Maintainer request reason:
    '; + + echo html_frame_end(" "); + } + } + + function ObjectGetId() + { + return $this->iMaintainerId; + } + + function getOutputEditorValues($aClean) + { + $this->iAppId = $aClean['iAppId']; + $this->iVersionId = $aClean['iVersionId']; + $this->sReplyText = $aClean['sReplyText']; + $this->sMaintainReason = $aClean['sMaintainReason']; + $this->bSuperMaintainer = $this->iVersionId ? 0 : 1; + + return TRUE; + } + + function objectGetItemsPerPage($sState = 'accepted') + { + $aItemsPerPage = array(25, 50, 100, 200); + $iDefaultPerPage = 25; + return array($aItemsPerPage, $iDefaultPerPage); + } + + public function objectGetParent($sClass = '') + { + if($this->iVersionId) + return new version($this->iVersionId); + else + return new application($this->iAppId); + } + + public function objectSetParent($iNewId, $sClass = '') + { + if($this->iVersionId) + $this->iVersionId = $iNewId; + else + $this->iAppId = $iNewId; + } + + function objectGetChildren($bIncludeDeleted = false) + { + /* We have none */ + return array(); + } + + public function update() + { + $oMaintainer = new maintainer($this->iMaintainerId); + + if($this->iVersionId && $oMaintainer->iVersionId != $this->iVersionId) + { + $hResult = query_parameters("UPDATE appMaintainers SET versionId = '?' + WHERE maintainerId = '?'", + $this->iVersionId, $this->iMaintainerId); + + if(!$hResult) + return FALSE; + } + + if($this->iAppId && $oMaintainer->iAppId != $this->iAppId) + { + $hResult = query_parameters("UPDATE appMaintainers SET appId = '?' + WHERE maintainerId = '?'", + $this->iAppId, $this->iMaintainerId); + + if(!$hResult) + return FALSE; + } + + return TRUE; + } + + function getDefaultReply() + { + $sReplyTextHelp = "Enter a personalized reason for accepting or rejecting the ". + "user's maintainer request here"; + + return $sReplyTextHelp; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + $oSubmitter = new user($this->iUserId); + + $sVerb = $this->sState == 'queued' ? 'rejected' : 'removed'; + + if($this->bSuperMaintainer) + { + $oApp = new application($this->iAppId); + $sFor = $oApp->sName; + } else + { + $sFor = version::fullName($this->iVersionId); + } + + $sMsg = null; + $sSubject = null; + + if($bMailSubmitter) + { + switch($sAction) + { + case "delete": + $sSubject = "Maintainership for $sFor $sVerb"; + if($this->sState == 'queued') + { + $sMsg = "Your request to be a maintainer of '$sFor'". + " has been denied."; + } else + { + $sMsg = "You have been removed as a maintainer of ". + "'$sFor'."; + } + break; + } + $aMailTo = null; + } else + { + switch($sAction) + { + case "delete": + if(!$bParentAction) + { + $sSubject = "Maintainership for $sFor $sVerb"; + if($this->sState == 'accepted') + { + $sMsg = $oSubmitter->sRealname." has been removed as a ". + "maintainer of $sFor."; + } else + { + $sMsg = $oSubmitter->sRealname."'s request to be a maintainer ". + " of $sFor has been rejected."; + } + } + break; + } + $aMailTo = User::get_notify_email_address_list(null, null); + } + return array($sSubject, $sMsg, $aMailTo); + } + + function objectGetSubmitterId() + { + return $this->iUserId; + } + + function objectHideDelete() + { + return TRUE; + } + + function display() + { + /* STUB: There is not much use for this, but it may be implemented later */ + return TRUE; + } + + function objectMakeUrl() + { + /* STUB: There is not much use for this, but it may be implemented later */ + return TRUE; + } + + function objectMakeLink() + { + /* STUB: There is not much use for this, but it may be implemented later */ + return TRUE; + } + + /* Delete a user's non-super maintainer entries for an application. This is useful + to ensure that the user has no maintainer entries for an app he supermaintains */ + function removeUserFromAppVersions() + { + $sQuery = "DELETE FROM appMaintainers WHERE + superMaintainer = '0' + AND + appId = '?' + AND + userId = '?'"; + $hResult = query_parameters($sQuery, $this->iAppId, $this->iUserId); + + if(!$hResult) + return FALSE; + + return TRUE; + } + + function allowAnonymousSubmissions() + { + return FALSE; + } + + function fetchNotificationUpdate() + { + $bDebugOutputEnabled = false; + + if($bDebugOutputEnabled) + echo "notifyMaintainerOfQueuedData()\n"; + + // if a maintainer has an non-zero warning level + // has it been enough days since we last warned them to warrent + // checking to see if we should warn them again? + if($this->iNotificationLevel != 0) + { + $iLastWarnTime = strtotime($this->sNotificationTime); + $iLastWarnAgeInSeconds = strtotime("now") - $iLastWarnTime; + + if($bDebugOutputEnabled) + echo "iLastWarnAgeInSeconds: ".$iLastWarnAgeInSeconds."\n"; + + // if it hasn't been at least $iNotificationIntervalDays since the last + // warning we can skip even checking the user + if($iLastWarnAgeInSeconds < (iNotificationIntervalDays * 24 * 60 * 60)) + { + if($bDebugOutputEnabled) + echo "iNotificationIntervalDays has not elapsed, skipping checking the user\n"; + return null; + } + } + + if($bDebugOutputEnabled) + echo "notification level is: ".$this->iNotificationLevel."\n"; + + // instantiate the user so we can retrieve particular values + $oUser = new User($this->iUserId); + + if($bDebugOutputEnabled) + { + echo "this->iUserId: ".$this->iUserId."\n"; + print_r($oUser); + } + + // get the time the user signed up + // if queued entries have been queued since before the user signed up + // we can't punish them for this fact + $iMaintainerSignupTime = strtotime($this->aSubmitTime); + + if($bDebugOutputEnabled) + echo "iMaintainerSignupTime: ".$iMaintainerSignupTime."\n"; + + // store the oldest queued entry + $iOldestQueuedEntryTime = strtotime("now"); + + // construct the subject of the notification email that we may send + $sSubject = "Notification of queued data for "; + $sMsg = ""; + $sMsg.= "Hello ".$oUser->sRealname."<".$oUser->sEmail.">".".\n\n"; + $sMsg.= "You are receiving this email to notify you that there is queued data"; + $sMsg.=" for the "; + if($this->bSuperMaintainer) + { + $oApp = new Application($this->iAppId); + $sSubject.= $oApp->sName; + $sMsg.='application, '.$oApp->sName.'('.$oApp->objectMakeUrl().'), that you maintain.'."\n\n"; + } else + { + $sFullname = version::fullName($this->iVersionId); + $oVersion = new Version($this->iVersionId); + $sSubject.= $sFullname; + $sMsg.='version, '.$sFullname.'('.$oVersion->objectMakeUrl().'), that you maintain.'."\n\n"; + } + $sSubject.=" ready for your processing"; + + // retrieve the queued entries + $oQueuedEntries = new queuedEntries($this); + $oQueuedEntries->retrieveQueuedEntries(); + if($oQueuedEntries->isEmpty()) + { + if($bDebugOutputEnabled) + echo "No entries, returning\n"; + + //no entries, we might as well return here + return; + } + + // process each of the queued versions + foreach($oQueuedEntries->aVersionIds as $iVersionId) + { + $oVersion = new Version($iVersionId); + + $sMsg .= 'Version '.$sFullname.' ('.$oVersion->objectMakeUrl().'">'.$sFullname. + ') is queued and ready for processing.'; + + $iSubmitTime = strtotime($oVersion->sSubmitTime); + + // is this submission time older than the oldest queued time? + // if so this is the new oldest time + if($iSubmitTime < $iOldestQueuedEntryTime) + { + $iOldestQueuedEntryTime = $iSubmitTime; + } + } + + if(count($oQueuedEntries->aVersionIds) != 0) + { + // FIXME: should use a function to generate these urls and use it here and + // in sidebar_maintainer.php and sidebar_admin.php + $sMsg = 'Please visit the version queue ('.APPDB_ROOT."objectManager.php?sClass=version_queue&bIsQueue=true&sTitle=". + 'Version%20Queue) to process queued versions for applications you maintain.'."\n"; + } + + ////////////////// + // queued testdata + + // go through the test results looking for the oldest queued data + foreach($oQueuedEntries->aTestDataIds as $iTestDataId) + { + if($bDebugOutputEnabled) + echo "Testresult found\n"; + $oTestData = new TestData($iTestDataId); + + $iSubmitTime = strtotime($oTestData->sSubmitTime); + if($bDebugOutputEnabled) + echo "iSubmitTime is ".$iSubmitTime."\n"; + + // is this submission time older than the oldest queued time? + // if so this is the new oldest time + if($iSubmitTime < $iOldestQueuedEntryTime) + { + if($bDebugOutputEnabled) + echo "setting new oldest time\n"; + + $iOldestQueuedEntryTime = $iSubmitTime; + } + } + + $iTestResultCount = count($oQueuedEntries->aTestDataIds); + if($iTestResultCount != 0) + { + // grammar is slightly different for singular vs. plural + if($iTestResultCount == 1) + $sMsg.="There is $iTestResultCount queued test result. "; + else + $sMsg.="There are $iTestResultCount queued test results. "; + + // FIXME: should use a function to generate these urls and use it here and + // in sidebar_maintainer.php and sidebar_admin.php + $sMsg .= 'Please visit the AppDB Test Data Queue'. + '('.APPDB_ROOT.'objectManager.php?sClass=testData_queue&'. + 'bIsQueue=true&sTitle=Test%20Results%20Queue)'. + ' to process queued test data for versions you maintain.'."\n"; + } + // queued testdata + ////////////////// + + + //////////////////// + // queued screenshots + foreach($oQueuedEntries->aScreenshotIds as $iScreenshotId) + { + $oScreenshot = new Screenshot($iScreenshotId); + + $iSubmitTime = strtotime($oScreenshot->sSubmitTime); + + // is this submission time older than the oldest queued time? + // if so this is the new oldest time + if($iSubmitTime < $iOldestQueuedEntryTime) + { + $iOldestQueuedEntryTime = $iSubmitTime; + } + } + + // if the oldest queue entry time is older than the time the maintainer + // signed up, use the maintainer signup time as the oldest time + if($iOldestQueuedEntryTime < $iMaintainerSignupTime) + $iOldestQueuedEntryTime = $iMaintainerSignupTime; + + $iScreenshotCount = count($oQueuedEntries->aScreenshotIds); + // if we found any queued screenshots add the screenshot queue processing link + // to the email + if($iScreenshotCount != 0) + { + if($iScreenshotCount == 1) + $sMsg.= 'There is one queued screenshot waiting to be processed. '; + else + $sMsg.= "There are $iScreenshotCount screenshots waiting to be processed. "; + + // FIXME: should use a function to generate these urls and use it here and + // in sidebar_maintainer.php and sidebar_admin.php + $sMsg.= 'Please visit the screenshot queue('; + $sMsg.= APPDB_ROOT.'objectManager.php?sClass=screenshot&bIsQueue=true&sTitle=Screenshot%20Queue) '; + $sMsg.= 'to process queued screenshots for versions you maintain.'."\n"; + } + + // queued screenshots + ////////////////////// + + // compute the age in seconds of the oldest entry + $iAgeInSeconds = strtotime("now") - $iOldestQueuedEntryTime; + + // compute the target warning level based on the age and the notification interval + // we divide the age by the number of seconds in a day multiplied by the days per notification interval + $iTargetLevel = (integer)($iAgeInSeconds / (iNotificationIntervalDays * 24 * 60 * 60)); + + if($bDebugOutputEnabled) + { + echo "iOldestQueuedEntryTime is $iOldestQueuedEntryTime\n"; + echo "iAgeInSeconds is $iAgeInSeconds\n"; + echo "iNotificationIntervalDays is ".iNotificationIntervalDays."\n"; + echo "strtotime(now) is ".strtotime("now")."\n"; + echo "iTargetLevel is ".$iTargetLevel."\n"; + } + + $oNotificationUpdate = new notificationUpdate($oUser->sEmail, $sSubject, + $sMsg, $iTargetLevel); + + return $oNotificationUpdate; + } + + // level 0 is from 0 to iNotificationIntervalDays + // level 1 is from (iNotificationIntervalDays + 1) to (iNotificationIntervalDays * 2) + // level 2 is from (iNotificationIntervalDays * 2 + 1) to (iNotificationIntervalDays * 3) + // level 3 is beyond (iNotificationIntervalDays * 3) + function processNotificationUpdate($oNotificationUpdate) + { + $bDebugOutputEnabled = false; + + // if the target level is less than the current level, adjust the current level + // This takes into account the entries in the users queue that may have been processed + if($oNotificationUpdate->iTargetLevel < $this->iNotificationLevel) + { + if($bDebugOutputEnabled) + echo "Using iTargetLevel of $oNotificationUpdate->iTargetLevel\n"; + $this->iNotificationLevel = $oNotificationUpdate->iTargetLevel; + } + + // if the target level is higher than the current level then adjust the + // current level up by 1 + // NOTE: we adjust up by one because we want to ensure that we go through + // notification levels one at a time + if($oNotificationUpdate->iTargetLevel > $this->iNotificationLevel) + { + if($bDebugOutputEnabled) + echo "Increasing notification level of $this->iNotificationLevel by 1\n"; + $this->iNotificationLevel++; + } + + switch($this->iNotificationLevel) + { + case 0: // lowest level, no notification + // nothing to do here + break; + case 1: // send the first notification + // nothing to do here, the first notification is just a reminder + break; + case 2: // send the second notification, notify them that if the queued entries aren't + // processed after another $iNotificationIntervalDays that + // we'll have to remove their maintainership for this application/version + // so a more active person can fill the spot + $oNotificationUpdate->sMsg.= "\nThis your second notification of queued entries."; + $oNotificationUpdate->sMsg.= " If the queued entries are not processsed within"; + $oNotificationUpdate->sMsg.= " the next ".iNotificationIntervalDays. " days we will"; + $oNotificationUpdate->sMsg.= " remove your maintainership for this application/version"; + $oNotificationUpdate->sMsg.= " so a more active person can fill the spot.". + " It's important to process queued items in a timely manner". + " to provide a good user experience."; + break; + case 3: // remove their maintainership and notify the maintainer why we are doing so + $oNotificationUpdate->sMsg.= "\nThis your third notification of queued entries."; + $oNotificationUpdate->sMsg.= " Because your queued entries have not been processed"; + $oNotificationUpdate->sMsg.= " after two notifications we are removing your maintainer"; + $oNotificationUpdate->sMsg.= " role for this application/version. Removing inactive"; + $oNotificationUpdate->sMsg.= " maintainers makes our job easier, since we want to know" + ." not to wait for a maintainer to oversee submissions."; + $oNotificationUpdate->sMsg.= " If you are still interested in being a maintainer please"; + $oNotificationUpdate->sMsg.= " submit a maintainer request."; + $this->delete(); // delete ourselves from the database + break; + } + + // common end of our message + $oNotificationUpdate->sMsg.= "\n\nThanks,\n"; + $oNotificationUpdate->sMsg.= "Appdb Admins\n"; + $oNotificationUpdate->sMsg.= ""; + + // save the notification level and notification time back into the database + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = ?". + " where maintainerId = '?'"; + query_parameters($sQuery, $this->iNotificationLevel, "NOW()", $this->iMaintainerId); + + //TODO: we probably want to copy the mailing list on each of these emails + $oNotificationUpdate->sEmail.=" cmorgan@alum.wpi.edu"; // FIXME: for debug append my email address + + // we don't send any emails if the notification level is zero + if($this->iNotificationLevel == 0) + { + if($bDebugOutputEnabled) + echo "At level 0, no warning issued to ".$oUser->sEmail."\n"; + } else + { + if($bDebugOutputEnabled) + { + echo "Email: ".$oNotificationUpdate->sEmail."\n"; + echo "Subject: ".$oNotificationUpdate->sSubject."\n"; + echo "Msg: ".$oNotificationUpdate->sMsg."\n\n"; + } + + mail_appdb($oNotificationUpdate->sEmail, $oNotificationUpdate->sSubject, + $oNotificationUpdate->sMsg); + } + } + + function notifyMaintainerOfQueuedData() + { + $oNotificationUpdate = $this->fetchNotificationUpdate(); + + // if we have a valid notificationUpdate then process it, otherwise skip it + if($oNotificationUpdate != NULL) + $this->processNotificationUpdate($oNotificationUpdate); + } + + // static method called by the cron maintenance script to notify + // maintainers of data pending for their applications and versions + //TODO: php5 make this static when we have php5 + function notifyMaintainersOfQueuedData() + { + // retrieve all of the maintainers + $hResult = maintainer::objectGetEntries('accepted'); + + // echo "Processing ".query_num_rows($hResult)." maintainers\n"; + + // notify this user, the maintainer, of queued data, if any exists + while($oRow = query_fetch_object($hResult)) + { + $oMaintainer = new maintainer(null, $oRow); + $oMaintainer->notifyMaintainerOfQueuedData(); + } + } +} + +?> diff --git a/include/maintainerView.php b/include/maintainerView.php new file mode 100644 index 0000000..90883be --- /dev/null +++ b/include/maintainerView.php @@ -0,0 +1,151 @@ +iUserId = $_SESSION['current']->iUserId; + else + $this->iUserId = $iUserId; + + if(!$iUserId || $this->iUserId == $_SESSION['current']->iUserId) + $this->bViewingSelf = true; + else + $this->bViewingSelf = false; + } + + function objectGetId() + { + return $this->iUserId; + } + + /* We don't queue this class or process it in any way */ + function objectGetState() + { + return 'accepted'; + } + + function addVersionRatingInfo($oTableRow, $oVersion) + { + $oTableRow->AddTextCell($oVersion->objectMakeLink()); + + /* Rating info */ + $oTableCell = new TableCell($oVersion->sTestedRating); + $oTableCell->SetClass($oVersion->sTestedRating); + $oTableRow->AddCell($oTableCell); + $oTableCell = new TableCell($oVersion->sTestedRelease); + $oTableCell->SetClass($oVersion->sTestedRating); + $oTableRow->AddCell($oTableCell); + + /* Get test reports submitted by the user */ + $aTestData = testData::getTestResultsForUser($this->iUserId, + $oVersion->iVersionId); + + if(sizeof($aTestData)) + { + $oTest = $aTestData[0]; + $sUserRating = $oTest->sTestedRating; + $sUserRelease = $oTest->sTestedRelease; + } else + { + $sUserRating = ''; + $sUserRelease = ''; + } + + $oTableCell = new TableCell($sUserRating); + $oTableCell->SetClass($sUserRating); + $oTableRow->AddCell($oTableCell); + $oTableCell = new TableCell($sUserRelease); + $oTableCell->SetClass($sUserRating); + $oTableRow->AddCell($oTableCell); + + return $oTableRow; + } + + /* Shows a detailed vis of the user's maintained applications, + including last tested release & rating */ + function display() + { + $oUser = new user($this->iUserId); + + $aMaintainedApps = maintainer::getAppsMaintained($oUser); + if(!$aMaintainedApps || !sizeof($aMaintainedApps)) + { + if($this->bViewingSelf) + echo '

    You do not maintain any apps

    '; + else + echo "

    {$oUser->sRealname} does not maintain any apps

    "; + return; + } + + if($this->bViewingSelf) + echo '

    Viewing your maintained apps

    '; + else + echo "

    Viewing {$oUser->sRealname}'s maintained apps

    "; + + $oTable = new Table(); + $oTableRow = new TableRow(); + $oTableRow->setClass('color4'); + $oTable->setCellSpacing(0); + $oTable->setCellPadding(3); + $oTableRow->AddTextCell('Application'); + $oTableRow->AddTextCell('Version'); + $oTableRow->AddTextCell('Current Rating'); + $oTableRow->AddTextCell('Current Version'); + $oTableRow->AddTextCell($this->bViewingSelf ? 'Your Rating' : "User's Rating"); + $oTableRow->AddTextCell($this->bViewingSelf ? 'Your Version' : "User's Version"); + $oTable->AddRow($oTableRow); + + $i = 1; + while(list($iIndex, list($iAppId, $iVersionId, $bSuperMaintainer)) = each($aMaintainedApps)) + { + $oApp = new application($iAppId); + $aVersions = array(); + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell($oApp->objectMakeLink()); + + $oTableRow->SetClass(($i % 2) ? 'color0' : 'color1'); + $i++; + + if($iVersionId) + { + $oVersion = new version($iVersionId); + $oTableRow = maintainerView::addVersionRatingInfo($oTableRow, $oVersion); + $oTable->AddRow($oTableRow); + } else + { + $aVersions = $oApp->getVersions(true); + $oTableRow->AddTextCell('*'); + $oTableRow->AddTextCell(''); + $oTableRow->AddTextCell(''); + $oTableRow->AddTextCell(''); + $oTableRow->AddTextCell(''); + $oTable->AddRow($oTableRow); + } + + foreach($aVersions as $oVersion) + { + $oTableRow = new TableRow($oTableRow); + $oTableRow->AddTextCell(''); + $oTableRow = maintainerView::addVersionRatingInfo($oTableRow, $oVersion); + + $oTableRow->SetClass(($i % 2) ? 'color0' : 'color1'); + $i++; + + $oTable->AddRow($oTableRow); + } + } + echo $oTable->GetString(); + } +} + +?> diff --git a/include/menu.php b/include/menu.php new file mode 100644 index 0000000..dfa6fc2 --- /dev/null +++ b/include/menu.php @@ -0,0 +1,46 @@ +\n"; + + echo ' +
  • '.$name.'

  • +'; + + } + + /* add a table row */ + function add($sName, $shUrl = null, $sAlign = "left") + { + $oTableRow = new TableRow(); + + if($shUrl) + { + echo "
  • {$sName}

  • \n"; + } + else + { + echo "
  • {$sName}

  • \n"; + } + } + + function addmisc($sStuff, $sAlign = "left") + { + echo "
  • $sStuff

  • \n"; + } + + function done($form = null) + { + echo ' +
  • +'; + + if ($form) + echo "\n"; + } +} +?> diff --git a/include/monitor.php b/include/monitor.php new file mode 100644 index 0000000..f8a95cf --- /dev/null +++ b/include/monitor.php @@ -0,0 +1,387 @@ +iMonitorId = $oRow->monitorId; + $this->iAppId = $oRow->appId; + $this->iVersionId = $oRow->versionId; + $this->iUserId = $oRow->userId; + } + } + + function find($iUserId, $iVersionId=0) + { + if($iUserId && $iVersionId) + { + $sQuery = "SELECT * + FROM appMonitors + WHERE userId = '".$iUserId."' + AND versionId = '".$iVersionId."'"; + $hResult = query_appdb($sQuery); + if( $oRow = query_fetch_object($hResult) ) + { + $this->iMonitorId = $oRow->monitorId; + $this->iAppId = $oRow->appId; + $this->iVersionId = $oRow->versionId; + $this->iUserId = $oRow->userId; + } + } + } + + public function objectGetParent($sClass = '') + { + if($this->iVersionId) + return new version($this->iVersionId); + else + return new application($this->iAppId); + } + + public function objectSetParent($iNewId, $sClass = '') + { + if($this->iVersionId) + $this->iVersionId = $iNewId; + else + $this->iAppId = $iNewId; + } + + function objectGetChildren($bIncludeDeleted = false) + { + /* We have none */ + return array(); + } + + /* + * Creates a new Monitor. + * Informs interested people about the creation. + * Returns true on success, false on failure + */ + function create() + { + /* Check for duplicate entries */ + $oMonitor = new monitor(); + $this->iUserId = $_SESSION['current']->iUserId; + $oMonitor->find($this->iUserId, $this->iVersionId); + if($oMonitor->iVersionId) + return FALSE; + + // create the new monitor entry + $hResult = query_parameters("INSERT INTO appMonitors (versionId, appId,". + "submitTime, userId) ". + "VALUES ('?', '?', ?, '?')", + $this->iVersionId, $this->iAppId, + "NOW()", $this->iUserId); + + if($hResult) + { + $this->Monitor(query_appdb_insert_id()); + $sWhatChanged = "New monitor\n\n"; + $this->SendNotificationMail("add", $sWhatChanged); + return true; + } else + { + addmsg("Error while creating a new Monitor.", "red"); + return false; + } + } + + function update() + { + $oMonitor = new monitor($this->iMonitorId); + + if($this->iVersionId && $oMonitor->iVersionId != $this->iVersionId) + { + $hResult = query_parameters("UPDATE appMonitors SET versionId = '?' + WHERE monitorId = '?'", + $this->iVersionId, $this->iMonitorId); + + if(!$hResult) + return FALSE; + } + + if($this->iAppId && $oMonitor->iAppId != $this->iAppId) + { + $hResult = query_parameters("UPDATE appMonitors SET appId = '?' + WHERE monitorId = '?'", + $this->iAppId, $this->iMonitorId); + + if(!$hResult) + return FALSE; + } + + return TRUE; + } + + function unQueue() + { + return true; // We don't queue monitors + } + + function objectGetSubmitterId() + { + return $this->iUserId; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + $sSubject = null; + $sMsg = null; + + if($this->iVersionId) + { + $sWhat = "version"; + $sName = version::fullName($this->iVersionId); + $oVersion = new version($this->iVersionId); + $sUrl = $oVersion->objectMakeUrl(); + } else + { + $sWhat = "application"; + $oApp = new application($this->iAppId); + $sName = $oApp->sName; + $sUrl = $oApp->objectMakeUrl(); + } + + if($bMailSubmitter) + { + switch($sAction) + { + case "delete": + if($bParentActino) + { + $sSubject = "Monitored $sWhat deleted"; + $sMsg = "The $sWhat $sName which you monitored has been ". + "deleted by ".$_SESSION['current']->iUserId."."; + } + break; + } + $aMailTo = null; + } else + { + $oUser = new user($this->iUserId); + $sUser = $oUser->sName; + switch($sAction) + { + case "delete": + if(!$bParentAction) + { + $sSubject = "Monitor for $sName removed: $sUser"; + $sMsg = $sUrl; + } + break; + } + User::get_notify_email_address_list(null, $this->iVersionId); + } + return array($sSubject, $sMsg, $aMailTo); + } + + function purge() + { + return $this->delete(); + } + + /** + * Removes the current Monitor from the database. + * Informs interested people about the deletion. + */ + function delete() + { + $hResult = query_parameters("DELETE FROM appMonitors WHERE monitorId = '?'", $this->iMonitorId); + + if(!$hResult) + return FALSE; + + return TRUE; + } + + function SendNotificationMail($sAction="add",$sMsg=null) + { + /* Set variables depending on whether it is an application or version monitor */ + if(isset($this->iVersionId)) + { + $oVersion = new version($this->iVersionId); + $sAppName = version::fullName($this->iVersionId); + $sUrl = $oVersion->objectMakeUrl(); + $sVersion = " version"; + } else + { + $oApp = new application($this->iAppId); + $sAppName = Application::lookup_name($this->iAppId); + $sUrl = $oApp->objectMakeUrl(); + } + + switch($sAction) + { + case "add": + $sSubject = "Monitor for ".$sAppName; + $sSubject .= " added: ".$_SESSION['current']->sRealname; + $sMsg .= "$sUrl\n"; + addmsg("You will now receive an email whenever changes are made ". + "to this application$sVersion.", "green"); + break; + case "delete": + $sSubject = "Monitor for ".$sAppName; + $sSubject .= " removed: ".$_SESSION['current']->sRealname; + $sMsg .= "$sUrl\n"; + addmsg("You will no longer receive an email whenever changes ". + "are made to this application$sVersion.", "green"); + break; + } + $sEmail = User::get_notify_email_address_list(null, $this->iVersionId); + if($sEmail) + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + function objectGetState() + { + // We don't queue monitors + return 'accepted'; + } + + function canEdit() + { + if($_SESSION['current']->hasPriv("admin") || + ($this->iUserId == $_SESSION['current']->iUserId)) + return TRUE; + + return FALSE; + } + + function mustBeQueued() + { + return FALSE; + } + + /* Stub */ + function display() + { + return ""; + } + + /* Stub */ + function getOutputEditorValues($aClean) + { + $this->iVersionId = $aClean['iVersionId']; + $this->iAppId = $aClean['iAppId']; + } + + /* Stub */ + function objectGetHeader() + { + return null; + } + + function objectGetId() + { + return $this->iMonitorId; + } + + /* Stub */ + function objectGetTableRow() + { + return null; + } + + /* Stub */ + function objectMakeLink() + { + return ""; + } + + /* Stub */ + function objectMakeUrl() + { + return ""; + } + + /* Stub */ + function outputEditor() + { + return ""; + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true) + { + $hResult = query_parameters("SELECT * FROM appMonitors"); + + if(!$hResult) + return FALSE; + + return $hResult; + } + + function objectGetEntriesCount($sState) + { + $hResult = query_parameters("SELECT COUNT(DISTINCT monitorId) as count + FROM appMonitors"); + + if(!$hResult) + return FALSE; + + $oRow = query_fetch_object($hResult); + + if(!$oRow) + return FALSE; + + return $oRow->count; + } + + function allowAnonymousSubmissions() + { + /* That makes no sense */ + return FALSE; + } + + /* Retrieve the user's monitored versions */ + function getVersionsMonitored($oUser) + { + $hResult = query_parameters("SELECT appId, versionId FROM appMonitors WHERE userId = '?'", $oUser->iUserId); + + if(!$hResult || query_num_rows($hResult) == 0) + return NULL; + + $aVersionsMonitored = array(); + + for($i = 0; $oRow = query_fetch_object($hResult); $i++) + $aVersionsMonitored[$i] = array($oRow->appId, $oRow->versionId); + + return $aVersionsMonitored; + } +} +?> diff --git a/include/note.php b/include/note.php new file mode 100644 index 0000000..92891b5 --- /dev/null +++ b/include/note.php @@ -0,0 +1,877 @@ +aNoteLinks = array(); + + if(!$iNoteId && !$oRow) + return; + + if(!$oRow) + { + $sQuery = "SELECT * FROM appNotes WHERE noteId = '?'"; + if($hResult = query_parameters($sQuery, $iNoteId)) + $oRow = query_fetch_object($hResult); + } + + if($oRow) + { + $this->iNoteId = $oRow->noteId; + $this->iVersionId = $oRow->versionId; + $this->iAppId = $oRow->appId; + $this->sTitle = $oRow->noteTitle; + $this->shDescription = $oRow->noteDesc; + $this->sSubmitTime = $oRow->submitTime; + $this->iSubmitterId = $oRow->submitterId; + $this->iLinkedWith = $oRow->linkedWith; + $this->aNoteLinks = $this->objectGetChildren(); + } + } + + + /* + * Creates a new note. + * Informs interested people about the creation. + * Returns true on success, false on failure + */ + function create() + { + $hResult = query_parameters("INSERT INTO appNotes (versionId, ". + "appId, noteTitle, noteDesc, submitterId, ". + "submitTime) ". + "VALUES('?', '?', '?', '?', '?', ?)", + $this->iVersionId, $this->iAppId, + $this->sTitle, $this->shDescription, + $_SESSION['current']->iUserId, + "NOW()"); + + if($hResult) + { + // We need to backup the noteLinks array + $aNoteLinks = $this->aNoteLinks; + $this->note(query_appdb_insert_id()); + + foreach($aNoteLinks as $oLink) + { + $oLink->objectSetParent($this->iNoteId, 'note'); + $this->aNoteLinks[] = $oLink; + } + + $this->saveNoteLinks(true); + $sWhatChanged = "Description is:\n".$this->shDescription.".\n\n"; + $this->SendNotificationMail("add", $sWhatChanged); + return true; + } + else + { + addmsg("Error while creating a new note.", "red"); + return false; + } + } + + + function unQueue() + { + return true; // We don't queue notes + } + + /** + * Update note. + * Returns true on success and false on failure. + */ + function update() + { + $sWhatChanged = ""; + + /* create an instance of ourselves so we can see what has changed */ + $oNote = new Note($this->iNoteId); + + if ($this->sTitle && $this->sTitle!=$oNote->sTitle) + { + if (!query_parameters("UPDATE appNotes SET noteTitle = '?' WHERE noteId = '?'", + $this->sTitle, $this->iNoteId)) + return false; + $sWhatChanged .= "Title was changed from ".$oNote->sTitle." to ".$this->sTitle.".\n\n"; + } + + if ($this->shDescription && $this->shDescription!=$oNote->shDescription) + { + if (!query_parameters("UPDATE appNotes SET noteDesc = '?' WHERE noteId = '?'", + $this->shDescription, $this->iNoteId)) + return false; + $sWhatChanged .= "Description was changed from\n ".$oNote->shDescription."\n to \n".$this->shDescription.".\n\n"; + } + + if($this->iVersionId == APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS && (sizeof($this->aNoteLinks) == 1)) + { + $oLink = $this->aNoteLinks[0]; + $this->iVersionId = $oLink->objectGetParent('version'); + $this->iAppId = 0; + $oLink->delete(); + } + + if (($this->iVersionId || $this->iAppId) && $this->iVersionId!=$oNote->iVersionId) + { + if (!query_parameters("UPDATE appNotes SET versionId = '?' WHERE noteId = '?'", + $this->iVersionId, $this->iNoteId)) + return false; + + if(!$this->iAppId && !$oNote->iAppId) // Changed version only + { + $sVersionBefore = Version::lookup_name($oNote->iVersionId); + $sVersionAfter = Version::lookup_name($this->iVersionId); + $sWhatChanged .= "Version was changed from ".$sVersionBefore." to ".$sVersionAfter.".\n\n"; + } else if(!$this->iAppId) // Moved from app to version + { + $sVersionAfter = Version::fullName($this->iVersionId); + $oApp = new application($oNote->iAppId); + $sOldApp = $oApp->sName; + $sWhatChanged .= "Moved from application $sOldApp to version $sVersionAfter.\n\n"; + } else if($oNote->hasRealVersionId()) // Moved from version to app + { + $oApp = new application($this->iAppId); + $sNewApp = $oApp->sName; + $sVersionBefore = version::fullName($oNote->iVersionId); + $sWhatChanged .= "Moved from version $sVersionBefore to application $sNewApp.\n\n"; + } else // Change display mode for app note + { + $sOldMode = $oNote->getDisplayModeName(); + $sNewMode = $this->getDisplayModeName(); + $sWhatChanged .= "Display mode was changed from '$sOldMode' to '$sNewMode'.\n\n"; + } + } + if (($this->iAppId || $this->iVersionId) && $this->iAppId!=$oNote->iAppId) + { + if(!query_parameters("UPDATE appNotes SET appId = '?' WHERE noteId = '?'", + $this->iAppId, $this->iNoteId)) + return false; + } + + $this->saveNoteLinks(); + + if($sWhatChanged) + $this->SendNotificationMail("edit",$sWhatChanged); + return true; + } + + function purge() + { + return $this->delete(); + } + + /** + * Removes the current note from the database. + * Informs interested people about the deletion. + * + * Returns: true if successful, false if not + */ + function delete() + { + $hResult = query_parameters("DELETE FROM appNotes WHERE noteId = '?'", $this->iNoteId); + + if(!$hResult) + return FALSE; + + return TRUE; + } + + function objectShowPreview() + { + return TRUE; + } + + function SendNotificationMail($sAction="add",$sMsg=null) + { + if(!$this->iAppId) + { + $oVersion = new version($this->iVersionId); + $sAppName = version::fullName($this->iVersionId); + $sMsg .= $oVersion->objectMakeUrl()."\n"; + } else + { + $oApp = new application($this->iAppId); + $sAppName = $oApp->sName; + $sMsg .= $oApp->objectMakeUrl()."\n"; + } + + switch($sAction) + { + case "add": + $sSubject = "Note $this->sTitle for $sAppName added by ". + $_SESSION['current']->sRealname; + addmsg("The note was successfully added into the database.", "green"); + break; + case "edit": + $sSubject = "Note $this->sTitle for $sAppName has been modified by ". + $_SESSION['current']->sRealname; + addmsg("Note modified.", "green"); + break; + case "delete": + $oSubmitter = new User($this->iSubmitterId); + $sSubject = "Note $this->sTitle for $sAppName has been deleted by ". + $_SESSION['current']->sRealname; + $sMsg .= "This note was made on ".print_date(mysqldatetime_to_unixtimestamp($this->sSubmitTime)). + " by ".$oSubmitter->sRealname."\n"; + $sMsg .= "\n"; + $sMsg .= "Subject: ".$this->sTitle."\n"; + $sMsg .= "\n"; + $sMsg .= "Note contents:\n"; + $sMsg .= $this->shDescription."\n"; + $sMsg .= "\n"; + $sMsg .= "Because:\n"; + if(isset($aClean['sReplyText']) && $aClean['sReplyText']) + $sMsg .= $aClean['sReplyText']."\n"; + else + $sMsg .= "No reason given.\n"; + + addmsg("Note deleted.", "green"); + break; + } + $sEmail = User::get_notify_email_address_list(null, $this->iVersionId); + if($sEmail) + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + /* Show note */ + /* $bDisplayOnly means we should not display any editing controls, even if */ + /* the user has the ability to edit this note */ + function display($aVars = null) + { + switch($this->sTitle) + { + case 'WARNING': + $sClass = 'warning'; + $sTitle = 'Warning'; + break; + + case 'HOWTO': + $sClass = 'howto'; + $sTitle = 'HOWTO'; + break; + + default: + if(!empty($this->sTitle)) + $sTitle = $this->sTitle; + else + $sTitle = 'Note'; + + $sClass = 'defaultnote'; + } + + if(!$aVars || !getInput('shReturnTo', $aVars)) + { + $oVersion = new version($this->iVersionId); + $shReturnTo = $oVersion->objectMakeUrl(); + } else + { + $shReturnTo = $aVars['shReturnTo']; + } + + $shOutput = html_frame_start("","98%",'',0); + + $shOutput .= "\n"; + $shOutput .= "\n"; + $shOutput .= "\n"; + + if((!$aVars || $aVars['bEditing'] != "true") && $this->canEdit()) + { + $shOutput .= "'; + } + + $shOutput .= "
     
    ".$sTitle."
    \n"; + $shOutput .= $this->shDescription; + $shOutput .= "
    "; + $shOutput .= "
    iNoteId."&sReturnTo=".urlencode($shReturnTo)."\">"; + $shOutput .= ''; + $shOutput .= '
    \n"; + $shOutput .= html_frame_end(); + + echo $shOutput; + } + + function displayNotesForEntry($iVersionId, $iAppId = null) + { + if($iVersionId) + { + $oVersion = new version($iVersionId); + $oApp = $oVersion->objectGetParent(); + $hResult = query_parameters("SELECT noteId FROM appNotes WHERE versionId = '?' OR (appId = '?' AND (versionId = '?' OR versionId = '?')) ORDER BY versionId,noteId", $iVersionId, $oApp->objectGetId(), APPNOTE_SHOW_FOR_ALL, APPNOTE_SHOW_FOR_VERSIONS); + } else if($iAppId) + { + $hResult = query_parameters("SELECT noteId FROM appNotes WHERE appId = '?' AND (versionId = '?' OR versionId = '?')", $iAppId, APPNOTE_SHOW_FOR_ALL, APPNOTE_SHOW_FOR_APP); + } + + if(!$hResult) + return; + + if($iVersionId) + $oVersion = new version($iVersionId); + else + $oApp = new application($iAppId); + + while($oRow = mysql_fetch_object($hResult)) + { + $oNote = new note($oRow->noteId); + + $shReturnTo = $iVersionId ? $oVersion->objectMakeUrl() : $oApp->objectMakeUrl(); + + $aVars = array('shReturnTo' => $shReturnTo, 'bEditing' => 'false'); + + $oLink = $oNote->getLink(); + + if($oLink) + $oLink->display($aVars); + else + $oNote->display($aVars); + } + } + + function objectGetCustomVars($sAction) + { + switch($sAction) + { + case "preview": + return array("bEditing"); + + case "add": + return array('iVersionId','iAppId','sNoteTitle'); + + default: + return null; + } + } + + public static function isRealVersionId($iVersionId) + { + return $iVersionId > 0; + } + + public function hasRealVersionId() + { + return note::isRealVersionId($this->iVersionId); + } + + public static function getDisplayModeIds() + { + return array(APPNOTE_SHOW_FOR_ALL, APPNOTE_SHOW_FOR_VERSIONS, APPNOTE_SHOW_FOR_APP, APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS); + } + + public static function getDisplayModeNames() + { + return array('Show on both application and version pages', 'Show on all version pages only', 'Show on application page only', 'Show on the following version pages only:'); + } + + public function getDisplayModeName($iModeId = null) + { + if(!$iModeId) + $iModeId = $this->iVersionId; + + $aNames = note::getDisplayModeNames(); + $iIndex = 0; + + foreach(note::getDisplayModeIds() as $iId) + { + if($iId == $iModeId) + return $aNames[$iIndex]; + $iIndex++; + } + + return ''; + } + + public function findLink($iVersionId, $bQueryDB = true) + { + if($bQueryDB) + { + // If we don't have a noteId we can't be linked to anything + if(!$this->iNoteId) + return null; + + $hResult = query_parameters("SELECT * FROM appNotes WHERE linkedWith = '?' AND versionId = '?'", $this->iNoteId, $iVersionId); + + if(!$hResult || !($oRow = mysql_fetch_object($hResult))) + return null; + + return new noteLink(null, $oRow); + } + + foreach($this->aNoteLinks as $oLink) + { + if($oLink->objectGetParent('version') == $iVersionId) + return $oLink; + } + + return null; + } + + public function isLinkedWith($iVersionId, $bQueryDB = true) + { + $oLink = $this->findLink($iVersionId, $bQueryDB); + + return $oLink != null; + } + + public function getNoteLinksFromInput($aValues) + { + $iAppId = $this->iAppId; + if(!$iAppId) + $iAppId = getInput('iAppId', $aValues); + $oApp = new application($iAppId); + $iCount = sizeof($oApp->getVersions()); + $aLinkedVersions = html_read_input_series('iVersionId', $aValues, $iCount); + $aLinks = array(); + + foreach($aLinkedVersions as $sLinkedVersionId) + { + + if(!$sLinkedVersionId) + continue; + + $iLinkedVersionId = (int)$sLinkedVersionId; + // See if we already have a DB entry for this link + $oExistingLink = $this->findLink($iLinkedVersionId); + if($oExistingLink) + { + $aLinks[] = $oExistingLink; + continue; + } + $oLink = new noteLink(); + + $oLink->objectSetParent($this->iNoteId, 'note'); + $oLink->objectSetParent($iLinkedVersionId, 'version'); + $aLinks[] = $oLink; + } + + return $aLinks; + } + + public function saveNoteLinks($bNewNote = false) + { + foreach($this->aNoteLinks as $oLink) + { + if($bNewNote || !$this->isLinkedWith($oLink->objectGetParent('version'))) + $oLink->create(); + } + + // Check if we should delete any links + $aDBLinks = $this->objectGetChildren(); + + if(sizeof($this->aNoteLinks) != sizeof($aDBLinks)) + { + foreach($aDBLinks as $oDBLink) + { + $bFound = false; + foreach($this->aNoteLinks as $oLink) + { + if($oDBLink->objectGetParent('version') == $oLink->objectGetParent('version')) + $bFound = true; + } + if(!$bFound) + $oDBLink->delete(); + } + } + } + + public function getLink() + { + if($this->iLinkedWith) + return new noteLink($this->iNoteId); + + return null; + } + + function outputEditor($aValues = null) + { + if($aValues) + { + if(!$this->iVersionId) + $this->iVersionId = getInput('iVersionId', $aValues); + + if(!$this->iAppId) + $this->iAppId = getInput('iAppId', $aValues); + + if(!$this->sTitle) + $this->sTitle = getInput('sNoteTitle', $aValues); + } + + if($this->iAppId && !$this->iVersionId) + $this->iVersionId = APPNOTE_SHOW_FOR_ALL; + + if(!$this->iAppId) + { + $oVersion = new version($this->iVersionId); + $this->iAppId = $oVersion->iAppId; + } + + HtmlAreaLoaderScript(array("editor")); + + echo html_frame_start("Edit Application Note", "90%","",0); + echo html_table_begin("width='100%' border=0 align=left cellpadding=6 cellspacing=0 class='box-body'"); + + echo ''; + echo ''; + + echo ''; + + echo 'Title'."\n"; + echo ' ',"\n"; + echo 'Description', "\n"; + echo '

    ', "\n"; + echo '',"\n"; + echo '

    '; + echo ''."\n"; + + if($this->iAppId || $oApp->canEdit()) + { + if($this->hasRealVersionId()) + { + $oLink = new noteLink(); + $oLink->objectSetParent($this->iNoteId, 'note'); + $oLink->objectSetParent($this->iVersionId, 'version'); + $this->aNoteLinks[] = $oLink; + $oVersion = new version($this->iVersionId); + $this->iAppId = $oVersion->iAppId; + $this->iVersionId = APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS; + } + + $oApp = new application($this->iAppId); + $aIds = $this->getDisplayModeIds(); + $aOptions = $this->getDisplayModeNames(); + + echo 'Display mode'."\n"; + echo ''.html_radiobuttons($aIds, $aOptions, 'iVersionId', $this->iVersionId); + + /* Allow the note to be shown for certain versions only */ + $aIds = array(); + $aOptions = array(); + $aSelected = array(); + + foreach($oApp->getVersions(true) as $oAppVersion) // Only accepted versions + { + + $aIds[] = $oAppVersion->objectGetId(); + $aOptions[] = $oAppVersion->objectMakeLink(); + + $aSelected[] = $this->isLinkedWith($oAppVersion->objectGetId(), false); + } + echo html_checkboxes('iVersionId', $aIds, $aOptions, $aSelected); + + echo ''; + } else if(!$this->iAppId) + { + echo ''; + } + + echo '',"\n"; + + echo html_table_end(); + echo html_frame_end(); + } + + public function checkOutputEditorInput($aClean) + { + $shErrors = ''; + $iVersionId = getInput('iVersionId', $aClean); + + if($iVersionId == APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS) + { + $aNoteLinks = $this->getNoteLinksFromInput($aClean); + if(!sizeof($aNoteLinks)) + $shErrors .= '
  • You need to show the note for at least one version, or choose another display mode
  • '; + } + return $shErrors; + } + + /* retrieves values from $aValue that were output by outputEditor() */ + /* $aValues can be $_REQUEST or any array with the values from outputEditor() */ + function GetOutputEditorValues($aValues) + { + $this->iVersionId = getInput('iVersionId', $aValues); + + if(!$this->isRealVersionId($this->iVersionId)) + $this->iAppId = getInput('iAppId', $aValues); + else + $this->iAppId = 0; + + if($this->iVersionId == APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS) + { + $this->aNoteLinks = $this->getNoteLinksFromInput($aValues); + + // There's no need to use links if the note is only shown for one version + if(sizeof($this->aNoteLinks) == 1) + { + $oLink = $this->aNoteLinks[0]; + $this->iVersionId = $oLink->objectGetParent('version'); + $this->iAppId = 0; + $this->aNoteLinks = array(); + } + } + + $this->sTitle = $aValues['sNoteTitle']; + $this->shDescription = $aValues['shNoteDesc']; + } + + function allowAnonymousSubmissions() + { + return false; + } + + // NOTE: notes cannot be queued at this point + function mustBeQueued() + { + return false; + } + + function objectGetId() + { + return $this->iNoteId; + } + + // TODO: we ignore $bQueued and $bRejected as notes + // do not support queuing at this point + // TODO: we have no permissions scope on retrieving entries + // as notes are typically only added to unqueued versions + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true) + { + $sQuery = "select * from appNotes"; + $hResult = query_parameters($sQuery); + return $hResult; + } + + function objectGetEntriesCount($sState) + { + $sQuery = "SELECT COUNT(DISTINCT noteId) as count FROM appNotes"; + $hResult = query_parameters($sQuery); + + if(!$hResult) + return false; + + if(($oRow = mysql_fetch_object($hResult))) + return $oRow->count; + + return false; + } + + //TODO: not sure how to best let users view a table of notes + // since the note contents could be very long we would only + // want to show a small amount of the text. Implement this + // routine when we need it + function objectGetHeader() + { + return null; + } + + //TODO: implement this when we implement objectGetHeader() + function objectGetTableRow() + { + return null; + } + + function objectMakeUrl() + { + $oManager = new objectManager("note", "View Note"); + return $oManager->makeUrl("view", $this->objectGetId()); + } + + function objectGetSubmitterId() + { + return $this->iSubmitterId; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + /* We don't do this at the moment */ + return array(null, null, null); + } + + public function objectGetParent($sClass = '') + { + if($this->hasRealVersionId()) + return new version($this->iVersionId); + else + return new application($this->iAppId); + } + + public function objectSetParent($iNewId, $sClass = '') + { + if($this->hasRealVersionId()) + $this->iVersionId = $iNewId; + else + $this->iAppId = $iNewId; + } + + function objectGetChildren($bIncludeDeleted = false) + { + $aRet = array(); + + if(!$this->iAppId) + return $aRet; + + $hResult = query_parameters("SELECT * FROM appNotes WHERE linkedWith = '?'", $this->iNoteId); + + if(!$hResult) + return $aRet; + + while($oRow = mysql_fetch_object($hResult)) + $aRet[] = new noteLink(null, $oRow); + + return $aRet; + } + + //TODO: not sure if we want to use sTitle here or what + function objectMakeLink() + { + $sLink = "objectMakeUrl()."\">". + $this->sTitle.""; + return $sLink; + } + + function objectGetState() + { + return 'accepted'; // We don't queue notes + } + + // users can edit the note if they: + // - have "admin" privileges + // - maintain the version, or supermaintain the application that + // this version is under + function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + return true; + else if($this->iVersionId && !$this->iAppId) + return maintainer::isUserMaintainer($_SESSION['current'], $this->iVersionId); + else if($this->iAppId) + return maintainer::isUserSuperMaintainer($_SESSION['current'], $this->iAppId); + + return false; + } +} + +class noteLink +{ + private $iLinkId; + private $iNoteId; + private $iVersionId; + + function noteLink($iLinkId = null, $oRow = null) + { + $this->iLinkId = $iLinkId; + + if(!$oRow && $this->iLinkId) + { + $hResult = query_parameters("SELECT * FROM appNotes WHERE noteId = '?'", $this->iLinkId); + + if(!$hResult) + return; + + $oRow = mysql_fetch_object($hResult); + } + + if($oRow) + { + $this->iLinkId = $oRow->noteId; + $this->iNoteId = $oRow->linkedWith; + $this->iVersionId = $oRow->versionId; + } + } + + public function create() + { + $hResult = query_parameters("INSERT INTO appNotes (linkedWith,versionId) VALUES('?','?')", $this->iNoteId, $this->iVersionId); + + if(!$hResult) + return false; + + return true; + } + + public function isDuplicate() + { + $oNote = new note($this->iNoteId); + return $oNote->isLinkedWith($this->iVersionId); + } + + public function update() + { + // Query the DB so we have something to compare against + $oLink = new noteLink($this->iLinkId); + + if($this->objectGetParent('version') != $oLink->objectGetParent('version') && !$this->isDuplicate()) + { + $hResult = query_parameters("UPDATE appNotes SET versionId = '?' WHERE noteId = '?'", $this->iVersionId, $this->iNoteId); + if(!$hResult) + return false; + } + return true; + } + + public function delete() + { + $hResult = query_parameters("DELETE FROM appNotes WHERE noteId = '?'", $this->iLinkId); + + if(!$hResult) + return false; + + return true; + } + + public function objectSetParent($iNewId, $sClass = '') + { + if(!$sClass || $sClass == 'note') + $this->iNoteId = $iNewId; + else if($sClass == 'version') + $this->iVersionId = $iNewId; + } + + public function objectGetParent($sClass = '') + { + if(!$sClass || $sClass == 'note') + return $this->iNoteId; + if($sClass == 'version') + return $this->iVersionId; + } + + function display($aValues = null) + { + $oNote = new note($this->iNoteId); + $oNote->display($aValues); + } +} + +?> diff --git a/include/objectManager.php b/include/objectManager.php new file mode 100644 index 0000000..e345020 --- /dev/null +++ b/include/objectManager.php @@ -0,0 +1,1934 @@ +oObject = null; + } + + /* Get an instance of the object of the class we are working with */ + private function getObject() + { + if(!$this->oObject) + $this->oObject = new $this->sClass($this->iId); + + return $this->oObject; + } + + private function setId($iId) + { + $this->iId = $iId; + + if($this->oObject) + $this->oObject = new $this->sClass($this->iId); + } + + public function getClass() + { + return $this->sClass; + } + + public function getState() + { + return $this->sState; + } + + private function initFilterInfo() + { + $this->oFilters = $this->getOptionalSetting('objectGetFilterInfo', FALSE); + } + + public function getFilterInfoFromInput($aClean) + { + $this->initFilterInfo(); + + if($this->oFilters) + $this->oFilters->readInput($aClean); + } + + public function setState($sState) + { + /* Ensure that the given state is valid */ + switch($sState) + { + case 'accepted': + case 'queued': + case 'rejected': + case 'deleted': + $this->sState = $sState; + return true; + + default: + return false; + } + } + + public function getIsQueue() + { + return $this->sState != 'accepted'; + } + + public function setReturnTo($sReturnTo) + { + $this->sReturnTo = $sReturnTo; + } + + public function setReturnToTitle($sTitle) + { + $this->sReturnToTitle = $sTitle; + } + + public function setSortInfo($aClean = null) + { + $this->oSortInfo = new TableSortInfo($this->makeUrl().'&'); + + /* No use to continue if there are no sortable fields */ + if(!$this->getOptionalSetting("objectGetSortableFields", FALSE)) + return; + + if($aClean) + $this->oSortInfo->ParseArray($aClean, $this->getObject()->objectGetSortableFields()); + } + + public function getId() + { + return $this->iId; + } + + public function getMultiPageDataFromInput($aClean) + { + $this->oMultiPage->getDataFromInput($aClean); + } + + function ObjectManager($sClass, $sTitle = "list", $iId = false) + { + $this->sClass = $sClass; + $this->sTitle = $sTitle; + $this->iId = $iId; + $this->oMultiPage = new MultiPage(FALSE); + $this->oTableRow = new OMTableRow(null); + $this->sState = 'accepted'; + $this->oFilters = null; // We only fill this when needed, as it can be quite slow + + // initialize the common responses array + $this->aCommonResponses = array(); + $this->aCommonResponses[] = "Thank you for your submission."; + $this->aCommonResponses[] = "Please consider filing a bug for the ". + "problem you have with this app, if there are not bugs filed already". + " at http://bugs.winehq.org. If you want some advice or guidance on". + " this, please visit http://forum.winehq.org"; + $this->aCommonResponses[] = "Please do not paste debug output in the AppDB,". + " it belongs only as an attachment on bugzilla."; + $this->aCommonResponses[] = "We appreciate your submission but it". + " needs to be more detailed before it will be most useful to other users of". + " the Application Database.". + " Please try to improve the entry and resubmit."; + $this->aCommonResponses[] = "We appreciate your submission but it". + " requires improvement to its grammar and/or spelling". + " before it will be most useful to other users of". + " the Application Database.". + " Please try to improve the entry and resubmit."; + $this->aCommonResponses[] = "Please do not copy large amount of text from". + " the program's website"; + } + + /* Check whether the associated class has the given method */ + public function checkMethod($sMethodName, $bEnableOutput) + { + if(!method_exists($this->sClass, $sMethodName)) + { + if($bEnableOutput) echo "class '".$this->sClass."' lacks method '".$sMethodName."'\n"; + return false; + } + + return true; + } + + /* Check whether the specified methods are valid */ + public function checkMethods($aMethods, $bExit = true) + { + foreach($aMethods as $sMethod) + { + if(!$this->checkMethod($sMethod, false)) + { + echo "Selected class does not support this operation ". + "(missing '$sMethod()')\n"; + + if($bExit) + exit; + else + return FALSE; + } + } + + return TRUE; + } + + public function IsNullIdAllowed($sAction) + { + $oObject = new $this->sClass(); + $bAllowed = method_exists($oObject, 'objectAllowNullId'); + + if($bAllowed) + $bAllowed = $oObject->objectAllowNullId($sAction); + + return $bAllowed; + } + + public static function error_exit($shMessage) + { + echo '

    '.$shMessage.'

    '; + + /* Output header cells */ + $this->outputHeader("color4"); + + /* Preserve the page title */ + $this->setReturnToTitle($this->sTitle); + + /* output each entry */ + for($iCount = 0; $oRow = query_fetch_object($hResult); $iCount++) + { + $oObject = new $this->sClass(null, $oRow); + + $this->oTableRow = $oObject->objectGetTableRow(); + + $sColor = ($iCount % 2) ? "color0" : "color1"; + + // if there is no class set for a given row use the + // default one in $sColor + if(!$this->oTableRow->GetTableRow()->GetClass()) + { + $this->oTableRow->GetTableRow()->SetClass($sColor); + } + + // if this row is clickable, make it highlight appropirately + $oTableRowClick = $this->oTableRow->GetTableRow()->GetTableRowClick(); + if($oTableRowClick) + { + $oTableRowHighlight = GetStandardRowHighlight($iCount); + $oTableRowClick->SetHighlight($oTableRowHighlight); + } + + $sEditLinkLabel = $this->getIsQueue() ? 'process' : 'edit'; + + /* We add some action links */ + if($oObject->canEdit()) + { + $shDeleteLink = ""; + if($this->oTableRow->GetHasDeleteLink()) + { + $shDeleteLink = ' [ objectGetId()). + '">delete ]'; + } + + $oTableCell = new TableCell('[ objectGetId()).'">'.$sEditLinkLabel.' ]'.$shDeleteLink); + $this->oTableRow->AddCell($oTableCell); + } + + echo $this->oTableRow->GetString(); + } + + echo ""; + } + + /* displays the list of entries */ + public function display_table($aClean) + { + $this->checkMethods(array("ObjectGetEntries", "ObjectGetHeader", + "objectGetTableRow", "objectGetId", "canEdit")); + + /* We cannot process a queue if we are not logged in */ + if(!$_SESSION['current']->isLoggedIn() && $this->getIsQueue()) + { + $sQueueText = $this->sState == 'rejected' ? "rejected" : "queued"; + echo '
    You need to '; + echo "log in in order to process $sQueueText entries
    \n"; + login_form(false); + return; + } + + // if displaying a queue display the help for the given queue + if($this->getIsQueue()) + $this->GetOptionalSetting("ObjectDisplayQueueProcessingHelp", ""); + + $oObject = new $this->sClass(); + + // Display top of the page selectors for items per page and + // current page, if applicable. + $this->handleMultiPageControls($aClean, TRUE); + + /* Set the sort info */ + $this->setSortInfo($aClean); + + if(!$this->oSortInfo->sCurrentSort) + $this->oSortInfo->sCurrentSort = $this->getOptionalSetting('objectGetDefaultSort', ''); + + $this->handleFilterControls($aClean); + + /* query the class for its entries */ + /* We pass in queue states to tell the object */ + /* if we are requesting a list of its queued objects or */ + /* all of its objects */ + $hResult = $oObject->objectGetEntries($this->sState, + $this->oMultiPage->iItemsPerPage, + $this->oMultiPage->iLowerLimit, + $this->oSortInfo->sCurrentSort, + $this->oSortInfo->bAscending, + $this->oFilters); + + /* did we get any entries? */ + if(!$hResult || query_num_rows($hResult) == 0) + { + if($this->oFilters && $this->oFilters->getFilterCount()) + { + echo '
    No matches found
    '; + } else + { + switch($this->getQueueString($this->getIsQueue(), $this->sState == 'rejected')) + { + case "true": + echo "
    The queue for '$this->sClass' is empty
    "; + break; + case "false": + echo "
    No entries of '$this->sClass' are present
    "; + break; + case "rejected": + echo "
    No rejected entries of '$this->sClass' are ". + "present
    "; + break; + } + } + + if($this->GetOptionalSetting("objectShowAddEntry", FALSE) && $oObject->canEdit()) + { + echo "
    makeUrl("add", false, + "Add $this->sClass entry"). + "\">Add an entry?
    "; + } + return; + } + + /* Show a link to the 'purge rejected entries' page if we are an admin */ + if($_SESSION['current']->hasPriv('admin') && $this->getOptionalSetting('objectAllowPurgingRejected', FALSE)) + { + echo '
    '; + $oM = new objectManager($this->sClass, 'Purge Rejected Entries'); + echo 'Purge rejected entries

    '; + echo '
    '; + } + + $sQueued = $this->getQueueString($this->getIsQueue(), $this->sState == 'rejected'); + + $this->showNumberOfResults($oObject); + + /* Should we let the class draw its own custom table? */ + if(method_exists($this->sClass, 'objectWantCustomDraw') && + $oObject->objectWantCustomDraw('table', $sQueued)) + $oObject->objectDrawCustomTable($hResult, $sQueued); + else + $this->drawTable($hResult); + + $oObject = new $this->sClass(); + if($oObject->canEdit() && $this->GetOptionalSetting("objectShowAddEntry", FALSE)) + { + echo "

    makeUrl("add", false, + "Add $this->sClass")."\">Add entry\n"; + } + + // Display bottom of page selectors current page, if applicable + // NOTE: second parameter is false because we don't want the + // items per page selector appearing for the second set of page controls + $this->handleMultiPageControls($aClean, FALSE); + } + + private function getOptionalSetting($sFunction, $bDefault) + { + if(!method_exists($this->sClass, $sFunction)) + return $bDefault; + + return $this->getObject()->$sFunction(); + } + + /* display the entry for editing */ + public function display_entry_for_editing($aClean, $sErrors) + { + $this->checkMethods(array("outputEditor", "getOutputEditorValues", + "update", "create")); + + // open up the div for the default container + echo "
    \n"; + + // link back to the previous page + echo html_back_link(1, null); + + $oObject = new $this->sClass($this->iId); + + /* The entry does not exist */ + if(!$oObject->objectGetId()) + { + echo "There is no entry with that id in the database.\n"; + echo "
    "; + return; + } + + /* Only show the edit screen if the user has sufficient rights */ + if(!$oObject->canEdit() && !getInput('sSubmit', $aClean)) + $this->error_exit('You do not have sufficient privileges to edit this entry'); + else if(!$oObject->canEdit()) + $this->show_form_help_session_timeout(); + + /* Display errors, if any, and fetch form data */ + if($this->displayErrors($sErrors)) + { + $oObject->getOutputEditorValues($aClean); + + if($sErrors === PREVIEW_ENTRY) + $this->show_preview($oObject, $aClean); + } + + echo '
    iId). + '" method="post" enctype="multipart/form-data">',"\n"; + + echo $this->makeUrlFormData(); + + $aCustomVars = $this->get_custom_vars($aClean, "edit"); + + if($aCustomVars) + $oObject->outputEditor($aClean); + else + $oObject->outputEditor(); + + $this->oObject = $oObject; + + /* If it isn't implemented, that means there is no default text */ + $sDefaultReply = $this->getOptionalSetting("getDefaultReply", ""); + + if($this->getIsQueue()) + $sReplyFieldHeader = 'Reply Text'; + else + $sReplyFieldHeader = 'Comment'; + + echo html_frame_start($sReplyFieldHeader, "90%", "", 0); + echo "\n"; + echo '',"\n"; + echo '',"\n"; + + if($this->getIsQueue()) + { + ///////////////////////////////////////////////// + // output radio buttons for some common responses + echo '',"\n"; + + // NOTE: We use the label tag so the user can click anywhere in + // the text of the radio button to select the radio button. + // Otherwise the user has to click on the very small circle portion + // of the button to select it + foreach($this->aCommonResponses as $iIndex => $sReply) + { + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + } + // end output radio buttons for common responses + ///////////////////////////////////////////////// + } + + + /* buttons for operations we can perform on this entry */ + echo '',"\n"; + echo '
    E-mail Text
    '. + 'Common replies
    Email '. + APPDB_OWNER_EMAIL.' if you want to suggest a new common reply.
    ' ,"\n"; + echo '',"\n"; + if(!$this->getOptionalSetting("objectHideDelete", FALSE)) + { + echo '',"\n"; + } + + if($this->sState == 'queued' && !$this->getOptionalSetting("objectHideReject", FALSE)) + { + echo '',"\n"; + } + + echo $this->handle_preview_button(); + + echo '',"\n"; + echo '
    '; + echo html_frame_end(); + + echo '
    '; + + echo "
    \n"; + + } + + /* Ask whether the user really wants to delete the entry and display a delete reason box */ + public function delete_prompt() + { + $this->checkMethods(array("delete", "canEdit")); + + $oObject = new $this->sClass($this->iId); + + /* Check permissions */ + if(!$oObject->canEdit()) + { + echo "You do not have permission to delete this entry.\n"; + return; + } + + /* Check whether the object exists */ + if(!$oObject->objectGetId()) + { + echo "There is no entry with that id in the database.\n"; + return; + } + + /* Why the user should write an explanation for the deletion */ + if($oObject->objectGetSubmitterId() != $_SESSION['current']->iUserId) + { + $shWhyComment = "Please enter a reason why so that you don't hurt the submitter's". + " feelings."; + + $oUser = new user($oObject->objectGetSubmitterId()); + $sSubmitter = " (submitted by ".$oUser->objectMakeLink().")"; + } else + { + $shWhyComment = "Although you submitted it, it might be useful for other users to know why ". + "you are deleting it."; + + $sSubmitter = ""; + } + + $oTable = new Table(); + $oTableRow = new TableRow(); + $oTable->setAlign("center"); + $oTable->addRow($oTableRow); + $oTableRow->addTextCell( + '
    '. + '
    '. + '
    '. + "Confirm deletion". + "
    ". + '
    '. + "Are you sure you wish to delete this entry".$sSubmitter."?
    ". + $shWhyComment. + "
    ". + "
    ". + + '
    '. + $this->makeUrlFormData(). + ''. + '

    '. + ''. + "
    ". + "
    "); + echo $oTable->getString(); + } + + public function delete_child($sReplyText, $bMailSubmitter, $bMailCommon) + { + $this->checkMethods(array("delete", "canEdit")); + + $oObject = new $this->sClass($this->iId); + $oSubmitterMail = null; + $oCommonMail = null; + + if(!$oObject->canEdit()) + return FALSE; + + if($bMailSubmitter) + $oSubmitterMail = $this->get_mail(TRUE, "delete", TRUE); + + if($bMailCommon) + $oCommonMail = $this->get_mail(FALSE, "delete", TRUE); + + if($oObject->delete()) + { + if($oCommonMail || $oSubmitterMail) + { + $sReplyText = "The parent entry was deleted. The reason given for ". + "that deletion was:\n$sReplyText"; + + if($oCommonMail) + $oCommonMail->send("delete", $sReplyText); + + if($oSubmitterMail) + $oSubmitterMail->send("delete", $sReplyText); + } + + return TRUE; + } else + { + return FALSE; + } + } + + /* Delete the object associated with the given id + bStandAlone determines whether this is a stand alone delete operation, where we want to output messages and return */ + public function delete_entry($sReplyText, $bStandAlone = true) + { + $this->checkMethods(array("delete", "canEdit")); + + $oObject = $this->getObject(); + $oOriginalObject = new $this->sClass($this->iId); /* Prevent possible security hole if users change key + variables, making the permission checks run on + the wrong criteria */ + + if(!$oOriginalObject->objectGetId()) + { + addmsg("No id defined", "red"); + return FALSE; + } + + if(!$oOriginalObject->canEdit()) + { + addmsg("You don't have permission to delete this entry", "red"); + return FALSE; + } + + $oSubmitterMail = $this->get_mail(TRUE, "delete"); + $oCommonMail = $this->get_mail(FALSE, "delete"); + + $iFailed = 0; + $iDeleted = 0; + + /* Delete children first, if there are any */ + if(method_exists($oObject, "objectGetChildren")) + { + $aChildren = $oObject->objectGetChildren(); + + if(!is_array($aChildren)) + { + addmsg("Failed to get child entries, aborting", "red"); + util_redirect_and_exit($this->makeUrl("view", false)); + } + + /* Keep track of whether we should send mails. This is used by the + 'mail once' option */ + $aSendMailSubmitter = array(); + $aSendMailCommon = array(); + + foreach($aChildren as $oChild) + { + if(!is_object($oChild)) + { + addmsg("Failed to get child entries, aborting", "red"); + util_redirect_and_exit($this->makeUrl("view", false)); + } + + $oM = $this->om_from_object($oChild); + + if(!isset($aSendMailSubmitter[$oM->sClass][$oChild->objectGetSubmitterId()])) + $aSendMailSubmitter[$oM->sClass][$oChild->objectGetSubmitterId()] = TRUE; + + if(!isset($aSendMailCommon[$oM->sClass])) + $aSendMailCommon[$oM->sClass] = TRUE; + + if($oM->delete_child($sReplyText, $aSendMailSubmitter[$oM->sClass][$oChild->objectGetSubmitterId()], $aSendMailCommon[$oM->sClass])) + { + $iDeleted++; + + if($oChild->objectGetMailOptions("delete", TRUE, TRUE)->bMailOnce) + $aSendMailSubmitter[$oM->sClass][$oChild->objectGetSubmitterId()] = FALSE; + + if($oChild->objectGetMailOptions("delete", FALSE, TRUE)->bMailOnce) + $aSendMailCommon[$oM->sClass] = FALSE; + } else + { + $iFailed++; + } + } + } + + if($oObject->delete()) + { + $oCommonMail->send("delete", $sReplyText); + + if($oSubmitterMail) + $oSubmitterMail->send("delete", $sReplyText); + + if($bStandAlone) + { + addmsg("Entry deleted", "green"); + + if($iDeleted) + { + if($iDeleted == 1) + $sNoun = 'entry'; + else + $sNoun = 'entries'; + + addmsg("Deleted $iDeleted child $sNoun", 'green'); + } + + if($iFailed) + { + if($iFailed == 1) + $sNoun = 'entry'; + else + $sNoun = 'entries'; + + addmsg("Failed to delete $iFailed child $sNoun", 'red'); + } + + $this->return_to_url($this->makeUrl("view", false)); + } + return TRUE; + } + + if($bStandAlone) + addmsg("Failed to delete entry", "red"); + + return FALSE; + } + + /* Return the user to the url specified in the objectManager object. Fall back to a + given value if the object member is not set */ + private function return_to_url($sFallback) + { + $sUrl = $this->sReturnTo; + + if(!$sUrl) + $sUrl = $sFallback; + + util_redirect_and_exit($sUrl); + } + + private function om_from_object($oObject) + { + return new objectManager(get_class($oObject), "", $oObject->objectGetId()); + } + + /* Creates a mail object using information from objectGetMail(). If bMailSubmitter + is true then we first check to see whether the submitter is the one deleting the + entry, in which case we don't send him a notification mail. + Thus it returns null if no mail is to be sent, or a Mail object otherwise. + bParentAction states whether the action was caused by a change to the parent + entry, for instance this will be true when deleting a version because we + delete its parent application. */ + private function get_mail($bMailSubmitter, $sAction, $bParentAction = FALSE) + { + $oObject = new $this->sClass($this->iId); + + if($bMailSubmitter) + { + $iSubmitterId = $oObject->objectGetSubmitterId(); + + /* Should we mail the submitter? */ + if($iSubmitterId && $iSubmitterId != $_SESSION['current']->iUserId) + { + return new mail($oObject->objectGetMail($sAction, $bMailSubmitter, + $bParentAction), + $iSubmitterId); + } else + { + return null; + } + } else + { + return new mail($oObject->objectGetMail("delete", $bMailSubmitter, + $bParentAction)); + } + } + + /* Purge rejected entries, optionally by date */ + public function purgeRejected($aClean) + { + if(!$_SESSION['current']->hasPriv("admin")) + { + addmsg("Insufficient privileges", "red"); + return FALSE; + } + + if(!$this->getOptionalSetting("objectAllowPurgingRejected", FALSE)) + { + addmsg("Purging rejected entries is not allowed for this object type"); + return FALSE; + } + + $oObject = $this->getObject(); + + $hResult = $oObject->objectGetEntries('rejected'); + + if(!$hResult) + { + addmsg("Failed to get list of rejected entries", "red"); + return FALSE; + } + + if($aClean['bTimeLimit'] == 'true') + $iSubmittedBefore = mysqltimestamp_to_unixtimestamp($aClean['sSubmittedBefore']); + else + $iSubmittedBefore = 0; + + $iDeleted = 0; + $iFailed = 0; + + if($sSubmittedBefore) + $sMailWord = "old"; + else + $sMailWord = "all"; + + while($oRow = mysql_fetch_object($hResult)) + { + $oObject = new $this->sClass(null, $oRow); + + if(!$iSubmittedBefore || $oObject->objectGetSubmitTime() < $iSubmittedBefore) + { + $oM = new objectManager($this->sClass, "", $oObject->objectGetId()); + if($oM->delete_entry("Purging $sMailWord rejected entries", false)) + $iDeleted++; + else + $iFailed++; + } + } + + if($iFailed) + addmsg("Failed to delete $iFailed entries", 'red'); + + $sNoun = ($iDeleted == 1) ? 'entry' : 'entries'; + + if($iDeleted) + addmsg("Deleted $iDeleted $sNoun", 'green'); + + $this->return_to_url(APPDB_ROOT); + } + + public function displayPurgeRejected() + { + if(!$_SESSION['current']->hasPriv("admin")) + { + $this->error_exit('Only admins can do this'); + return FALSE; + } + + if(!$this->getOptionalSetting("objectAllowPurgingRejected", FALSE)) + { + $this->error_exit('Purging rejected entries is not allowed for this object type'); + return FALSE; + } + + echo '
    '; + echo 'Purge rejected entries of this type
    '; + echo ' '; + echo 'Only entries submitted before '; + echo '

    '; + echo ''; + echo $this->makeUrlFormData(); + echo ''; + echo '
    '; + } + + /* Move the object to another parent entry */ + public function change_parent($iNewId) + { + $oObject = new $this->sClass($this->iId); + $oParent = $oObject->objectGetParent(); + $sParentClass = get_class($oParent); + $oNewParent = new $sParentClass($iNewId); + + /* The user needs to have edit rights to both the old and the new object + If you have edit rights to an object then you should have edit rights + to its child objects as well */ + if(!$oObject->canEdit() || !$oParent->canEdit() || !$oNewParent->canEdit()) + return FALSE; + + $oObject->objectSetParent($oNewParent->objectGetId()); + + if($oObject->update()) + { + addmsg('The entry was moved successfully', 'green'); + } else + { + addmsg('Failed to move the entry', 'red'); + } + + $this->return_to_url(APPDB_ROOT); + } + + /* Move all the object's children to another object of the same type, and + delete the original object afterwards */ + public function move_children($iNewId) + { + $oObject = new $this->sClass($this->iId); + $oNewObject = new $this->sClass($iNewId); + + /* The user needs to have edit rights to both the old and the new object + If you have edit rights to an object then you should have edit rights + to its child objects as well */ + if(!$oObject->canEdit() || !$oNewObject->canEdit()) + return FALSE; + + $iAffected = $oObject->objectMoveChildren($iNewId); + + /* Some classes record the id of their child objects, so we shouldn't keep an old instance around */ + $this->flushCachedObject(); + + if($iAffected) + { + $sPlural = ($iAffected == 1) ? "": "s"; + addmsg("Moved $iAffected child object$sPlural", "green"); + } else if($iAfffected === FALSE) + { + /* We don't want to delete this object if some children were not moved */ + addmsg("Failed to move child objects", "red"); + return FALSE; + } + + /* The argument is the reply text */ + $this->delete_entry("This entry was merged with an existing one, which can be found at\n" . $oNewObject->objectMakeUrl()); + } + + /* Display a page where the user can move the current object to another parent */ + public function display_change_parent() + { + $oObject = new $this->sClass($this->iId); + if(!$oObject->canEdit()) + { + echo "Insufficient privileges.
    \n"; + return FALSE; + } + + $oParent = $oObject->objectGetParent(); + $oParentOM = new objectManager(get_class($oParent), '', $oParent->objectGetId()); + + $sClassDisplayName = $oParentOM->GetOptionalSetting('objectGetClassDisplayName', 'parent entry'); + + if($this->GetOptionalSetting('objectAllowMovingToNewParent', false)) + echo '

    Create and move to a new $sClassDisplayName

    \n"; + + /* Display some help text */ + echo "

    Move ".$oObject->objectMakeLink()." to the $sClassDisplayName "; + echo "selected below:

    \n"; + + echo "\n"; + echo html_tr(array( + "Name", + "Move here"), + "color4"); + + if(method_exists($oParent, 'objectGetParent')) + { + $oGrandFather = $oParent->objectGetParent(); + } else + { + $oGrandFather = null; + } + + if($oGrandFather && $oParentOM->GetOptionalSetting('objectRestrictMoveObjectListsToParents', false)) + { + $aParentSiblings = $oGrandFather->objectGetChildrenClassSpecific(get_class($oParent)); + + echo "Children of " . $oGrandFather->objectMakeLink() . "
    "; + + $i = 0; + foreach($aParentSiblings as $oCandidate) + { + if($oCandidate->objectGetState() != 'accepted') + continue; + + if($oCandidate->objectGetId() == $oParent->objectGetId()) + continue; + + echo html_tr(array($oCandidate->objectMakeLink(), + "makeUrl('changeParent', $this->iId). "&iNewId=".$oCandidate->objectGetId()."\">Move here"), + ($i % 2) ? "color0" : "color1"); + $i++; + } + } else + { + /* We only allow moving to non-queued objects */ + if(!$hResult = $oParent->objectGetEntries('accepted')) + { + echo "Failed to get list of objects.
    \n"; + return FALSE; + } + + for($i = 0; $oRow = query_fetch_object($hResult); $i++) + { + $sParentClass = get_class($oParent); + $oCandidate = new $sParentClass(null, $oRow); + if($oCandidate->objectGetId() == $oParent->objectGetId()) + { + $i++; + continue; + } + + echo html_tr(array( + $oCandidate->objectMakeLink(), + "makeUrl('changeParent', $this->iId). + "&iNewId=".$oCandidate->objectGetId()."\">Move here"), + ($i % 2) ? "color0" : "color1"); + } + } + + + echo "
    \n"; + } + + /* Display a page where the user can select which object the children of the current + object can be moved to */ + public function display_move_children() + { + $oObject = new $this->sClass($this->iId); + if(!$oObject->canEdit()) + { + echo "Insufficient privileges.
    \n"; + return FALSE; + } + + /* Display some help text */ + echo "

    Move all child objects of ".$oObject->objectMakeLink()." to the entry "; + echo "selected below, and delete ".$oObject->objectMakeLink()." afterwards.

    \n"; + + echo "\n"; + echo html_tr(array( + "Name", + "Move here"), + "color4"); + + if($this->GetOptionalSetting('objectRestrictMoveObjectListsToParents', false)) + { + $oParent = $oObject->objectGetParent(); + + $aParentChildren = $oParent->objectGetChildrenClassSpecific($this->sClass); + + echo "Children of " . $oParent->objectMakeLink() . "
    "; + + $i = 0; + foreach($aParentChildren as $oCandidate) + { + if($oCandidate->objectGetState() != 'accepted') + continue; + + if($oCandidate->objectGetId() == $this->iId) + continue; + + echo html_tr(array($oCandidate->objectMakeLink(), + "makeUrl("moveChildren", $this->iId). "&iNewId=".$oCandidate->objectGetId()."\">Move here"), + ($i % 2) ? "color0" : "color1"); + $i++; + } + } else + { + /* We only allow moving to non-queued objects */ + if(!$hResult = $oObject->objectGetEntries('accepted')) + { + echo "Failed to get list of objects.
    \n"; + return FALSE; + } + + for($i = 0; $oRow = query_fetch_object($hResult); $i++) + { + $oCandidate = new $this->sClass(null, $oRow); + if($oCandidate->objectGetId() == $this->iId) + { + $i++; + continue; + } + + echo html_tr(array( + $oCandidate->objectMakeLink(), + "makeUrl("moveChildren", $this->iId). + "&iNewId=".$oCandidate->objectGetId()."\">Move here"), + ($i % 2) ? "color0" : "color1"); + } + } + + + echo "
    \n"; + } + + private function show_preview($oObject, $aClean) + { + echo html_frame_start("Preview", "75%"); + + $aVars = $this->get_custom_vars($aClean, "preview"); + + if($aVars) + $oObject->display($aVars); + else + $oObject->display(); + + echo html_frame_end(); + } + + /* Display screen for submitting a new entry of given type */ + public function add_entry($aClean, $sErrors = "") + { + $this->checkMethods(array("outputEditor", "getOutputEditorValues", + "update", "create")); + + + $oObject = new $this->sClass(); + + echo "
    \n"; + + /* Display errors, if any, and fetch form data */ + if($this->displayErrors($sErrors)) + { + global $aClean; + $oObject->getOutputEditorValues($aClean); + + if($sErrors === PREVIEW_ENTRY) + $this->show_preview($oObject, $aClean); + } + + /* Display help if it is exists */ + if(method_exists(new $this->sClass, "objectDisplayAddItemHelp")) + { + $aVars = $this->get_custom_vars($aClean, "addHelp"); + + if($aVars) + $oObject->objectDisplayAddItemHelp($aClean); + else + $oObject->objectDisplayAddItemHelp(); + } + + echo "
    makeUrl("add")."\">\n"; + + echo $this->makeUrlFormData(); + + $aVars = $this->get_custom_vars($aClean, "add"); + + if($aVars) + $oObject->outputEditor($aVars); + else + $oObject->outputEditor(); + + $this->oObject = $oObject; + echo "
    "; + echo "\n"; + $this->handle_preview_button(); + echo "
    \n"; + echo html_back_link(1); + + echo "
    \n"; + } + + public function move_to_new_parent($aClean, $sErrors = '') + { + $oObject = new $this->sClass($this->iId); + $oOldParent = $oObject->objectGetParent(); + $sParentClass = get_class($oOldParent); + $oParent = new $sParentClass(); + $oParentOM = new objectManager($sParentClass); + + echo "
    \n"; + + echo '

    Move '.$oObject->objectMakeLink().' to a new entry:

    '; + + /* Display errors, if any, and fetch form data */ + if($this->displayErrors($sErrors)) + { + global $aClean; + $oParent->getOutputEditorValues($aClean); + + if($sErrors === PREVIEW_ENTRY) + $this->show_preview($oParent, $aClean); + } + + /* Display help if it exists */ + if(method_exists($oParent, "objectDisplayAddItemHelp")) + { + $aVars = $this->get_custom_vars($aClean, "addHelp"); + + if($aVars) + $oParent->objectDisplayAddItemHelp($aClean); + else + $oParent->objectDisplayAddItemHelp(); + } + + echo "
    makeUrl('moveToNewParent', $this->iId)."\">\n"; + + echo $this->makeUrlFormData(); + + $aVars = $oParentOM->get_custom_vars($aClean, 'add'); + + if($aVars) + $oParent->outputEditor($aVars); + else + $oParent->outputEditor(); + + $this->oObject = $oObject; + echo "
    "; + echo "\n"; + $this->handle_preview_button(); + echo "
    \n"; + echo html_back_link(1); + + echo "
    \n"; + } + + private function handle_preview_button() + { + $oObject = $this->getObject(); + + if(!method_exists($oObject, "objectShowPreview")) + return; + + if(!$oObject->objectShowPreview()) + return; + + echo ''; + } + + public function show_form_help_session_timeout() + { + $this->error_exit("Your session has timed out. Log in and then refresh thise page."); + } + + public function handle_anonymous_submission($aClean) + { + $oObject = new $this->sClass(); + if($oObject->allowAnonymousSubmissions() || $_SESSION['current']->isLoggedIn()) + return; + + // Allow the user to continue filling out a form + if(getInput('sSubmit', $aClean)) + { + apidb_header($this->get_title(getInput($sAction, $aClean))); + $this->show_form_help_session_timeout(); + } + + login_form(); + exit; + } + + private function displayChangeParent($oObject, $sLinkText = 'default') + { + /* Display a link to the move child objects page if the class has the necessary + functions and the user has edit rights. Not all classes have child objects. */ + if(method_exists($oObject, "objectSetParent") && + method_exists($oObject, "objectGetId") && $oObject->canEdit()) + { + if($sLinkText == 'default') + { + $oParent = $oObject->objectGetParent(); + if(!$oParent || !$oParent->objectGetId()) + { + echo html_note('Failed to find parent entry', 'No parent entry could be found, even though it is supposed to exist.'); + } + if($oParent) + { + $oParentOM = new objectManager(get_class($oParent), '', $oParent->objectGetId()); + $sClassName = $oParentOM->getOptionalSetting('objectGetClassDisplayName', false); + if($sClassName) + $sLinkText = "Move to another $sClassName"; + else + $sLinkText = 'Move to another parent entry'; + } + } + echo "makeUrl("showChangeParent", $this->iId, + "Move to another parent entry")."\">$sLinkText\n"; + } + } + + /* Returns true if the link was displayed */ + private function displayMoveChildren($oObject) + { + /* Display a link to the move child objects page if the class has the necessary + functions and the user has edit rights. Not all classes have child objects. */ + if(method_exists($oObject, "objectMoveChildren") && + method_exists($oObject, "objectGetId") && $oObject->canEdit()) + { + echo "makeUrl("showMoveChildren", $this->iId, + "Move Child Objects")."\">Move child objects\n"; + return true; + } + + return false; + } + + /* Gets the title of the page to be displayed. Classes can set + the page title depending on the action, or return null to + let objectManager use one, normally the title specified in + the URL. Since this only affects the user interface and not + functionality, objectGetCustomTitle is not a required method. + Why do we need this method? Think of the versions, for instance. + If we were to fetch the name from the URL, that would mean + that changes to the version name would not be reflected in + static URLs, like external links to the AppDB. */ + public function get_title($sAction) + { + $oObject = new $this->sClass($this->iId); + $sTitle = ""; + + if(method_exists($oObject, "objectGetCustomTitle")) + $sTitle = $oObject->objectGetCustomTitle($sAction); + + if(!$sTitle) + $sTitle = $this->sTitle; + + return $sTitle; + } + + /* Gets the custom variables, if any, from a class depending on + the action which is being taken, such as viewing an entry, + editing one etc. + Returns null if there are no custom vars, or a labelled array + with the variable contents otherwise */ + private function get_custom_vars($aClean, $sAction) + { + $oObject = new $this->sClass($this->iId); + + if(!method_exists($oObject, "objectGetCustomVars")) + return null; /* No vars */ + + $aVars = array(); + $aVarNames = $oObject->objectGetCustomVars($sAction); + + if(!$aVarNames) /* No vars */ + return null; + + foreach($aVarNames as $sVar) + $aVars[$sVar] = getInput($sVar, $aClean); + + return $aVars; + } + + /* View an entry */ + public function view($sBackLink, $aClean) + { + $this->checkMethods(array("display")); + + $oObject = new $this->sClass($this->iId); + + /* Check that the entry exists */ + if(!$oObject->objectGetId() && !$this->isNullIdAllowed('view')) + $this->error_exit("Entry not found (class: {$this->sClass}, id: {$this->iId})"); + + /* Check if the entry has been deleted */ + if($oObject->objectGetState() == 'deleted') + $this->error_exit("This entry has been deleted (class: {$this->sClass}, id: {$this->iId})
    Its content may have been moved to another entry"); + + /* Show a note if the entry is queued or rejected */ + if($oObject->objectGetState() != 'accepted') + { + $sSentence = 'This entry '; + switch($oObject->objectGetState()) + { + case 'queued': + case 'pending': + $sVerb = 'Queued'; + $sSentence .= 'is currently queued'; + break; + case 'rejected': + $sVerb = 'Rejected'; + $sSentence .= 'has been rejected'; + break; + } + $sSentence .= ', and may not be visible to all users.'; + echo html_note("$sVerb Entry", $sSentence); + } + + $aVars = $this->get_custom_vars($aClean, "view"); + + echo "
    "; + // display the move children entry + if($this->displayMoveChildren($oObject)) + echo "     "; + $this->displayChangeParent($oObject); + + echo "

    "; + + if(!$aVars) + $oObject->display(); + else + $oObject->display($aVars); + + echo '
    '; + // display the move children entry + if($this->displayMoveChildren($oObject)) + echo "     "; + $this->displayChangeParent($oObject); + + echo "

    "; + + echo html_back_link(1, $sBackLink); + } + + /* Process form data generated by adding or updating an entry */ + public function processForm($aClean) + { + // FIXME: hack so if we modify $aClean in here any objects that use the global + // $aClean will see the modified value. Should be replaced when we have + // general purpose objectManager email code in place since the sReplyText value + // is the value we modify and we'll be passing that into methods in the future + global $aClean; + + if(!isset($aClean['sSubmit'])) + return; + + $this->checkMethods(array("getOutputEditorValues", "update", "create", + "canEdit")); + + $this->iId = $this->getIdFromInput($aClean); + + $oObject = new $this->sClass($this->iId); + + if($aClean['sSubmit'] == 'Move to new parent') + { + $oOldParent = $oObject->objectGetParent(); + $sParentClass = get_class($oOldParent); + $oObject = new $sParentClass(); + } + + $oOriginalObject = new $this->sClass($this->iId); /* Prevent possible security hole if users change key + variables, making the permission checks run on + the wrong criteria */ + + /* If it isn't implemented, that means there is no default text */ + if(method_exists(new $this->sClass, "getDefaultReply")) + { + /* Don't send the default reply text */ + if($oObject->getDefaultReply() == $aClean['sReplyText']) + $aClean['sReplyText'] = ""; + } + + // handle the common response radio button value + // if sReplyText is empty, if sOMCommonReply was set because + // the user selected a radio button then use that text instead + if( isset($aClean['sReplyText']) && $aClean['sReplyText'] == "" && isset($aClean['sOMCommonReply'])) + { + $aClean['sReplyText'] = $aClean['sOMCommonReply']; + } + + $oObject->getOutputEditorValues($aClean); + + /* Check input, if necessary */ + if($aClean['sSubmit'] != "Delete" && + method_exists($oObject, "checkOutputEditorInput")) + { + $sErrors = $oObject->checkOutputEditorInput($aClean); + } + + // NOTE: we only check for errors when submitting + // because there is always the possibility that we can + // get into some error state but we don't want to be stuck, unable + // to delete an entry because of an error that we don't want to + // have to correct + switch($aClean['sSubmit']) + { + case "Preview": + return PREVIEW_ENTRY; + + case 'Move to new parent': + if(!$this->iId) + return FALSE; + + if($sErrors) + return $sErrors; + + if(!$oOriginalObject->canEdit()) + return FALSE; + + if(!$this->getOptionalSetting('objectAllowCreatingParents', false)) + return FALSE; + + $oObject->create(); + if($oObject->objectGetState() != 'accepted') + $oObject->unQueue(); + + $oOriginalObject->objectSetParent($oObject->objectGetId()); + $oOriginalObject->update(); + break; + + case "Submit": + // if we have errors, return them + if($sErrors) + return $sErrors; + + // if we have a valid iId then we are displaying an existing entry + // otherwise we should create the entry in the 'else' case + if($this->iId) + { + if(!$oOriginalObject->canEdit()) + return FALSE; + + if($this->sState == 'rejected') + $oObject->ReQueue(); + + if($this->getIsQueue() && !$oOriginalObject->mustBeQueued()) + $oObject->unQueue(); + + $oObject->update(); + } else + { + $this->handle_anonymous_submission(); + + $oObject->create(); + } + break; + + case "Reject": + if(!$oOriginalObject->canEdit()) + return FALSE; + + $oObject->reject(); + break; + + case "Delete": + /* Heere we call an objectManager function instead + of a function of the object's class. Thus we + need to store the object so changes in + getOutputEditorValues() are caught. */ + $this->oObject = $oObject; + $this->delete_entry($aClean['sReplyText']); + break; + + default: + // shouldn't end up here, log the submit type that landed us here + error_log::log_error(ERROR_GENERAL, "processForm() received ". + "unknown aClean[sSubmit] of: ".$aClean['sSubmit']); + return false; + } + + /* Displaying the entire un-queued list for a class is not a good idea, + so only do so for queued data */ + if($this->getIsQueue()) + $sRedirectLink = $this->makeUrl("view", false, $this->sReturnToTitle ? $this->sReturnToTitle : "$this->sClass list"); + else + $sRedirectLink = APPDB_ROOT; + + $this->return_to_url($sRedirectLink); + + return TRUE; + } + + /* Make an objectManager URL based on the object and optional parameters */ + public function makeUrl($sAction = false, $iId = false, $sTitle = false, $bOmitFilters = false) + { + $sUrl = APPDB_ROOT."objectManager.php?"; + + $sIsQueue = $this->getIsQueue() ? "true" : "false"; + $sUrl .= "bIsQueue=$sIsQueue"; + $sIsRejected = $this->sState == 'rejected' ? "true" : "false"; + $sUrl .= "&bIsRejected=$sIsRejected"; + + $sUrl .= "&sClass=".$this->sClass; + if($iId) + $sUrl .= "&iId=$iId"; + + if($sAction) + $sUrl .= "&sAction=$sAction"; + + if($this->sReturnTo) + $sUrl .= "&sReturnTo=".urlencode($this->sReturnTo); + + if(!$sTitle) + $sTitle = $this->sTitle; + + if($this->sReturnToTitle) + $sUrl .= "&sReturnToTitle=".$this->sReturnToTitle; + + $sUrl .= "&sTitle=".urlencode($sTitle); + + if($this->oMultiPage->bEnabled) + { + $sUrl .= "&iItemsPerPage=".$this->oMultiPage->iItemsPerPage; + $sUrl .= "&iPage=".$this->oMultiPage->iPage; + } + + /* Some times it is necessary to omit the filter data, for instance when using + makeUrl() to form the action element of a form tag. This is because having + filter data present may prevent clearing a filter */ + if($this->oFilters && !$bOmitFilters) + $sUrl .= $this->oFilters->getUrlData(); + + if($this->oSortInfo && $this->oSortInfo->sCurrentSort) + { + $sUrl .= "&sOrderBy={$this->oSortInfo->sCurrentSort}"; + $sUrl .= '&bAscending='.($this->oSortInfo->bAscending ? 'true' : 'false'); + } + + return $sUrl; + } + + /* Inserts the information in an objectManager object as form data, so that it + is preserved when submitting forms */ + public function makeUrlFormData() + { + $sIsQueue = $this->getIsQueue() ? "true" : "false"; + $sIsRejected = $this->sState == 'rejected' ? "true" : "false"; + + $sReturn = "\n"; + $sReturn .= "\n"; + $sReturn .= "sClass."\">\n"; + $sReturn .= "sTitle."\">\n"; + $sReturn .= "sReturnTo."\">\n"; + $sReturn .= "iId."\">\n"; + + if($this->oMultiPage->bEnabled) + { + $sReturn .= "oMultiPage->iItemsPerPage."\">\n"; + $sReturn .= "oMultiPage->iPage."\">\n"; + } + + if($this->oFilters) + $sReturn .= $this->oFilters->getHiddenFormData(); + + if($this->sReturnToTitle) + $sReturn .= "sReturnToTitle."\">\n"; + + if($this->oSortInfo && $this->oSortInfo->sCurrentSort) + { + $sReturn .= "oSortInfo->sCurrentSort}\">"; + $sReturn .= "oSortInfo->bAscending ? 'true' : 'false')."\">"; + } + + return $sReturn; + } + + /* Get id from form data */ + private function getIdFromInput($aClean) + { + $sId = "i".ucfirst($this->sClass)."Id"; + $iId = isset($aClean['sId']) ? $aClean['sId'] : $aClean['iId']; + + return $iId; + } + + /* Output headers for a table */ + private function outputHeader($sClass) + { + $oObject = new $this->sClass(); + $oTableRow = $oObject->objectGetHeader($this->sState); + + /* Add an action column if the user can edit this class, or if it is a queue. + Even though a user annot process items, he can edit his queued submissions */ + if($oObject->canEdit() || $this->getIsQueue()) + { + $oTableRow->AddTextCell("Action"); + } + + $oTableRow->SetClass($sClass); + + /* Set the current sorting info if the header is sortable */ + if(get_class($oTableRow) == "TableRowSortable") + $oTableRow->SetSortInfo($this->oSortInfo); + + echo $oTableRow->GetString(); + } + + private function handleFilterControls($aClean) + { + /* Show filter info */ + if($this->oFilters) + { + echo "
    makeUrl(false, false, false, true)."\" >"; + + echo $this->oFilters->getEditor(); + + echo "
    "; + echo "
    "; + } + } + + /* Shows how many entries we are displaying */ + private function showNumberOfResults($oObject) + { + $iTotalEntries = $oObject->objectGetEntriesCount($this->sState, $this->oFilters); + if($this->oMultiPage->isEnabled()) + { + $iShowingEntryFrom = $this->oMultiPage->iLowerLimit + 1; + $iShowingEntryTo = min($this->oMultiPage->iLowerLimit + $this->oMultiPage->iItemsPerPage, $iTotalEntries); + echo "Showing entry $iShowingEntryFrom to $iShowingEntryTo of $iTotalEntries

    \n"; + } else + { + echo "Showing $iTotalEntries entries"; + } + } + + private function handleMultiPageControls($aClean, $bItemsPerPageSelector = TRUE) + { + /* Display multi-page browsing controls (prev, next etc.) if applicable. + objectGetItemsPerPage returns FALSE if no multi-page display should be used, + or an array of options, where the first element contains an array of items + per page values and the second contains the default value. + If the function does not exist we assume no multi-page behaviour */ + $oObject = new $this->sClass(); + $sControls = ''; + + if(!method_exists($oObject, "objectGetItemsPerPage") || + $oObject->objectGetItemsPerPage($this->sState) === FALSE) + { + /* Do not enable the MultiPage controls */ + $this->oMultiPage->MultiPage(FALSE); + return; + } + + $aReturn = $oObject->objectGetItemsPerPage($this->sState); + $aItemsPerPage = $aReturn[0]; + $iDefaultPerPage = $aReturn[1]; + + + $iItemsPerPage = $iDefaultPerPage; + + if ( isset($aClean['iItemsPerPage']) && + in_array($aClean['iItemsPerPage'], $aItemsPerPage) ) + { + $iItemsPerPage = $aClean['iItemsPerPage']; + } + + // if $bItemsPerPageSelector is true, display the items + // per-page dropdown and update button + if($bItemsPerPageSelector) + { + $sControls = "
    makeUrl()."\" method=\"get\">"; + + /* Fill in form data for the objectManager URL */ + $sControls .= $this->makeUrlFormData(); + $sControls .= "

     Items per page"; + $sControls .= " "; + $sControls .= "   "; + $sControls .= "

    "; + } + + $iTotalEntries = $oObject->objectGetEntriesCount($this->sState, $this->oFilters); + $iNumPages = ceil($iTotalEntries / $iItemsPerPage); + if($iNumPages == 0) + $iNumPages = 1; + + /* Check current page value */ + $iPage = isset($aClean['iPage']) ? $aClean['iPage'] : 1; + $iCurrentPage = min($iPage, $iNumPages); + + // if iPage is beyond the maximum number of pages, make it the + // highest page number + if($iPage > $iNumPages) + $iPage = $iNumPages; + + /* Display selectors and info */ + echo '
    '; + echo "Page $iPage of $iNumPages
    "; + + /* Page controls */ + $iPageRange = 7; // the number of page links we want to display + display_page_range($iPage, $iPageRange, $iNumPages, + $this->makeUrl()."&iItemsPerPage=$iItemsPerPage"); + + echo $sControls; + echo "
    \n"; + + /* Fill the MultiPage object with the LIMIT related values */ + $iLowerLimit = ($iPage - 1) * $iItemsPerPage; + $this->oMultiPage->MultiPage(TRUE, $iItemsPerPage, $iLowerLimit); + $this->oMultiPage->iPage = $iPage; + } + + public function getQueueString($bQueued, $bRejected) + { + if($bQueued) + { + if($bRejected) + $sQueueString = "rejected"; + else + $sQueueString = "true"; + } else + $sQueueString = "false"; + + return $sQueueString; + } + + public function getStateString($bQueued, $bRejected) + { + if($bQueued) + { + if($bRejected) + $sStateString = 'rejected'; + else + $sStateString = 'queued'; + } else + $sStateString = 'accepted'; + + return $sStateString; + } + + private function displayErrors($sErrors) + { + if($sErrors) + { + /* A class's checkOutputEditorInput() may simply return TRUE if + it wants the editor to be displayed again, without any error + messages. This is for example useful when gathering information + in several steps, such as with application submission */ + if($sErrors === TRUE) + return TRUE; + + + if($sErrors == PREVIEW_ENTRY) + return TRUE; + + echo "\n"; + echo "The following errors were found
    \n"; + echo "
      $sErrors
    \n"; + echo "

    "; + return TRUE; + } else + { + return FALSE; + } + } +} + +class MultiPage +{ + var $iItemsPerPage; + var $iLowerLimit; /* Internal; set by handleMultiPageControls. We use iPage in the URls */ + var $iPage; + var $bEnabled; + + function MultiPage($bEnabled = FALSE, $iItemsPerPage = 0, $iLowerLimit = 0) + { + $this->bEnabled = $bEnabled; + $this->iItemsPerPage = $iItemsPerPage; + $this->iLowerLimit = $iLowerLimit; + } + + public function isEnabled() + { + return $this->bEnabled; + } + + function getDataFromInput($aClean) + { + if(isset($aClean['iItemsPerPage']) && isset($aClean['iPage'])) + $this->bEnabled = TRUE; + else + return; + + $this->iItemsPerPage = $aClean['iItemsPerPage']; + $this->iPage = $aClean['iPage']; + } +} + +class mailOptions +{ + var $bMailOnce; + + function mailOptions() + { + /* Set default options */ + $this->bMailOnce = FALSE; + } +} + +class mail +{ + var $sSubject; + var $sMessage; + var $sRecipients; + + function mail($aInput, $iRecipientId = null) + { + if(!$aInput) + return; + + /* $aInput is returned from objectGetMail(); an array with the following members + 0: Mail subject + 1: Mail text + 2: Space-separated list of recipients + If iRecipientId is set the third array member is ignored. */ + $this->sSubject = $aInput[0]; + $this->sMessage = $aInput[1]; + + if($iRecipientId) + { + $oRecipient = new user($iRecipientId); + $this->sRecipients = $oRecipient->sEmail; + } else + { + $this->sRecipients = $aInput[2]; + } + } + + function send($sAction, $sReplyText) + { + /* We don't send empty mails */ + if(!$this->sSubject && !$this->sMessage) + return; + + $this->sMessage .= "\n"; + + $this->sMessage .= "The action was performed by ".$_SESSION['current']->sRealname."\n"; + + if($sReplyText) + { + switch($sAction) + { + case "delete": + $this->sMessage .= "Reasons given\n"; + break; + } + + $this->sMessage .= $sReplyText; + } else + { + $this->sMessage .= 'No reasons given'; + } + + mail_appdb($this->sRecipients, $this->sSubject, $this->sMessage); + } +} + +?> diff --git a/include/parsedate.php b/include/parsedate.php new file mode 100644 index 0000000..01bc585 --- /dev/null +++ b/include/parsedate.php @@ -0,0 +1,84 @@ + 1, "feb" => 2, "mar" => 3, "apr" => 4, "may" => 5, "jun" => 6, + "jul" => 7, "aug" => 8, "sep" => 9, "oct" => 10, "nov" => 11, "dec" => 12); + $ampm = array("am" => 00, "pm" => 12); + + if(!$datestr) + return -1; + + $datestr = strtolower($datestr); + $datestr = ereg_replace("[,]", "", $datestr); + $dp = explode(' ', $datestr); + while(list($idx, $part) = each($dp)) + { + //echo "PART($part)
    "; + + /* 23:59:59 */ + if(ereg("^([0-9]+):([0-9]+):([0-9]+)$", $part, $arr)) + { + $hour = $arr[1]; + $minute = $arr[2]; + $second = $arr[3]; + continue; + } + + /* 23:59 */ + if(ereg("^([0-9]+):([0-9]+)$", $part, $arr)) + { + $hour = $arr[1]; + $minute = $arr[2]; + $second = 0; + continue; + } + + /* 2000-12-31 (mysql date format) */ + if(ereg("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$", $part, $arr)) + { + $year = $arr[1]; + $month = $arr[2]; + $day = $arr[3]; + continue; + } + + if(defined($ampm[$part])) + { + $hour += $ampm[$part]; + continue; + } + + if($monthnames[substr($part, 0, 3)]) + { + $month = $monthnames[substr($part, 0, 3)]; + continue; + } + + if($part > 1900) + { + $year = $part; + continue; + } + + if($part > 31) + { + $year = 1900 + $part; + continue; + } + + if($part >= 1 && $part <= 31) + { + $day = $part; + continue; + } + + //echo "Unparsed: '$part'
    \n"; + + } + + return mktime($hour, $minute, $second, $month, $day, $year); +} + +?> diff --git a/include/query.php b/include/query.php new file mode 100644 index 0000000..0c45496 --- /dev/null +++ b/include/query.php @@ -0,0 +1,232 @@ + 'original string quoted' + * OPAQUE (&) => 'string from file quoted' + * MISC (~) => original string (left 'as-is') + * + * NOTE: These rules convienently match those for Pear DB + * + * MySQL Prepare Function + * By: Kage (Alex) + * KageKonjou@GMail.com + * http://us3.php.net/manual/en/function.mysql-query.php#53400 + * + * Modified by CMM 20060622 + * + * Values are mysql_real_escape_string()'d to prevent against injection attacks + * See http://php.net/mysql_real_escape_string for more information about why this is the case + * + * Usage: + * $hResult = query_parameters("Select * from mytable where userid = '?'", + * $iUserId); + * + * Note: + * Ensure that all variables are passed as parameters to query_parameters() + * to ensure that sql injection attacks are prevented against + * + */ +function query_parameters() +{ + global $hAppdbLink; + + if(!is_resource($hAppdbLink)) + { + // The last argument makes sure we are really opening a new connection + $hAppdbLink = mysql_connect(APPS_DBHOST, APPS_DBUSER, APPS_DBPASS, true) or die('Database error, please try again soon: '.mysql_error()); + mysql_select_db(APPS_DB, $hAppdbLink); + } + + $aData = func_get_args(); + $sQuery = $aData[0]; + $aTokens = split("[&?~]", $sQuery); /* NOTE: no need to escape characters inside of [] in regex */ + $sPreparedquery = $aTokens[0]; + $iCount = strlen($aTokens[0]); + + /* do we have the correct number of tokens to the number of parameters provided? */ + if(count($aTokens) != count($aData)) + return NULL; /* count mismatch, return NULL */ + + for ($i=1; $i < count($aTokens); $i++) + { + $char = substr($sQuery, $iCount, 1); + $iCount += (strlen($aTokens[$i])+1); + if ($char == "&") + { + $fp = @fopen($aData[$i], 'r'); + $pdata = ""; + if ($fp) + { + while (($sBuf = fread($fp, 4096)) != false) + { + $pdata .= $sBuf; + } + fclose($fp); + } + } else + { + $pdata = &$aData[$i]; + } + $sPreparedquery .= ($char != "~" ? mysql_real_escape_string($pdata) : $pdata); + $sPreparedquery .= $aTokens[$i]; + } + + return query_appdb($sPreparedquery); +} + +function query_bugzilladb($sQuery,$sComment="") +{ + global $hBugzillaLink; + + if(!is_resource($hBugzillaLink)) + { + // The last argument makes sure we are really opening a new connection + $hBugzillaLink = mysql_connect(BUGZILLA_DBHOST, BUGZILLA_DBUSER, BUGZILLA_DBPASS, true); + if(!$hBugzillaLink) return; + mysql_select_db(BUGZILLA_DB, $hBugzillaLink); + } + + $hResult = mysql_query($sQuery, $hBugzillaLink); + if(!$hResult) query_error($sQuery, $sComment, $hBugzillaLink); + return $hResult; +} + + +function query_error($sQuery, $sComment, $hLink) +{ + static $bInQueryError = false; + + // if we are already reporting an error we can't report it again + // as that indicates that error reporting itself produced an error + if($bInQueryError) + return; + + // record that we are inside of this function, we don't want to recurse + $bInQueryError = true; + + error_log::log_error(ERROR_SQL, "Query: '".$sQuery."' ". + "mysql_errno(): '".mysql_errno($hLink)."' ". + "mysql_error(): '".mysql_error($hLink)."' ". + "comment: '".$sComment."'"); + + $sStatusMessage = "

    An internal error has occurred and has been logged and reported to appdb admins

    "; + addmsg($sStatusMessage); + + $bInQueryError = false; // clear variable upon exit +} + +function query_fetch_row($hResult) +{ + return mysql_fetch_row($hResult); +} + +function query_fetch_object($hResult) +{ + return mysql_fetch_object($hResult); +} + +function query_appdb_insert_id() +{ + global $hAppdbLink; + return mysql_insert_id($hAppdbLink); +} + +function query_bugzilla_insert_id() +{ + global $hBugzillaLink; + return mysql_insert_id($hBugzillaLink); +} + +function query_num_rows($hResult) +{ + return mysql_num_rows($hResult); +} + +function query_escape_string($sString) +{ + global $hAppdbLink; + + if(!is_resource($hAppdbLink)) + { + // The last argument makes sure we are really opening a new connection + $hAppdbLink = mysql_connect(APPS_DBHOST, APPS_DBUSER, APPS_DBPASS, true); + if(!$hAppdbLink) + die("Database error, please try again soon."); + mysql_select_db(APPS_DB, $hAppdbLink); + } + + return mysql_real_escape_string($sString, $hAppdbLink); +} + +function query_field_type($hResult, $iFieldOffset) +{ + return mysql_field_type($hResult, $iFieldOffset); +} + +function query_field_name($hResult, $iFieldOffset) +{ + return mysql_field_name($hResult, $iFieldOffset); +} + +function query_field_len($hResult, $ifieldOffset) +{ + return mysql_field_len($hResult, $iFieldOffset); +} + +function query_field_flags($hResult, $iFieldOffset) +{ + return mysql_field_flags($hResult, $iFieldOffset); +} + +function query_fetch_field($hResult, $iFieldOffset) +{ + return mysql_fetch_field($hResult, $iFieldOffset); +} + +?> diff --git a/include/screenshot.php b/include/screenshot.php new file mode 100644 index 0000000..a48b375 --- /dev/null +++ b/include/screenshot.php @@ -0,0 +1,832 @@ +iScreenshotId = $oRow->id; + $this->sDescription = $oRow->description; + $this->iAppId = $oRow->appId; + $this->iVersionId = $oRow->versionId; + $this->sUrl = $oRow->url; + $this->bQueued = ($oRow->state=='queued')?true:false; + $this->sSubmitTime = $oRow->submitTime; + $this->iSubmitterId = $oRow->submitterId; + $this->hFile = null; + } + } + + + /** + * Creates a new screenshot. + */ + function create() + { + $hResult = query_parameters("INSERT INTO appData + (versionId, type, description, state, submitTime, submitterId) + VALUES('?', '?', '?', '?', ?, '?')", + $this->iVersionId, "screenshot", + $this->sDescription, + $this->mustBeQueued() ? 'queued' : 'accepted', + "NOW()", + $_SESSION['current']->iUserId); + if($hResult) + { + $this->iScreenshotId = query_appdb_insert_id(); + + /* make sure we supply the full path to move_uploaded_file() */ + $moveToPath = appdb_fullpath("data/screenshots/originals/").$this->iScreenshotId; + if(!move_uploaded_file($this->hFile['tmp_name'], $moveToPath)) + { + // whoops, moving failed, do something + addmsg("Unable to move screenshot from '".$this->hFile['tmp_name']."' to '".$moveToPath."'", "red"); + $sQuery = "DELETE + FROM appData + WHERE id = '?'"; + query_parameters($sQuery, $this->iScreenshotId); + return false; + } else // we managed to copy the file, now we have to process the image + { + $this->sUrl = $this->iScreenshotId; + if($this->generate()) + { + // we have to update the entry now that we know its name + $sQuery = "UPDATE appData + SET url = '?' + WHERE id = '?'"; + if (!query_parameters($sQuery, $this->iScreenshotId, $this->iScreenshotId)) return false; + } else + { + addmsg("Unable to generate image or thumbnail. The file format might not be recognized. Please use PNG or JPEG only.","red"); + $sQuery = "DELETE + FROM appData + WHERE id = '?'"; + query_parameters($sQuery, $this->iScreenshotId); + return false; + } + } + + $this->screenshot($this->iScreenshotId,$this->bQueued); + $this->mailMaintainers(); + return true; + } + else + { + addmsg("Error while creating a new screenshot.", "red"); + return false; + } + } + + function purge() + { + return $this->delete(); + } + + /** + * Deletes the screenshot from the database. + * and request its deletion from the filesystem (including the thumbnail). + * + * Returns: true if deletion was success, false if otherwise + */ + function delete() + { + /* appData has a universal function for removing database entries */ + $oAppData = new appData($this->iScreenshotId, null, $this); + if($oAppData->delete()) + { + /* make sure the screenshot and thumbnail is loaded */ + /* up before we try to delete them */ + $this->load_image(true); + $this->load_image(false); + + $this->oScreenshotImage->delete(); + $this->oThumbnailImage->delete(); + + // if the original file exists, delete it + $sOriginalFilename = appdb_fullpath("/data/screenshots/originals/".$this->iScreenshotId); + if(is_file($sOriginalFilename)) + unlink($sOriginalFilename); + } + + return true; + } + + function reject() + { + $this->delete(); + } + + /** + * Move screenshot out of the queue. + */ + function unQueue() + { + // If we are not in the queue, we can't move the screenshot out of the queue. + if(!$this->bQueued) + return false; + + if(query_parameters("UPDATE appData SET state = '?' WHERE id='?'", + 'accepted', $this->iScreenshotId)) + { + $this->bQueued = false; + // we send an e-mail to interested people + $this->mailSubmitter(); + $this->mailMaintainers(); + // the screenshot has been unqueued + addmsg("The screenshot has been unqueued.", "green"); + } + } + + + /** + * Cleans up the memory. + */ + function free() + { + if($this->oScreenshotImage) + $this->oScreenshotImage->destroy(); + if($this->oThumbnailImage) + $this->oThumbnailImage->destroy(); + } + + + /** + * Sets the screenshot description. + */ + function setDescription($sDescription) + { + if($hResult = query_parameters("UPDATE id SET description = '?' WHERE id = '?' AND type = 'screenshot'", + $sDescription, $this->iScreenshotId)) + $this->sDescription = $sDescription; + } + + + /** + * This method generates a watermarked screenshot and thumbnail from the original file. + * Useful when changing thumbnail, upgrading GD, adding an image, etc. + * Return false if an image could not be loaded. + */ + function generate() + { + global $watermark; + // first we will create the thumbnail + // load the screenshot + $this->oThumbnailImage = new Image("/data/screenshots/originals/".$this->sUrl); + if(!$this->oThumbnailImage->isLoaded()) + { + $this->oThumbnailImage->delete(); // if we cannot load the original file we delete it from the filesystem + return false; + } + $this->oThumbnailImage->make_thumb(0,0,1,'#000000'); + // store the image + $this->oThumbnailImage->output_to_file(appdb_fullpath("/data/screenshots/thumbnails/".$this->sUrl)); + + // now we'll process the screenshot image for watermarking + // load the screenshot + $this->oScreenshotImage = new Image("/data/screenshots/originals/".$this->sUrl); + if(!$this->oScreenshotImage->isLoaded()) return false; + // resize the image + $this->oScreenshotImage->make_full(); + // store the resized image + $this->oScreenshotImage->output_to_file(appdb_fullpath("/data/screenshots/".$this->sUrl)); + // reload the resized screenshot + $this->oScreenshotImage = new Image("/data/screenshots/".$this->sUrl); + if(!$this->oScreenshotImage->isLoaded()) return false; + + // add the watermark to the screenshot + $this->oScreenshotImage->add_watermark($watermark->get_image_resource()); + // store the watermarked image + $this->oScreenshotImage->output_to_file(appdb_fullpath("/data/screenshots/".$this->sUrl)); + + return true; + } + + /* ensure that either the thumbnail or screenshot */ + /* has been loaded into memory */ + function load_image($bThumbnail) + { + if($bThumbnail) + { + /* if we haven't loaded the thumbnail up yet, do so */ + if(!$this->oThumbnailImage) + $this->oThumbnailImage = new Image("/data/screenshots/thumbnails/".$this->sUrl); + } else + { + /* if we haven't loaded the screenshot up yet, do so */ + if(!$this->oScreenshotImage) + $this->oScreenshotImage = new Image("/data/screenshots/".$this->sUrl); + } + } + + /* output the thumbnail if $bThumbnail or the full screenshot if !$bThumbnail */ + /* NOTE: use this instead of calling through to this classes oScreenshot or */ + /* oThumbnail objects directly to their output_*() functions */ + function output_screenshot($bThumbnail) + { + $this->load_image($bThumbnail); + + if($bThumbnail) + { + if($this->oThumbnailImage) + $this->oThumbnailImage->output_to_browser(1); + } else + { + if($this->oScreenshotImage) + $this->oScreenshotImage->output_to_browser(1); + } + } + + /* Accessor functions for the screenshot and thumbnail images that this */ + /* screenshot object encapsulates */ + /* NOTE: DO NOT call like $oScreenshot->oScreenshotImage->get_width(), there is NO */ + /* guarantee that oScreenshotImage will be valid */ + function get_screenshot_width() + { + $this->load_image(false); + return $this->oScreenshotImage->get_width(); + } + + public function objectGetParent($sClass = '') + { + $oAppData = new appData($this->iScreenshotId, null, $this); + return $oAppData->objectGetParent(); + } + + public function objectSetParent($iNewId, $sClass = '') + { + if($this->iVersionId) + $this->iVersionId = $iNewId; + else + $this->iAppId = $iNewId; + } + + function objectGetChildren($bIncludeDeleted = false) + { + /* We have none */ + return array(); + } + + function get_screenshot_height() + { + $this->load_image(false); + return $this->oScreenshotImage->get_height(); + } + + function get_thumbnail_width() + { + $this->load_image(true); + return $this->oThumbnailImage->get_width(); + } + + function get_thumbnail_height() + { + $this->load_image(true); + return $this->oThumbnailImage->get_height(); + } + + function objectGetSubmitterId() + { + return $this->iSubmitterId; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + $oOptions = new mailOptions(); + + if($sAction == "delete" && $bParentAction) + $oOptions->bMailOnce = TRUE; + + return $oOptions; + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + $sFor = version::fullName($this->iVersionId); + + $sMsg = null; + $sSubject = null; + + if($bMailSubmitter) + { + switch($sAction) + { + case "delete": + if($bParentAction) + { + $sSubject = "Submitter screenshots deleted"; + $sMsg = "The screenshots you submitted for $sFor have been ". + "deleted because $sFor was deleted."; + } else + { + $sSubject = "Submitted screenshot deleted"; + $sMsg = "The screenshot with description '".$this->sDescription. + "' that you submitted for $sFor has been deleted."; + } + break; + } + $aMailTo = null; + } else + { + switch($sAction) + { + case "delete": + if(!$bParentAction) + { + $sSubject = "Screenshot for $sFor deleted"; + $sMsg = "The screenshot with description '".$this->sDescription. + "' for $sFor has been deleted."; + } + break; + } + $aMailTo = User::get_notify_email_address_list(null, $this->iVersionId); + } + return array($sSubject, $sMsg, $aMailTo); + } + + function mailSubmitter($bRejected=false) + { + global $aClean; + + if($this->iSubmitterId) + { + $sAppName = Application::lookup_name($this->iAppId)." ".Version::lookup_name($this->iVersionId); + $oSubmitter = new User($this->iSubmitterId); + if(!$bRejected) + { + $sSubject = "Submitted screenshot accepted"; + $sMsg = "The screenshot you submitted for ".$sAppName." has been accepted."; + } else + { + $sSubject = "Submitted screenshot rejected"; + $sMsg = "The screenshot you submitted for ".$sAppName." has been rejected."; + } + $sMsg .= $aClean['sReplyText']."\n"; + $sMsg .= "We appreciate your help in making the Application Database better for all users."; + + mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg); + } + } + + + function mailMaintainers($bDeleted=false) + { + $oVersion = new version($this->iVersionId); + $sAppName = version::fullName($this->iVersionId); + + if(!$bDeleted) + $sMsg = $this->objectMakeUrl()."\n"; + else + $sMsg = $oVersion->objectMakeUrl()."\n"; + + if(!$bDeleted) + { + if(!$this->bQueued) + { + $sSubject = "Screenshot for $sAppName added by ". + $_SESSION['current']->sRealname; + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + $sMsg .= "This screenshot has been submitted by ". + $oSubmitter->sRealname."."; + $sMsg .= "\n"; + } + addmsg("The screenshot was successfully added into the database.", + "green"); + } else // Screenshot queued. + { + $sSubject = "Screenshot for $sAppName submitted by ". + $_SESSION['current']->sRealname; + $sMsg .= "This screenshot has been queued."; + $sMsg .= "\n"; + addmsg("The screenshot you submitted will be added to the ". + "database after being reviewed.", "green"); + } + } else // Screenshot deleted. + { + $sSubject = "Screenshot for $sAppName deleted by ". + $_SESSION['current']->sRealname; + addmsg("Screenshot deleted.", "green"); + } + + $sEmail = User::get_notify_email_address_list(null, $this->iVersionId); + if($sEmail) + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + function get_zoomicon_overlay() + { + /* if the user is using mozilla or firefox show the zoom icon over images */ + /* otherwise because IE doesn't support transparent PNGs or proper css we have to */ + /* skip it for IE */ + if(strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") === false) + { + $sZoomIcon = ''; + } + else + $sZoomIcon = ""; + + return $sZoomIcon; + } + + /** + * Get a random image for a particular version of an app. + * If the version is not set, get a random app image + * + * $bFormatting == false turns off all extranious formatting applied to the returned image html + */ + function get_random_screenshot_img($iAppId = null, $iVersionId = null, + $bFormatting = true) + { + // initialize variables to avoid notices when appending to them + $hResult = null; + $sImgFile = ''; + $sImg = ''; + // we want a random screenshots for this app + if($iAppId && !$iVersionId) + { + $hResult = query_parameters("SELECT appData.id, appData.description, RAND() AS rand + FROM appData, appVersion + WHERE appData.versionId = appVersion.versionId + AND appVersion.appId = '?' + AND type = 'screenshot' + AND appData.state = 'accepted' + ORDER BY rand", $iAppId); + } else if ($iVersionId) // we want a random screenshot for this version + { + $hResult = query_parameters("SELECT id, description, RAND() AS rand + FROM appData + WHERE versionId = '?' + AND type = 'screenshot' + AND state = 'accepted' + ORDER BY rand", $iVersionId); + } + + if($bFormatting) + $sImgFile .= '
    '; + + if(!$hResult || !query_num_rows($hResult)) + { + $sImgFile.= 'No Screenshot'; + } else + { + $oRow = query_fetch_object($hResult); + $sImgFile.= ''.$oRow->description.''; + } + + if($bFormatting) + $sImgFile .= '
    '; + + if($bFormatting) + $sImg = html_frame_start("",'128','',2); + + /* retrieve the url for the zoom icon overlay */ + $sZoomIcon = Screenshot::get_zoomicon_overlay(); + + /* we have screenshots */ + if($hResult && query_num_rows($hResult)) + { + if($iVersionId) + $sImg .= ""; + else + $sImg .= ""; + } else if($iVersionId) /* we are asking for a specific app version but it has no screenshots */ + { + $sImg .= ""; + } else /* we have no screenshots and we aren't a specific version, we don't allow adding screenshots for an app */ + { + $sImg .= $sImgFile.$sZoomIcon; + } + + if($bFormatting) + $sImg .= html_frame_end()."
    "; + + return $sImg; + } + + function get_screenshots($iAppId = null, $iVersionId = null, $bQueued = "false") + { + /* + * We want all screenshots for this app. + */ + if($iAppId && !$iVersionId) + { + $hResult = query_parameters("SELECT appData.*, appVersion.appId as appId + FROM appData, appVersion + WHERE appVersion.versionId = appData.versionId + AND type = 'screenshot' + AND appVersion.appId = '?' + AND appData.state = '?'", $iAppId, ($bQueued == 'false') ? 'accepted' : 'queued'); + } + /* + * We want all screenshots for this version. + */ + else if ($iVersionId) + { + $hResult = query_parameters("SELECT appData.*, appVersion.appId as appId + FROM appData, appVersion + WHERE appVersion.versionId = appData.versionId + AND type = 'screenshot' + AND appData.versionId = '?' + AND appData.state = '?'", $iVersionId, ($bQueued == 'false') ? 'accepted' : 'queued'); + } else + { + return false; + } + + return $hResult; + } + + function get_thumbnail_img() + { + // generate random tag for popup window + $sRandName = User::generate_passwd(5); + // set img tag + $shImgSRC = 'iScreenshotId.'" alt="'.$this->sDescription. + '" width="'.$this->get_thumbnail_width(). + '" height="'.$this->get_thumbnail_height().'">'; + $shImg = 'get_screenshot_width() + 20).','. + ($this->get_screenshot_height() + 6). + ');return false;">'.$shImgSRC.Screenshot::get_zoomicon_overlay().''; + + // set image link based on user pref + if ($_SESSION['current']->isLoggedIn()) + { + if ($_SESSION['current']->getpref("window:screenshot") == "no") + { + $shImg = ''.$shImgSRC.''; + } + } + return $shImg; + } + + public static function objectGetItemsPerPage($sState = 'accepted') + { + if($sState != 'accepted') + { + $aItemsPerPage = array(25, 50, 100, 200); + $iDefaultPerPage = 25; + } else + { + $aItemsPerPage = array(6, 9, 12, 15, 18, 21, 24); + $iDefaultPerPage = 6; + } + return array($aItemsPerPage, $iDefaultPerPage); + } + + function objectWantCustomDraw($sWhat, $sQueued) + { + switch($sWhat) + { + case 'table': + if($sQueued == 'false') + return true; + break; + } + + return false; + } + + function objectDrawCustomTable($hResult, $sQueued) + { + echo "
    \n"; + for($i = 1; $oRow = query_fetch_object($hResult); $i++) + { + // display thumbnail + $oVersion = new version($oRow->versionId); + $oApp = new Application($oVersion->iAppId); + $oScreenshot = new Screenshot($oRow->id); + $shImg = $oScreenshot->get_thumbnail_img(); + echo "\n"; + // end row if counter of 3 + if($i % 3 == 0) + echo "\n"; + } + + echo "
    \n"; + echo $shImg; + echo "
    ". substr($oRow->description,0,20). "\n"; + + echo "
    [".$oApp->objectMakeLink()."]"; + + echo "
    [".$oVersion->objectMakeLink()."]"; + + if($oScreenshot->canEdit()) + { + $oM = new objectManager('screenshot'); + echo '
    [Delete]'; + } + + echo "

    \n"; + } + + public function objectGetFilterInfo() + { + $oFilter = new filterInterface(); + + $aCatNames = array(); + $aCatIds = array(); + + $aCategories = category::getOrderedList(); + foreach($aCategories as $oCategory) + { + $aCatNames[] = $oCategory->sName; + $aCatIds[] = $oCategory->objectGetId(); + } + + $oFilter->addFilterInfo('appCategory', 'App category', array(FILTER_OPTION_ENUM), FILTER_VALUES_OPTION_ENUM, $aCatIds, $aCatNames); + + return $oFilter; + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true, $oFilters = null) + { + return appData::objectGetEntries($sState, $iRows, $iStart, $sOrderBy, $bAscending, + 'screenshot', $oFilters); + } + + function objectGetEntriesCount($sState, $oFilters = null) + { + return appData::objectGetEntriesCount($sState, 'screenshot', $oFilters); + } + + function objectGetHeader() + { + return appData::objectGetHeader("screenshot"); + } + + function objectGetState() + { + return ($this->bQueued) ? 'queued' : 'accepted'; + } + + function canEdit() + { + if($this) + { + $oAppData = new appData($this->objectGetId(), null, $this); + return $oAppData->canEdit(); + } else + return appData::canEdit(); + } + + function mustBeQueued() + { + if($this) + { + $oAppData = new appData(); + $oAppData->iVersionId = $this->iVersionId; + $oAppData->iAppId = NULL; + return $oAppData->mustBeQueued(); + } else + return appData::mustBeQueued(); + } + + function objectGetTableRow() + { + $oAppData = new AppData($this->iScreenshotId, null, $this); + return $oAppData->objectGetTableRow(); + } + + function objectDisplayQueueProcessingHelp() + { + $shRet = "

    This is the list of screenshots waiting to be processed

    "; + $shRet .= "

    To view and process an entry, use the links under ‘Action’

    "; + return $shRet; + } + + function outputEditor() + { + $oAppData = new appData($this->iScreenshotId, null, $this); + $oAppData->outputEditorGeneric(); + + echo 'Submitted screenshot',"\n"; + echo ''; + $imgSRC = ''; + // generate random tag for popup window + $randName = User::generate_passwd(5); + // set image link based on user pref + $img = ''.$imgSRC.''; + if ($_SESSION['current']->isLoggedIn()) + { + if ($_SESSION['current']->getpref("window:screenshot") == "no") + { + $img = ''.$imgSRC.''; + } + } + echo $img; + echo '',"\n"; + echo ''; + echo html_frame_end(); + } + + function getOutputEditorValues($aClean) + { + $this->sDescription = $aClean['sDescription']; + } + + function update() + { + $oAppData = new appData($this->iScreenshotId, null, $this); + return $oAppData->update(); + } + + function objectHideDelete() + { + return TRUE; + } + + function getDefaultReply() + { + return appData::getDefaultReply(); + } + + function display() + { + /* STUB */ + return TRUE; + } + + function objectMakeLink() + { + /* STUB */ + return TRUE; + } + + function objectMakeUrl() + { + return APPDB_ROOT."appimage.php?iId={$this->iScreenshotId}"; + } + + function allowAnonymousSubmissions() + { + return FALSE; + } + + function objectGetId() + { + return $this->iScreenshotId; + } +} + +?> diff --git a/include/session.php b/include/session.php new file mode 100644 index 0000000..8966261 --- /dev/null +++ b/include/session.php @@ -0,0 +1,168 @@ +_server = $server; + + // set the session and cookie expiration time in days (default 30 days) + $this->_expire = (60 * 60 * 24 * $expire); + + // set name for this session + $this->name = $name; + + // define options for sessions + ini_set('session.name', $this->name); + ini_set('session.use_cookies', true); + ini_set('session.use_only_cookies', true); + + // setup session object + session_set_save_handler( + array(&$this, "_open"), + array(&$this, "_close"), + array(&$this, "_read"), + array(&$this, "_write"), + array(&$this, "_destroy"), + array(&$this, "_gc") + ); + + // default lifetime on session cookie + session_set_cookie_params( + $this->_expire, + '/' + ); + + // start the loaded session + session_start(); + + // make sure we have a valid memcache server connection + if (!$this->_db->getVersion()) + { + trigger_error("Unable to Connect to Session Server", E_USER_ERROR); + } + } + + // register variables into session (dynamic load and save of vars) + function register ($var) + { + global $$var; + + // load $var into memory + if (isset($_SESSION[$var])) + $$var = $_SESSION[$var]; + + // store var into session + $_SESSION[$var] =& $$var; + } + + // destroy session + function destroy () + { + session_destroy(); + } + + // add alert message to buffer that will be displayed on the Next page view of the same user in html class + function addmsg ($text, $color = "black") + { + if (!isset($_SESSION['_msg'])) + $_SESSION['_msg'] = array(); + $_SESSION['_msg'][] = array( + 'msg' => $text, + 'color' => $color + ); + } + + // add alert message that will be displayed on the current page output in html class + function alert ($text, $color = "black") + { + $this->msg[] = array( + 'msg' => $text, + 'color' => $color + ); + } + + // clear session messages + function purgemsg () + { + $this->msg[] = array(); + $_SESSION['_msg'][] = array(); + } + + // output msg_buffer and clear it. + function dumpmsgbuffer () + { + if (isset($_SESSION['_msg']) and is_array($_SESSION['_msg'])) + { + foreach ($_SESSION['_msg'] as $alert) + { + $this->msg[] = $alert; + } + } + $_SESSION['_msg'] = array(); + } + + // connect to session + function _open ($save_path, $session_name) + { + $this->_db = new Memcache; + return $this->_db->connect($this->_server, "11211"); + } + + // close the session + function _close () + { + return $this->_db->close(); + } + + // restore a session from memory + function _read ($id) + { + return $this->_db->get($id); + } + + // write the session + function _write ($id, $data) + { + if ($this->_db->get($id)) + { + $this->_db->replace($id, $data, null, $this->_expire); + } + else + { + $this->_db->set($id, $data, null, $this->_expire); + } + return true; + } + + // Delete the Session + function _destroy ($id) + { + return $this->_db->delete($id); + } + + // Garbage Collector (Not Needed for MemCache) + function _gc ($maxlifetime) + { + return true; + } + +} +// end session + +?> diff --git a/include/sidebar.php b/include/sidebar.php new file mode 100644 index 0000000..c115d9a --- /dev/null +++ b/include/sidebar.php @@ -0,0 +1,30 @@ +add('Home', BASE.'index.php'); + $g->add("Screenshots", BASE."objectManager.php?sClass=screenshot&sTitle=View+Screenshots"); + $g->add("Browse Apps", BASE."objectManager.php?sClass=application&". + 'sTitle=Browse%20Applications&sOrderBy=appName&bAscending=true'); + $g->add('Browse by Developer', BASE.'objectManager.php?sClass=vendor&sTitle=Browse%20by%20Developer'); + $g->add("Top 25", BASE."votestats.php"); + $g->add("Submit App", BASE."objectManager.php?sClass=application_queue&". + "sTitle=Submit+Application&sAction=add"); + $g->add("Help", BASE."help/"); + $g->add("Statistics", BASE."appdbStats.php"); + $g->add('Distributions ('.distribution::objectGetEntriesCount('accepted').')', BASE.'objectManager.php?sClass=distribution&sTitle=View%20Distributions'); + $g->add("Email Us", "mailto:appdb@winehq.org"); + $g->done(); + +} + +?> diff --git a/include/sidebar_admin.php b/include/sidebar_admin.php new file mode 100644 index 0000000..c06864e --- /dev/null +++ b/include/sidebar_admin.php @@ -0,0 +1,66 @@ +add("App Queue (".application::objectGetEntriesCount('queued').")", + BASE.'objectManager.php?sClass=application_queue&sState=queued&sTitle='. + 'Application%20Queue'); + $g->add("Version Queue (".version::objectGetEntriesCount('queued').")", + BASE.'objectManager.php?sClass=version_queue&sState=queued&sTitle='. + 'Version%20Queue'); + $g->add("Screenshot Queue (".appData::objectGetEntriesCount('queued', "screenshot").")", + BASE.'objectManager.php?sClass=screenshot&sState=queued&sTitle='. + 'Screenshot%20Queue'); + $g->add("Maintainer Queue (".Maintainer::objectGetEntriesCount('queued').")", + BASE.'objectManager.php?sClass=maintainer&sState=queued&sTitle='. + 'Maintainer%20Queue'); + $g->add("Test Results Queue (".testData::objectGetEntriesCount('queued').")", + BASE.'objectManager.php?sClass=testData_queue&sState=queued&sTitle='. + 'Test%20Results%20Queue'); + $g->add("Bug Link Queue (".bug::objectGetEntriesCount('queued').")", + BASE.'objectManager.php?sClass=bug&sState=queued&sTitle='. + 'Bug%20Link%20Queue'); + + $g->addmisc(" "); + + $g->add("Maintainer Entries (".Maintainer::objectGetEntriesCount('accepted').")", + BASE."admin/adminMaintainers.php"); + $g->add("Bug Links (".bug::objectGetEntriesCount('accepted').")", + BASE."objectManager.php?sClass=bug&sTitle=". + "Bug%20Links"); + $g->add("Test Results (".testData::objectGetEntriesCount('accepted').")", + BASE."objectManager.php?sClass=testData&sTitle=". + "View%20Test%20Results"); + $g->add("Users Management", BASE."admin/adminUsers.php"); + $g->add("Comments Management", BASE."admin/adminCommentView.php"); + $g->add("Screenshots Management", BASE."admin/adminScreenshots.php"); + + $g->addmisc(" "); + + $g->add("Rejected Applications (".application::objectGetEntriesCount('rejected').")", + BASE.'objectManager.php?sClass=application_queue&sState=rejected&'. + 'sTitle=Rejected%20Applications'); + $g->add("Rejected Versions (".version::objectGetEntriesCount('rejected').")", + BASE.'objectManager.php?sClass=version_queue&sState=rejected&'. + 'sTitle=Rejected%20Versions'); + $g->add("Rejected Test Results (".testData::objectGetEntriesCount('rejected').")", + BASE.'objectManager.php?sClass=testData_queue&sState=rejected&'. + 'sTitle=Rejected%20Test%20Results'); + + $g->addmisc(" "); + + $g->add("Add Category", BASE."objectManager.php?sClass=category&sAction=add&sTitle=Add+Category"); + $g->add("Add Vendor", BASE."objectManager.php?sClass=vendor&bQueue=". + "false&sAction=add&sTitle=Add%20Vendor"); + + $g->done(); +} + +?> diff --git a/include/sidebar_login.php b/include/sidebar_login.php new file mode 100644 index 0000000..719647a --- /dev/null +++ b/include/sidebar_login.php @@ -0,0 +1,102 @@ +isLoggedIn()) + { + + $g->add("Logout", BASE."account.php?sCmd=logout"); + $g->add("Preferences", BASE."preferences.php"); + + /* if this user maintains any applications list them */ + /* in their sidebar */ + $apps_user_maintains = Maintainer::getAppsMaintained($_SESSION['current']); + if($apps_user_maintains) + { + $g->add('Maintainership Overview', BASE.'objectManager.php?sClass=maintainerView&iId='. + $_SESSION['current']->iUserId.'&sTitle=Your+Maintained+Apps'); + + $g->addmisc(""); + $g->addmisc("You maintain:\n"); + + while(list($index, list($appId, $versionId, $superMaintainer)) = each($apps_user_maintains)) + { + $oApp = new application($appId); + if($superMaintainer) + $g->add($oApp->sName."*", $oApp->objectMakeUrl(),"center"); + else + { + $oVersion = new version($versionId); + $g->add(version::fullName($versionId), + $oVersion->objectMakeUrl(), "center"); + } + } + } + + /* Display the user's rejected applications */ + $iAppsRejected = application::objectGetEntriesCount('rejected'); + if($iAppsRejected && !$_SESSION['current']->hasPriv("admin")) + { + $g->add("Review Rejected Apps ($iAppsRejected)", BASE."objectManager.php?". + "sClass=application_queue&bIsQueue=true&bIsRejected=true&sTitle=". + "Rejected+Applications", "center"); + } + + /* Display the user's rejected versions */ + $iVersionsRejected = version::objectGetEntriesCount('rejected'); + if($iVersionsRejected && !$_SESSION['current']->hasPriv("admin")) + { + $g->add("Review Rejected Versions ($iVersionsRejected)", + BASE."objectManager.php?sClass=version_queue&bIsRejected=true". + "&bIsQueue=true&sTitle=Rejected+Versions", "center"); + } + + /* Display the user's rejected test results */ + $iTestDataRejected = testData::objectGetEntriesCount('rejected'); + if($iTestDataRejected && !$_SESSION['current']->hasPriv("admin")) + $g->add("Review Rejected Test Results ($iTestDataRejected)", + BASE."objectManager.php?sClass=testData_queue&". + "sAction=view&bIsQueue=true&bIsRejected=true&sTitle=". + "Rejected+Test+Results", "center"); + + $aMonitored = Monitor::getVersionsMonitored($_SESSION['current']); + if($aMonitored) + { + $g->addmisc(""); + $g->addmisc("You monitor:\n"); + + while(list($i, list($iAppId, $iVersionId)) = each($aMonitored)) + { + $oVersion = new version($iVersionId); + $g->add(version::fullName($iVersionId), $oVersion->objectMakeUrl(), "center"); + } + } + + /* Display a link to the user's queued items, + but not for admins, as theirs are auto-accepted */ + if(!$_SESSION['current']->hasPriv("admin")) + { + $g->addmisc(""); + $g->add("Your queued items", BASE."queueditems.php"); + } + + } else + { + $g->add("Log in", login_url()); + $g->add("Register", BASE."account.php?sCmd=new"); + } + + $g->done(); + +} +?> diff --git a/include/sidebar_maintainer_admin.php b/include/sidebar_maintainer_admin.php new file mode 100644 index 0000000..1e46085 --- /dev/null +++ b/include/sidebar_maintainer_admin.php @@ -0,0 +1,22 @@ +add('View Version Queue ('.version::objectGetEntriesCount('queued').')', + BASE.'objectManager.php?sClass=version_queue&sState=queued&sTitle='. + 'Version%20Queue'); + $g->add('View Screenshot Queue ('.screenshot::objectGetEntriesCount('queued').')', + BASE.'objectManager.php?sClass=screenshot&sState=queued&sTitle='. + 'Screenshot%20Queue'); + $g->add('View Test Results Queue ('.testData::objectGetEntriesCount('queued').')', + BASE.'objectManager.php?sClass=testData_queue&sState=queued&sTitle='. + 'Test%20Results%20Queue'); + $g->done(); +} + +?> diff --git a/include/table.php b/include/table.php new file mode 100644 index 0000000..362d605 --- /dev/null +++ b/include/table.php @@ -0,0 +1,580 @@ +oHighlightColor = $oHighlightColor; + $this->oInactiveColor = $oInactiveColor; + + $this->sTextDecorationHighlight = $sTextDecorationHighlight; + $this->sTextDecorationInactive = $sTextDecorationInactive; + } + + function GetHighlightColor() + { + return $this->oHighlightColor; + } + + function GetInactiveColor() + { + return $this->oInactiveColor; + } + + function GetTextDecorationHighlight() + { + return $this->sTextDecorationHighlight; + } + + function GetTextDecorationInactive() + { + return $this->sTextDecorationInactive; + } +} + +class TableRowClick +{ + var $oTableRowHighlight; + var $bHasHighlight; + var $shUrl; + + function TableRowClick($shUrl) + { + $this->shUrl = $shUrl; + $this->bHasHighlight = false; + $this->oTableRowHighlight = null; + } + + function SetHighlight(TableRowHighlight $oTableRowHighlight) + { + $this->oTableRowHighlight = $oTableRowHighlight; + } + + function GetString() + { + $sStr = ""; + + // if we have highlighting output the attributes necessary to enable the javascript tht we use + // to perform the highlighting actions + if($this->oTableRowHighlight) + { + $sStr.= 'onmouseover="ChangeTr(this, true,'. + '\''.$this->oTableRowHighlight->getHighlightColor()->GetHexString().'\','. + '\''.$this->oTableRowHighlight->getInactiveColor()->GetHexString().'\','. + '\''.$this->oTableRowHighlight->getTextDecorationHighlight().'\','. + '\''.$this->oTableRowHighlight->getTextDecorationInactive().'\');"'; + $sStr.= ' onmouseout="ChangeTr(this, false,'. + '\''.$this->oTableRowHighlight->getHighlightColor()->GetHexString().'\','. + '\''.$this->oTableRowHighlight->getInactiveColor()->GetHexString().'\','. + '\''.$this->oTableRowHighlight->getTextDecorationHighlight().'\','. + '\''.$this->oTableRowHighlight->getTextDecorationInactive().'\');"'; + } + + $sStr.= ' onclick="DoNav(\''.$this->shUrl.'\');"'; + + return $sStr; + } +} + +class TableCell +{ + private $sCell; + private $sStyle; + private $sClass; + private $sAlign; // align="$sAlign" will be output if this is not null + private $sValign; // valign="$sValign" will be output if this is not null + private $sWidth; // width="$sWidth" + private $sUrl; // wraps the cell contents in an anchor tag if $sUrl is not null + private $bBold; // if true will output the cell contents as bold + + // NOTE: We specifically have limited the parameters to the constructor + // to only the contents of the cell. Additional parameters, while + // appearing convienent, make the parameters confusing + // Use accessors to set additional parameters. + function TableCell($sCellContents) + { + $this->sCellContents = $sCellContents; + $this->sStyle = null; + $this->sClass = null; + $this->sAlign = null; + $this->sValign = null; + $this->sWidth = null; + $this->bBold = false; + } + + function SetCellContents($sCellContents) + { + $this->sCellContents = $sCellContents; + } + + function SetStyle($sStyle) + { + $this->sStyle = $sStyle; + } + + function SetClass($sClass) + { + $this->sClass = $sClass; + } + + function SetAlign($sAlign) + { + $this->sAlign = $sAlign; + } + + function SetValign($sValign) + { + $this->sValign = $sValign; + } + + function SetWidth($sWidth) + { + $this->sWidth = $sWidth; + } + + function SetCellLink($sUrl) + { + $this->sUrl = $sUrl; + } + + function SetBold($bBold) + { + $this->bBold = $bBold; + } + + function GetString() + { + $sStr = "sClass) + $sStr.=" class=\"".$this->sClass."\""; + + if($this->sStyle) + $sStr.=" style=\"".$this->sStyle."\""; + + if($this->sAlign) + $sStr.=" align=\"".$this->sAlign."\""; + + if($this->sValign) + $sStr.=" valign=\"".$this->sValign."\""; + + if($this->sWidth) + $sStr.=" width=\"".$this->sWidth."\""; + + $sStr.=">"; + + // if we have a url, output the start of the anchor tag + if($this->sUrl) + $sStr.=''; + + if($this->bBold) + $sStr.=''; + + // output the contents of the cell + $sStr.=$this->sCellContents; + + if($this->bBold) + $sStr.=''; + + // if we have a url, close the anchor tag + if($this->sUrl) + $sStr.=''; + + $sStr.=""; + + return $sStr; + } +} + +class TableRow +{ + protected $aTableCells; // array that contains the cells for the table row + private $sStyle; // CSS style to be used + private $sClass; // CSS class to be used + private $sValign; // valign="$sValign" - if this variable is set + + private $oTableRowClick; // information about whether the table row is clickable etc + + function TableRow() + { + $this->aTableCells = array(); + $this->sStyle = null; + $this->sClass = null; + $this->sValign = null; + $this->oTableRowClick = null; + } + + function AddCell(TableCell $oTableCell) + { + $this->aTableCells[] = $oTableCell; + } + + function AddCells($aTableCells) + { + foreach($aTableCells as $oTableCell) + { + $this->AddCell($oTableCell); + } + } + + function AddTextCell($sCellText) + { + $this->AddCell(new TableCell($sCellText)); + } + + function SetStyle($sStyle) + { + $this->sStyle = $sStyle; + } + + function SetClass($sClass) + { + $this->sClass = $sClass; + } + + function SetValign($sValign) + { + $this->sValign = $sValign; + } + + function SetRowClick($oTableRowClick) + { + $this->oTableRowClick = $oTableRowClick; + } + + // get a string that contains the html representation + // of this table row + function GetString() + { + // generate the opening of the tr element + $sStr = "sClass) + $sStr.= " class=\"$this->sClass\""; + + if($this->sStyle) + $sStr.= " style=\"$this->sStyle\""; + + if($this->sValign) + $sStr.= " valign=\"$this->sValign\""; + + if($this->oTableRowClick) + $sStr.= " ".$this->oTableRowClick->GetString(); + + $sStr.= ">"; // close the opening tr + + // process the td elements + foreach($this->aTableCells as $oTableCell) + { + $sStr.=$oTableCell->GetString(); + } + + // close the table row + $sStr.= ""; + + return $sStr; + } + + function GetClass() + { + return $this->sClass; + } + + function GetTableRowClick() + { + return $this->oTableRowClick; + } +} + +/* Class for a sortable table row. The user can click on the header for a sortable field, and it + will alternate between sorting that by ascending/descending order and the default sorting */ +class TableRowSortable extends TableRow +{ + private $aSortVars; /* Array of sort variables. Not all fields have to be sortable. + This is paired with the aTableCells array from TableRow */ + + function TableRowSortable() + { + $this->aSortVars = array(); + + $this->TableRow(); + } + + /* Adds a table cell without sorting */ + function AddTableCell(TableCell $oCell) + { + $this->aTableCells[] = $oCell; + $this->aSortVars[] = ''; + } + + /* Adds a text cell without sorting */ + function AddTextCell($shText) + { + $this->AddTableCell(new TableCell($shText)); + } + + /* Adds a text cell with a sorting var */ + function AddSortableTextCell($shText, $sSortVar) + { + $this->aTableCells[] = new TableCell($shText); + $this->aSortVars[] = $sSortVar; + } + + /* Sets sorting info on all cells that are sortable */ + function SetSortInfo(TableSortInfo $oSortInfo) + { + for($i = 0; $i < sizeof($this->aTableCells); $i++) + { + $sSortVar = $this->aSortVars[$i]; + + if($sSortVar) + { + $bAscending = TRUE; + + if($this->aSortVars[$i] == $oSortInfo->sCurrentSort) + { + if($oSortInfo->bAscending) + $bAscending = FALSE; + else + $sSortVar = ''; + + $this->aTableCells[$i]->sCellContents .= $oSortInfo->bAscending ? + ' ▲' : ' ▼'; + } + + $sAscending = $bAscending == TRUE ? 'true': 'false'; + $this->aTableCells[$i]->SetCellLink($oSortInfo->shUrl."sOrderBy=$sSortVar&bAscending=$sAscending"); + } + } + } +} + +/* Container for table sorting info, used to hold the current sort order */ +class TableSortInfo +{ + var $sCurrentSort; + var $bAscending; + var $shUrl; + + function TableSortInfo($shUrl, $sCurrentSort = '', $bAscending = TRUE) + { + $this->sCurrentSort = $sCurrentSort; + $this->shUrl = $shUrl; + $this->bAscending = $bAscending; + } + + /* Parses an array of HTTP vars to determine current sort settings. + Optionally checks the sort var against an array of legal values */ + function ParseArray($aClean, $aLegalValues = null) + { + $sCurrentSort = key_exists('sOrderBy', $aClean) ? $aClean['sOrderBy'] : ''; + + if($aLegalValues && array_search($sCurrentSort, $aLegalValues) === FALSE) + return; + + $this->sCurrentSort = $sCurrentSort; + $this->bAscending = key_exists('bAscending', $aClean) ? + ($aClean['bAscending'] == 'false') ? false : true : true; + } +} + +// object manager table row, has additional parameters used by the object manager +// when outputting a table row +//TODO: php5 consider inheriting from HtmlTableRow since this class is really an +// extension of that class +class OMTableRow +{ + private $oTableRow; + private $bHasDeleteLink; + private $bCanEdit; + + function OMTableRow($oTableRow) + { + $this->oTableRow = $oTableRow; + $this->bHasDeleteLink = false; + $this->bCanEdit = false; + } + + function SetHasDeleteLink($bHasDeleteLink) + { + $this->bHasDeleteLink = $bHasDeleteLink; + } + + function GetHasDeleteLink() + { + return $this->bHasDeleteLink; + } + + function SetRowClickable(TableRowClick $oTableRowClick) + { + $this->oTableRowClick = $oTableRowClick; + } + + function SetStyle($sStyle) + { + $this->oTableRow->SetStyle($sStyle); + } + + // add a TableCell to an existing row + function AddCell($oTableCell) + { + $this->oTableRow->AddCell($oTableCell); + } + + function GetString() + { + return $this->oTableRow->GetString(); + } + + function GetTableRow() + { + return $this->oTableRow; + } +} + +class Table +{ + private $oTableRowHeader; + private $aTableRows; + private $sClass; + private $sWidth; + private $iBorder; + private $sAlign; // align="$sAlign" - deprecated in html standards + private $iCellSpacing; // cellspacing="$iCellSpacing" + private $iCellPadding; // cellpadding="$iCellPadding" + + function Table() + { + $this->oTableRowHeader = null; + $this->aTableRows = array(); + $this->sClass = null; + $this->sWidth = null; + $this->iBorder = null; + $this->sAlign = null; + $this->iCellSpacing = null; + $this->iCellPadding = null; + } + + function AddRow($oTableRow) + { + $this->aTableRows[] = $oTableRow; + } + + function SetHeader(TableRow $oTableRowHeader) + { + $this->oTableRowHeader = $oTableRowHeader; + } + + function SetClass($sClass) + { + $this->sClass = $sClass; + } + + function SetWidth($sWidth) + { + $this->sWidth = $sWidth; + } + + function SetBorder($iBorder) + { + $this->iBorder = $iBorder; + } + + function SetAlign($sAlign) + { + $this->sAlign = $sAlign; + } + + function SetCellSpacing($iCellSpacing) + { + $this->iCellSpacing = $iCellSpacing; + } + + function SetCellPadding($iCellPadding) + { + $this->iCellPadding = $iCellPadding; + } + + function GetString() + { + $sStr = "sClass) + $sStr.= ' class="'.$this->sClass.'"'; + + if($this->sWidth) + $sStr.= ' width="'.$this->sWidth.'"'; + + if($this->iBorder !== null) + $sStr.= ' border="'.$this->iBorder.'"'; + + if($this->sAlign) + $sStr.= ' align="'.$this->sAlign.'"'; + + if($this->iCellSpacing !== null) + $sStr.= ' cellspacing="'.$this->iCellSpacing.'"'; + + if($this->iCellPadding !== null) + $sStr.= ' cellpadding="'.$this->iCellPadding.'"'; + + $sStr.= ">"; // close the open table element + + if($this->oTableRowHeader) + { + $sStr.=""; + $sStr.= $this->oTableRowHeader->GetString(); + $sStr.=""; + } + + foreach($this->aTableRows as $oTableRow) + { + $sStr.= $oTableRow->GetString(); + } + + $sStr.= ""; + + return $sStr; + } +} + +// input is the row index, we alternate colors based on odd or even index rows +// returns a TableRowHighlight instance +function GetStandardRowHighlight($iRowIndex) +{ + //set row color + $sColor = ($iRowIndex % 2) ? "color0" : "color1"; + + $oInactiveColor = new color(); + $oInactiveColor->SetColorByName($sColor); + + $oHighlightColor = GetHighlightColorFromInactiveColor($oInactiveColor); + + $oTableRowHighlight = new TableRowHighlight($oHighlightColor, $oInactiveColor); + + return $oTableRowHighlight; +} + +// returns a color class instance +function GetHighlightColorFromInactiveColor(color $oInactiveColor) +{ + $oHighlightColor = new color($oInactiveColor->iRed, + $oInactiveColor->iGreen, + $oInactiveColor->iBlue); + $oHighlightColor->Add(50); + + return $oHighlightColor; +} + +?> diff --git a/include/tableve.php b/include/tableve.php new file mode 100644 index 0000000..9a4e11a --- /dev/null +++ b/include/tableve.php @@ -0,0 +1,480 @@ +mode = $mode; + $this->titleField = ""; + $this->titleText = ""; + $this->numberedTitles = 0; + } + + function test($query) + { + $hResult = query_appdb($query); + $nfields = query_num_fields($hResult); + $nrows = query_num_rows($hResult); + $table = query_field_table($hResult, 0); + + echo "Table: $table
    Fields: $nfields
    Rows: $nrows

    \n"; + + $i = 0; + while($i < $nfields) + { + $type = query_field_type($hResult, $i); + $name = query_field_name($hResult, $i); + $len = query_field_len($hResult, $i); + $flags = query_field_flags($hResult, $i); + + echo "$type | $name | $len | $flags
    \n"; + $i++; + } + } + + /* this is a bit of a hack, + * we first create an empty entry, and then simply use the + * edit() function to do the rest of the work for us. + */ + function create($query, $table, $idcolumn) + { + $hResult = query_appdb($query); + $id = query_appdb_insert_id(); + + $new_query = "SELECT * FROM $table WHERE $idcolumn = $id"; + $this->edit($new_query); + } + + + function view($query) + { + //$this->test($query); + + $nrows = 0; + + $hResult = query_appdb($query); + $nrows = query_num_rows($hResult); + + if(debugging()) + { + echo "Query returns $nrows rows."; + } + + for($i = 0; $i < $nrows; $i++) + { + $this->view_entry($hResult, $i); + echo "
    \n"; + } + } + + function view_entry($hResult, $num) + { + $nfields = query_num_fields($hResult); + $fields = query_fetch_array($hResult, MYSQL_BOTH); + + $titleValue = $fields[$this->titleField]; + $titleText = $this->titleText; + if($this->numberedTitles) + { + // don't want zero-based. + $num++; + $titleText .= " # $num"; + } + + //echo "\n"; + //echo "\n"; + + //echo "'."\n"); + } + + // if this is a clickable row, set the appropriate property + if($oTableRowClick) + $oTableRow->SetRowClick($oTableRowClick); + + return $oTableRow; + } + + // Show the Test results for a application version + function ShowVersionsTestingTable($sLink, $iDisplayLimit) + { + global $aClean; + + /* escape input parameters */ + $sLink = query_escape_string($sLink); + $iDisplayLimit = query_escape_string($iDisplayLimit); + + $bShowAll = (getInput('bShowAll', $aClean) == 'true') ? true : false; + + $sQuery = "SELECT * + FROM testResults, ?.versions + WHERE versionId = '?' + AND + versions.value = testResults.testedRelease + AND + versions.product_id = '?' + AND + state = '?' + ORDER BY versions.id DESC,testedDate DESC"; + + if(!$bShowAll) + $sQuery.=" LIMIT 0,".$iDisplayLimit; + + $hResult = query_parameters($sQuery, BUGZILLA_DB, $this->iVersionId, BUGZILLA_PRODUCT_ID, 'accepted'); + if(!$hResult) + return; + + $rowsUsed = query_num_rows($hResult); + + if($rowsUsed == 0) + return; + + $oTable = $this->CreateTestTable(); + + $iIndex = 0; + while($oRow = query_fetch_object($hResult)) + { + $oTest = new testData($oRow->testingId); + $oTableRow = $oTest->CreateTestTableRow($this->iTestingId, $sLink, $bShowAll); + // add the row to the table + $oTable->AddRow($oTableRow); + + $iIndex++; + } + + echo $oTable->GetString(); + + echo '
    ',"\n"; // put a space after the test results table and the button + + echo ''."\n"; + + if($rowsUsed >= $iDisplayLimit && $bShowAll) + { + $sShowButtonText = "Limit to $iDisplayLimit tests"; + } else + { + $sShowButtonText = "Show all tests"; + echo ''; + } + + $oManager = new objectManager("version", null, $this->iVersionId); + + echo $oManager->makeUrlFormData(); + + echo "\t".''."\n"; + + echo ''."\n"; + + echo '',"\n"; // end of the 'info_contents' div + echo '',"\n"; // end of the 'info_container' div + } + + /* Convert a given rating string to a numeric scale */ + public function ratingToNumber($sRating) + { + switch($sRating) + { + case GARBAGE_RATING: + return 0; + case BRONZE_RATING: + return 1; + case SILVER_RATING: + return 2; + case GOLD_RATING: + return 3; + case PLATINUM_RATING: + return 4; + } + } + + /* Convert a numeric rating scale to a rating name */ + public function numberToRating($iNumber) + { + switch($iNumber) + { + case 0: + return GARBAGE_RATING; + case 1: + return BRONZE_RATING; + case 2: + return SILVER_RATING; + case 3: + return GOLD_RATING; + case 4: + return PLATINUM_RATING; + } + } + + /* Gets rating info for the selected version: an array with the elements + 0 - Rating + 1 - Wine version + The $sDate parameter can be used to calculate the rating at a given point in time */ + public function getRatingInfoForVersionId($iVersionId, $sDate = 'NOW()') + { + $sQuery = "SELECT testedRating,testedDate,testedRelease,versions.id as versionId + FROM testResults, ?.versions WHERE + versions.value = testResults.testedRelease + AND + versions.product_id = '?' + AND versionId = '?' + AND + state = '?' + AND + TO_DAYS(testedDate) > (TO_DAYS(?) - ?) + ORDER BY versions.id DESC,testedDate DESC"; + + $hResult = query_parameters($sQuery, BUGZILLA_DB, BUGZILLA_PRODUCT_ID, $iVersionId, 'accepted', $sDate, TESTDATA_AGED_THRESHOLD); + + $aEntries = array(); + + if($hResult) + { + $iPrevRelease = 0; + $iIndex = -1; + for($i = 0; $oRow = mysql_fetch_object($hResult); $i++) + { + if($iPrevRelease != $oRow->versionId) + { + $iIndex++; + $iPrevRelease = $oRow->versionId; + } + + if(!$aEntries[$iIndex]) + { + $aEntries[$iIndex] = array(); + $aEntries[$iIndex][0] = 0; + $aEntries[$iIndex][1] = 0; + $aEntries[$iIndex][2] = $oRow->testedRelease; + } + + $aEntries[$iIndex][0] += testData::RatingToNumber($oRow->testedRating); + $aEntries[$iIndex][1]++; + } + } + + $sRelease = ''; + + if(sizeof($aEntries)) + { + $fRating = 0.0; + + for($i = 0; $i < sizeof($aEntries); $i++) + { + /* Discard the rating if it's the only one for that Wine version + and its score is lower than previous averages */ + if(($aEntries[$i][1] < 2) && sizeof($aEntries) > ($i+1) && ($aEntries[$i][0] < ($aEntries[$i+1][0] / $aEntries[$i+1][1]))) + continue; + + $fRating = $aEntries[$i][0] / $aEntries[$i][1]; + $sRelease = $aEntries[$i][2]; + break; + } + + $sRating = testData::NumberToRating(round($fRating, 0)); + } + + if(!$sRelease) + { + $iNewestId = testData::getNewestTestIdFromVersionId($iVersionId); + $oTestData = new testData($iNewestId); + return array($oTestData->sTestedRating, $oTestData->sTestedRelease); + } + return array($sRating,$sRelease); + } + + /* retrieve the latest test result for a given version id */ + function getNewestTestIdFromVersionId($iVersionId, $sState = 'accepted') + { + $sQuery = "SELECT testingId FROM testResults, ?.versions WHERE + versions.value = testResults.testedRelease + AND + versions.product_id = '?' + AND + versionId = '?' + AND + state = '?' + ORDER BY versions.id DESC,testedDate DESC limit 1"; + + $hResult = query_parameters($sQuery, BUGZILLA_DB, BUGZILLA_PRODUCT_ID, $iVersionId, $sState); + + if(!$hResult) + return 0; + + if(!$oRow = query_fetch_object($hResult)) + return 0; + + return $oRow->testingId; + } + + // show the fields for editing + function outputEditor() + { + global $aClean; + + /* Fill in some values */ + if(!$this->iVersionId) + $this->iVersionId = $aClean['iVersionId']; + if(!$this->sTestedDate) + $this->sTestedDate = date('Y-m-d H:i:s'); + + HtmlAreaLoaderScript(array("Test1", "Test2", "Test3")); + + $sName = version::fullName($this->iVersionId); + + echo html_frame_start("Test Form - $sName", "90%", "", 0); + echo "
    \n"; + + echo html_frame_start("Viewing $titleValue $titleText","80%","",0); + echo "\n"; + + for($i = 0; $i < $nfields; $i++) + { + $field = query_fetch_field($hResult, $i); + + if(ereg("^impl_(.+)$", $field->table, $arr)) + { + if($cur_impl != $arr[1]) + echo "\n"; + $cur_impl = $arr[1]; + } + + echo ""; + echo "\n"; + } + + echo "
    ".ucfirst($arr[1])." Implementation
    $field->name "; + $this->view_entry_output_field($field, $fields[$i], 0); + echo "
    \n"; + echo html_frame_end(); + } + + + function edit($query) + { + $hResult = query_appdb($query); + $nrows = query_num_rows($hResult); + + echo "
    \n"; + + for($i = 0; $i < $nrows; $i++) + { + $this->edit_entry($hResult); + echo "
    \n"; + } + + echo html_frame_start("Update Database",100); + echo "\n"; + echo html_frame_end(); + + echo "
    \n"; + } + + + function edit_entry($hResult) + { + $nfields = query_num_fields($hResult); + $fields = query_fetch_array($hResult); + + echo html_frame_start(ucfirst($this->mode),"80%","",0); + echo "\n"; + + $cur_impl = null; + for($i = 0; $i < $nfields; $i++) + { + global $testvar; + $field = query_fetch_field($hResult, $i); + $len = query_field_len($hResult, $i); + + if(ereg("^impl_(.+)$", $field->table, $arr)) + { + if($cur_impl != $arr[1]) + echo "\n"; + $cur_impl = $arr[1]; + } + + echo ""; + echo "\n"; + } + + echo "
    ".ucfirst($arr[1])." Implementation
    $field->name    "; + $this->edit_entry_output_field($field, $fields[$i], $len); + echo "
    \n"; + echo html_frame_end(); + } + + // returns a string that contains the option list + function make_option_list($sVarname, $sCvalue, $sTable, $sIdField, $sNameField, $aWhere = null) + { + $sStr = ""; + + /* We do not allow direct insertion into of SQL code, so the WHERE clause is + is accepted in an array form, where the first element is the variable + and the second is the value it must be equal to */ + if($aWhere) + $sWhere = "WHERE ".$aWhere[0]." ='".$aWhere[1]."'"; + + $hResult = query_parameters("SELECT ?, ? FROM ? $sWhere ORDER BY ?", + $sIdField, $sNameField, $sTable, $sNameField); + if(!$hResult) + return $sStr; // Oops + + $sStr.= "\n"; + + return $sStr; + } + + + function edit_entry_output_field($field, $value, $len) + { + static $idx = 0; + + $idx++; + if($len > 50) + $len = 50; + + $varname = "FIELD_".$field->table."___".$field->name."[]"; + echo "\n"; + + if($field->name == "appId" && $field->table != "appFamily") + { + echo $this->make_option_list($varname, $value, "appFamily", "appId", "appName"); + return; + } + + if($field->name == "vendorId" && $field->table != "vendor") + { + echo $this->make_option_list($varname, $value, "vendor", "vendorId", "vendorName"); + return; + } + + if($field->name == "catId" && $field->table != "appCategory") + { + echo $this->make_option_list($varname, $value, "appCategory", "catId", "catName"); + return; + } + + if($field->name == "catParent") + { + echo $this->make_option_list($varname, $value, "appCategory", "catId", "catName"); + return; + } + + if($field->name == "keywords") + { + echo "\n"; + return; + } + + switch($field->type) + { + case "string": + case "enum": + case "int": + case "text": + echo "\n"; + break; + case "blob": + echo "\n"; + break; + case "timestamp": + $time = mysqltimestamp_to_unixtimestamp($value); + echo print_date($time); + break; + case "datetime": + $time = mysqldatetime_to_unixtimestamp($value); + echo print_date($time); + break; + default: + echo "$value  \n"; + break; + } + + $this->entry_add_extra($field, $value); + } + + function view_entry_output_field($field, $value, $len) + { + if($len > 50) + $len = 50; + + //FIXME: need a better way for special cases + if(!$value && $field->name == "comments") + { + echo "none"; + return; + } + if(!$value && ($field->name == "location" || $field->name == "quality")) + { + echo "unknown"; + return; + } + + if($field->name == "lastmodby") + { + $user = new User(); + $name = $user->lookup_realname($value); + if(!$name) + $name = "system"; + echo "$name ($value)"; + return; + } + + switch($field->type) + { + case "string": + case "enum": + case "int": + case "blob": + echo "$value  \n"; + break; + case "timestamp": + $time = mysqltimestamp_to_unixtimestamp($value); + echo print_date($time); + break; + case "datetime": + $time = mysqldatetime_to_unixtimestamp($value); + echo print_date($time); + break; + default: + echo "$value  \n"; + break; + } + + $this->entry_add_extra($field, $value); + } + + + /* + * add extra stuff to certain fields + */ + function entry_add_extra($field, $value) + { + /* + * add extra stuff to certain fields + */ + + if($field->name == "mslink" && $value) + { + echo html_imagebutton("Go!", $value); + } + + if($field->name == "apiname") + { + echo html_imagebutton("Wine LXR", "http://twine.codeweavers.com/lxr/ident?i=$value"); + echo html_imagebutton("Wine API", "http://www.winehq.com/WineAPI/$value.html"); + } + } + + + /* + * required field for each table. + * When editing a query this field needs to be present in the query + * in order to identify the correct row to update. + */ + var $table_ids = array( + "user_list" => "userid", + "appFamily" => "appId", + "appVersion" => "versionId", + "userExperience" => "uExpId", + "appCategory" => "catId", + "vendor" => "vendorId", + "appNotes" => "noteId" + ); + + function get_id($name) + { + reset($this->table_ids); + while(list($table, $id) = each($this->table_ids)) + { + $r = "^$table$"; + //echo "Checking $r against $name
    \n"; + if(ereg($r, $name)) + { + //echo "ID for $name -> $id
    \n"; + return $id; + } + } + return null; + } + + /** + * update() expects $_POST as argument + * this is where things are getting kinda complex, here we update " + * multiple entries with multiple fields in multiple tables (get it?) + */ + function update($vars) + { + $tables = array(); + $fieldnames = array(); + $num_entries = 0; + + while(list($varname, $arr) = each($vars)) + { + if(!ereg("^FIELD_([a-zA-Z_]+)___(.+)$", $varname, $regs)) + continue; + + $tables[$regs[1]][] = $regs[2]; + $fieldnames[$regs[2]] = $arr; + $num_entries = sizeof($arr); + } + + while(list($table, $fields) = each($tables)) + { + echo " $table (".$this->get_id($table).") "; + + if($fieldnames[$this->get_id($table)]) + echo "OK!"; + + echo "
    \n"; + + for($i = 0; $i < sizeof($fields); $i++) + echo "- $fields[$i]
    \n"; + + echo "
    \n"; + } + + for($i = 0; $i < $num_entries; $i++) + { + reset($tables); + while(list($table, $fields) = each($tables)) + { + $update = "UPDATE $table SET "; + + $count = sizeof($fields); + reset($fields); + while(list($idx, $field) = each($fields)) + { + $count--; + + if($this->table_ids[$table] == $field) + { + continue; + } + $key = "FIELD_".$table."___".$field; + $type = $vars["TYPE_$key"][$i]; + + if($type == "int") + $update .= "$field = ".$vars[$key][$i]; + else + $update .= "$field = '".addslashes($vars[$key][$i])."'"; + + if($count) + $update .= ", "; + } + + $value = $fieldnames[$this->get_id($table)][$i]; + + $update .= " WHERE ".$this->get_id($table)." = $value"; + + if(query_appdb($update)) + { + addmsg("Database Operation Complete!","green"); + } + + if(ereg("^impl_.+$", $table)) + { + $value = $fieldnames["apiid"][$i]; + query_parameters("UPDATE ? SET lastmodby = '?' WHERE apiid = '?'", + $table, $_SESSION['current']->iUserId, $value); + } + } + } + } + + function set_title_field($newTitleField) + { + $this->titleField = $newTitleField; + } + + function set_title_text($newTitleText) + { + $this->titleText = $newTitleText; + } + + function set_numbered_titles() + { + $this->numberedTitles = 1; + } +}; + +?> diff --git a/include/testData.php b/include/testData.php new file mode 100644 index 0000000..33661b1 --- /dev/null +++ b/include/testData.php @@ -0,0 +1,1517 @@ +iTestingId = $oRow->testingId; + $this->iVersionId = $oRow->versionId; + $this->shWhatWorks = $oRow->whatWorks; + $this->shWhatDoesnt = $oRow->whatDoesnt; + $this->shWhatNotTested = $oRow->whatNotTested; + $this->sTestedDate = $oRow->testedDate; + $this->iDistributionId = $oRow->distributionId; + $this->sTestedRelease = $oRow->testedRelease; + $this->sInstalls = $oRow->installs; + $this->sRuns = $oRow->runs; + $this->sTestedRating = $oRow->testedRating; + $this->sComments = $oRow->comments; + $this->sSubmitTime = $oRow->submitTime; + $this->iSubmitterId = $oRow->submitterId; + $this->sState = $oRow->state; + } + } + + // Creates a new Test Results. + function create() + { + $oVersion = new version($this->iVersionId); + if($oVersion->objectGetState() != 'accepted') + $this->sState = 'pending'; + else + $this->sState = $this->mustBeQueued() ? 'queued' : 'accepted'; + + $hResult = query_parameters("INSERT INTO testResults (versionId, whatWorks, whatDoesnt,". + "whatNotTested, testedDate, distributionId, testedRelease,". + "installs, runs, testedRating, comments,". + "submitTime, submitterId, state)". + "VALUES('?', '?', '?', '?', '?', '?', '?',". + "'?', '?', '?', '?',". + "?, '?', '?')", + $this->iVersionId, $this->shWhatWorks, + $this->shWhatDoesnt, + $this->shWhatNotTested, $this->sTestedDate, + $this->iDistributionId, + $this->sTestedRelease, $this->sInstalls, + $this->sRuns, + $this->sTestedRating, $this->sComments, + "NOW()", + $_SESSION['current']->iUserId, + $this->sState); + + if($hResult) + { + $this->iTestingId = query_appdb_insert_id(); + $this->testData($this->iTestingId); + $this->SendNotificationMail(); + + if($this->sState == 'accepted') + $oVersion->updateRatingInfo(); + return true; + } + else + { + addmsg("Error while creating test results.", "red"); + return false; + } + } + + // Update Test Results. + function update($bSilent=false) + { + // is the current user allowed to update this test result? + $oVersion = new Version($this->iVersionId); + if(!$_SESSION['current']->hasPriv("admin") && + !$_SESSION['current']->hasAppVersionModifyPermission($oVersion) && + !(($_SESSION['current']->iUserId == $this->iSubmitterId) && $this->sState != 'accepted')) + { + return; + } + + $oOldTest = new testData($this->iTestingId); + /* Nothing changed */ + if($this == $oOldTest) + return TRUE; + + /* Provide some feedback as to what was changed. Not all fields are + interesting */ + $sWhatChanged = ""; + if($this->shWhatWorks != $oOldTest->shWhatWorks) + { + $sWhatChanged .= "What works was changed from\n'$oOldTest->shWhatWorks'\n". + "to\n'$this->shWhatWorks'.\n"; + } + + if($this->shWhatDoesnt != $oOldTest->shWhatDoesnt) + { + $sWhatChanged .= "What does not work was changed from\n'" + .$oOldTest->shWhatDoesnt."'\n to\n'$this->shWhatDoesnt'.\n"; + } + + if($this->shWhatNotTested != $oOldTest->shWhatNotTested) + { + $sWhatChanged .= "What was not tested was changed from\n'". + $oOldTest->shWhatNotTested."'\nto\n'$this->shWhatNotTested'.\n"; + } + + if($this->sComments != $oOldTest->sComments) + { + $sWhatChanged .= "Extra comments was changed from\n'". + $oOldTest->sComments."'\nto\n'$this->sComments'.\n"; + } + + if($this->iDistributionId != $oOldTest->iDistributionId) + { + $oNewDist = new distribution($this->iDistributionId); + $oOldDist = new distribution($oOldTest->iDistributionId); + $sWhatChanged .= "Distribution was changed from $oOldDist->sName ". + "to $oNewDist->sName.\n"; + } + + if($this->sInstalls != $oOldTest->sInstalls) + { + $sWhatChanged .= "Installs? was changed from $oOldTest->sInstalls to ". + "$this->sInstalls.\n"; + } + + if($this->sRuns != $oOldTest->sRuns) + { + $sWhatChanged .= "Runs? was changed from $oOldTest->sRuns to ". + "$this->sRuns.\n"; + } + + $bUpdateRatingInfo = false; + if($this->sTestedRating != $oOldTest->sTestedRating) + { + $bUpdateRatingInfo = true; + $sWhatChanged .= "Rating was changed from $oOldTest->sTestedRating ". + "to $this->sTestedRating.\n"; + } + + if($this->sTestedRelease != $oOldTest->sTestedRelease) + { + $bUpdateRatingInfo = true; + $sWhatChanged .= "Tested release was changed from ". + $oOldTest->sTestedRelease." to $this->sTestedRelease.\n"; + } + + if($this->iVersionId != $oOldTest->iVersionId) + { + $sWhatChanged .= 'Moved from '.version::fullName($oOldTest->iVersionId).' to '.version::fullName($this->iVersionId)."\n"; + $oNewVersion = new version($this->iVersionId); + if($oNewVersion->objectGetState() == 'accepted' && $this->sState == 'pending') + $this->sState = 'queued'; + + $bUpdateRatingInfo = true; + } + + if(query_parameters("UPDATE testResults SET + versionId = '?', + whatWorks = '?', + whatDoesnt = '?', + whatNotTested = '?', + testedDate = '?', + distributionId = '?', + testedRelease = '?', + installs = '?', + runs = '?', + testedRating = '?', + comments = '?', + state = '?' + WHERE testingId = '?'", + $this->iVersionId, + $this->shWhatWorks, + $this->shWhatDoesnt, + $this->shWhatNotTested, + $this->sTestedDate, + $this->iDistributionId, + $this->sTestedRelease, + $this->sInstalls, + $this->sRuns, + $this->sTestedRating, + $this->sComments, + $this->sState, + $this->iTestingId)) + { + if($bUpdateRatingInfo && $this->sState == 'accepted') + { + if($this->iVersionId != $oOldTest->iVersionId) + { + $oNewVersion = new version($this->iVersionId); + $oNewVersion->updateRatingInfo(); + } + $oVersion->updateRatingInfo(); + } + + if(!$bSilent) + $this->SendNotificationMail("edit", $sWhatChanged); + return true; + } + else + { + addmsg("Error while updating test results", "red"); + return false; + } + } + + // Purge test results from the database + function purge() + { + // is the current user allowed to delete this test result? + $oVersion = new Version($this->iVersionId); + if(!$_SESSION['current']->hasPriv("admin") && + !$_SESSION['current']->hasAppVersionModifyPermission($oVersion) && + !(($_SESSION['current']->iUserId == $this->iSubmitterId) && !($this->sState == 'accepted'))) + { + return false; + } + + // now we delete the data + $sQuery = "DELETE FROM testResults + WHERE testingId = '?' + LIMIT 1"; + if(!($hResult = query_parameters($sQuery, $this->iTestingId))) + return false; + + return true; + } + + // Delete test results. + function delete() + { + // is the current user allowed to delete this test result? + $oVersion = new Version($this->iVersionId); + if(!$_SESSION['current']->hasPriv("admin") && + !$_SESSION['current']->hasAppVersionModifyPermission($oVersion) && + !(($_SESSION['current']->iUserId == $this->iSubmitterId) && $this->sState != 'accepted')) + { + return false; + } + + // now we flag the data as deleted + $sQuery = "UPDATE testResults SET state = 'deleted' + WHERE testingId = '?' + LIMIT 1"; + if(!($hResult = query_parameters($sQuery, $this->iTestingId))) + { + addmsg("Error removing the deleted test data!", "red"); + return false; + } + + if($this->sState == 'accepted') + $oVersion->updateRatingInfo(); + + return true; + } + + + // Move Test Data out of the queue. + function unQueue() + { + // is the current user allowed to delete this test data? + $oVersion = new Version($this->iVersionId); + if(!$_SESSION['current']->hasPriv("admin") && + !$_SESSION['current']->hasAppVersionModifyPermission($oVersion)) + { + return false; + } + + // If we are not in the queue, we can't move the test data out of the queue. + if($this->sState == 'accepted') + return false; + + if(query_parameters("UPDATE testResults SET state = '?' WHERE testingId = '?'", + 'accepted', $this->iTestingId)) + { + $this->sState = 'accepted'; + // we send an e-mail to interested people + $this->mailSubmitter("add"); + $this->SendNotificationMail(); + } else + { + return false; + } + + $oVersion->updateRatingInfo(); + + return true; + } + + function Reject() + { + // is the current user allowed to delete this test data? + $oVersion = new Version($this->iVersionId); + if(!$_SESSION['current']->hasPriv("admin") && + !$_SESSION['current']->hasAppVersionModifyPermission($oVersion)) + { + return; + } + + // If we are not in the queue, we can't move the version out of the queue. + if($this->sState != 'queued') + return false; + + if(query_parameters("UPDATE testResults SET state = '?' WHERE testingId = '?'", + 'rejected', $this->iTestingId)) + { + $this->sState = 'rejected'; + // we send an e-mail to interested people + $this->mailSubmitter("reject"); + $this->SendNotificationMail("reject"); + } + } + + function ReQueue() + { + // is the current user allowed to requeue this data + $oVersion = new Version($this->iVersionId); + if(!$_SESSION['current']->hasPriv("admin") && + !$_SESSION['current']->hasAppVersionModifyPermission($oVersion) && + !$_SESSION['current']->iUserId == $this->iSubmitterId) + { + return; + } + + if(query_parameters("UPDATE testResults SET state = '?' WHERE testingId = '?'", + 'queued', $this->iTestingId)) + { + $this->sState = 'queued'; + // we send an e-mail to interested people + $this->SendNotificationMail(); + } + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + $oOptions = new mailOptions(); + + if($sAction == "delete" && $bParentAction) + $oOptions->bMailOnce = TRUE; + + return $oOptions; + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + $oSubmitter = new User($this->iSubmitterId); + $sName = version::fullName($this->iVersionId); + + $sMsg = null; + $sSubject = null; + + if($bMailSubmitter) + { + switch($sAction) + { + case "delete": + $sSubject = "Submitted test data deleted"; + if($bParentAction) + { + $sMsg = "All test data you submitted for '$sName' has ". + "been deleted because '$sName' was deleted."; + } else + { + $sMsg = "The test report you submitted for '$sName' has ". + "been deleted."; + } + break; + } + $aMailTo = nulL; + } else + { + switch($sAction) + { + case "delete": + if(!$bParentAction) + { + $sSubject = "Test Results deleted for $sName by ". + $_SESSION['current']->sRealname; + $sMsg = ""; + } + break; + } + $aMailTo = User::get_notify_email_address_list(null, $this->iVersionId); + } + return array($sSubject, $sMsg, $aMailTo); + } + + function mailSubmitter($sAction="add") + { + global $aClean; + + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + + /* Get the full app/version name to display */ + $sName = version::fullName($this->iVersionId); + + $oVersion = new version($this->iVersionId); + + switch($sAction) + { + case "add": + $sSubject = "Submitted test data accepted"; + $sMsg = "The test data you submitted for '$sName' has been ". + "accepted by ".$_SESSION['current']->sRealname.".\n"; + $sMsg .= $oVersion->objectMakeUrl()."&iTestingId=".$this->iTestingId."\n"; + $sMsg .= "Administrators response:\n"; + break; + case "reject": + $sSubject = "Submitted test data rejected"; + $sMsg = "The test data you submitted for '$sName' has ". + "been rejected by ".$_SESSION['current']->sRealname."."; + $sMsg .= $this->objectMakeUrl()."\n"; + $sMsg .= "Reason given:\n"; + break; + } + $sMsg .= $aClean['sReplyText']."\n"; + $sMsg .= "We appreciate your help in making the Application ". + "Database better for all users."; + + mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg); + } + } + + + function SendNotificationMail($sAction="add",$sMsg=null) + { + global $aClean; + + $oVersion = new Version($this->iVersionId); + $oApp = new Application($oVersion->iAppId); + $sBacklink = $oVersion->objectMakeUrl()."&iTestingId=".$this->iTestingId."\n"; + + switch($sAction) + { + case "add": + if($this->sState == 'accepted') + { + $sSubject = "Test Results added to version ".$oVersion->sName." of ".$oApp->sName." by ".$_SESSION['current']->sRealname; + $sMsg .= $sBacklink; + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + $sMsg .= "This Test data has been submitted by ".$oSubmitter->sRealname."."; + $sMsg .= "\n"; + } + if($aClean['sReplyText']) + { + $sMsg .= "Appdb admin reply text:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + addmsg("The test data was successfully added into the database.", "green"); + } else // test data queued. + { + $sSubject = "Test Results submitted for version ".$oVersion->sName." of ".$oApp->sName." by ".$_SESSION['current']->sRealname; + $sMsg .= $sBacklink; + $sMsg .= "This test data has been queued."; + $sMsg .= "\n"; + addmsg("The test data you submitted will be added to the database after being reviewed.", "green"); + } + break; + case "edit": + $sSubject = "Test Results modified for version ".$oVersion->sName." of ".$oApp->sName." by ".$_SESSION['current']->sRealname; + $sMsg .= $sBacklink; + break; + case "reject": + $sSubject = "Test Results rejected for version ".$oVersion->sName." of ".$oApp->sName." by ".$_SESSION['current']->sRealname; + $sMsg .= $sBacklink; + // if replyText is set we should report the reason the data was rejected + if($aClean['sReplyText']) + { + $sMsg .= "Reason given:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + addmsg("test data rejected.", "green"); + break; + } + $sEmail = User::get_notify_email_address_list(null, $this->iVersionId); + if($sEmail) + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + function ShowTestResult() + { + echo '

    What works
    ',"\n"; + echo $this->shWhatWorks,"\n"; + echo '


    What does not
    ',"\n"; + echo $this->shWhatDoesnt,"\n"; + echo '


    What was not tested
    ',"\n"; + echo $this->shWhatNotTested,"\n"; + echo '


    Additional Comments

    ',"\n";
    +        echo $this->sComments,"\n";
    +        echo '
    ',"\n"; + } + + function CreateTestTable() + { + echo '
    ',"\n"; + echo '
    Test Results
    ',"\n"; + echo '
    ',"\n"; + + // create the table + $oTable = new Table(); + $oTable->SetClass("historyTable"); + $oTable->SetBorder(1); + $oTable->SetWidth("100%"); + + // setup the table header + $oTableRowHeader = new TableRow(); + $oTableRowHeader->SetClass("historyHeader"); + $oTableRowHeader->AddTextCell(""); + $oTableRowHeader->AddTextCell("Distribution"); + $oTableRowHeader->AddTextCell("Test date"); + $oTableRowHeader->AddTextCell("Wine version"); + $oTableRowHeader->AddTextCell("Installs?"); + $oTableRowHeader->AddTextCell("Runs?"); + $oTableRowHeader->AddTextCell("Rating"); + $oTableRowHeader->AddTextCell("Submitter"); + $oTable->SetHeader($oTableRowHeader); + + return $oTable; + } + + /* Creates and returns a table row for a test result table */ + function CreateTestTableRow($iCurrentId, $sLink, $bShowAll = false) + { + $oVersion = new Version($this->iVersionId); + $oApp = new Application($oVersion->iAppId); + $oSubmitter = new User($this->iSubmitterId); + $oDistribution = new distribution($this->iDistributionId); + $bgcolor = $this->sTestedRating; + + // initialize the array ech time we loop + $oTableRowClick = null; + + $oTableRow = new TableRow(); + + /* if the test we are displaying is this test then */ + /* mark it as the current test */ + if ($this->iTestingId == $iCurrentId) + { + $sTRClass = $bgcolor; + + $oTableCell = new TableCell("Current"); + $oTableCell->SetAlign("center"); + } else /* make all non-current rows clickable so clicking on them selects the test as current */ + { + $sTRClass = $bgcolor; + + $oInactiveColor = new color(); + $oInactiveColor->SetColorByName($this->sTestedRating); + + $oHighlightColor = GetHighlightColorFromInactiveColor($oInactiveColor); + + $oTableRowHighlight = new TableRowHighlight($oHighlightColor, $oInactiveColor); + + $sUrl = $sLink.$this->iTestingId; + + if($bShowAll) + $sUrl .= '&bShowAll=true'; + + $oTableRowClick = new TableRowClick($sUrl); + $oTableRowClick->SetHighlight($oTableRowHighlight); + + // add the table element indicating that the user can show the row by clicking on it + $oTableCell = new TableCell("Show"); + $oTableCell->SetCellLink($sUrl); + $oTableCell->SetAlign("center"); + } + + $oTableRow->AddCell($oTableCell); + $oTableRow->SetClass($sTRClass); + + $oTableRow->AddTextCell($oDistribution->objectMakeLink()); + $oTableRow->AddTextCell(date("M d Y", mysqldatetime_to_unixtimestamp($this->sTestedDate))); + $oTableRow->AddTextCell($this->sTestedRelease.' '); + $oTableRow->AddTextCell($this->sInstalls.' '); + $oTableRow->AddTextCell($this->sRuns.' '); + $oTableRow->AddTextCell($this->sTestedRating.' '); + $oTableRow->AddTextCell($oSubmitter->objectMakeLink().' '); + if ($this->iTestingId && $_SESSION['current']->hasAppVersionModifyPermission($oVersion)) + { + $oObject = new objectManager('testData'); + if($oApp->canEdit()) + $shChangeParentLink = 'Move'."\n"; + else + $shChangeParentLink = ''; + + $oTableRow->AddTextCell(''. + 'Edit   '."\n". + $shChangeParentLink. + 'Delete
    \n"; + + // What works + echo '',"\n"; + echo '',"\n"; + // What Does not work + echo '',"\n"; + echo '',"\n"; + // What was not tested + echo '',"\n"; + echo '',"\n"; + // Date Tested + echo '',"\n"; + echo '',"\n"; + echo '',"\n"; + + // Distribution + $oDistribution = new distribution($this->iDistributionId); + $sDistributionHelp = ""; + if(!$this->iDistributionId || $oDistribution->objectGetState() != 'accepted') + { + if(!$this->iDistributionId) + { + $sDistributionHelp = "If yours is not on the list, ". + "please add it using the form below."; + } else + { + $sDistributionHelp = "The user added a new distribution; "; + "review it in the form below or replace ". + "it with one from the list."; + } + $sDistributionHelp .= "
    \n"; + } + + echo '',"\n"; + + echo '',"\n"; + + // Version List + echo '',"\n"; + + // Installs + echo '',"\n"; + // Runs + echo '',"\n"; + // Rating + echo '',"\n"; + // extra comments + echo '',"\n"; + echo '',"\n"; + + echo ''; + echo ''; + echo ''; + + // Display confirmation box for changing the Wine version + $oOldTest = new testData($this->iTestingId); + if($this->iTestingId && $oOldTest->sTestedRelease != $this->sTestedRelease) + { + if(getInput('bConfirmTestedVersionChange', $aClean) != 'true') + { + echo ''; + } else + { + echo ''; + } + } + + echo "
    What works

    What does not work

    What was not tested

    Date tested

    YYYY-MM-DD HH:MM:SS

    Distribution',"\n"; + echo $sDistributionHelp; + distribution::make_distribution_list("iDistributionId", $this->iDistributionId); + echo '
    Tested release',"\n"; + echo make_bugzilla_version_list("sTestedRelease", $this->sTestedRelease); + // Give the user some information about our available versions + echo "Version not listed? Your Wine is too old, upgrade!"; + echo '
    Installs?',"\n"; + testData::make_Installs_list("sInstalls", $this->sInstalls); + echo '  Installing is an important part of testing under Wine. Select N/A if there is no installer.
    Runs?',"\n"; + testData::make_Runs_list("sRuns", $this->sRuns); + echo '
    Rating',"\n"; + echo make_maintainer_rating_list("sTestedRating", $this->sTestedRating); + echo 'Rating definitions
    Extra comments
     '; + echo 'You have changed the Wine version of the report. Are you sure you want to do this? Please submit a new test report for every Wine version you test; this is useful for tracking Wine\'s progress.
    '; + echo ' '; + echo 'Yes, I want to change the Wine version'; + echo '
    \n"; + + echo html_frame_end(); + } + + /* $aValues can be $aValues or any array with the values from outputEditor() */ + function CheckOutputEditorInput($aValues, $sDistribution="") + { + $errors = ""; + if (empty($aValues['shWhatWorks'])) + $errors .= "
  • Please enter what worked.
  • \n"; + + /* The 'what doesn't work' field can be empty if the rating is Platinum, + because then an app should run flawlessly */ + if (!getInput('shWhatDoesnt', $aValues) && + getInput('sTestedRating', $aValues) != PLATINUM_RATING) + $errors .= "
  • Please enter what did not work.
  • \n"; + + if (empty($aValues['shWhatNotTested'])) + $errors .= "
  • Please enter what was not tested.
  • \n"; + + if (empty($aValues['sTestedDate'])) + $errors .= "
  • Please enter the date and time when you tested.
  • \n"; + + if (empty($aValues['sTestedRelease'])) + $errors .= "
  • Please enter the version of Wine that you tested with.
  • \n"; + + // Ask for confirmation if changing the tested Wine versions, becase we want users + // to submit new reports instead of updating existing ones when testing new Wines + $oOldTest = new testData($this->iTestingId); + if($this->iTestingId && $oOldTest->sTestedRelease != getInput('sTestedRelease', $aValues) && + getInput('bConfirmTestedVersionChange', $aValues) != 'true') + { + $errors .= '
  • Are you sure you want to change the Wine version of the report? Please submit a new '. + 'test report for every Wine version you test; this is useful for tracking Wine\'s progress. '. + 'Tick the box above the submit button if you want to proceed
  • '; + } + + // No Distribution entered, and nothing in the list is selected + if (empty($aValues['sDistribution']) && !$aValues['iDistributionId']) + $errors .= "
  • Please enter a distribution.
  • \n"; + + if (empty($aValues['sInstalls'])) + $errors .= "
  • Please enter whether this application installs or not.
  • \n"; + + if (empty($aValues['sRuns'])) + $errors .= "
  • Please enter whether this application runs or not.
  • \n"; + + if (empty($aValues['sTestedRating'])) + $errors .= "
  • Please enter a rating based on how well this application runs.
  • \n"; + + // Basic checking of rating logic to ensure that the users test results + // are consistent + if (($aValues['sRuns'] != "Yes") && ($aValues['sTestedRating'] != GARBAGE_RATING)) + $errors .= "
  • Applications that do not run should be rated ‘Garbage’.
  • \n"; + + if (($aValues['sInstalls'] == "No") && ($aValues['sTestedRating'] == PLATINUM_RATING)) + $errors .= "
  • An application can only get a Platinum rating if it installs and runs ‘out of the box’.
  • \n"; + + // Basic checking of logic. Runs? can obviously only be 'Not Installable' + // if the application does not install + if (($aValues['sInstalls'] != "No") && ($aValues['sRuns'] == "Not installable")) + $errors .= "
  • You can only set Runs? to ‘Not installable’ if the application's installer does not work
  • \n"; + + if (($aValues['sInstalls'] == "No") && ($aValues['sRuns'] != "Not installable")) + $errors .= "
  • You can only set Runs? to ‘Not installable’' if the application's installer does not work
  • \n"; + + return $errors; + + } + + /* retrieves values from $aValues that were output by outputEditor() */ + /* $aValues can be $_REQUEST or any array with the values from outputEditor() */ + function GetOutputEditorValues($aValues) + { + if($aValues['iTestingId']) + $this->iTestingId = $aValues['iTestingId']; + + if($aValues['iVersionId']) + $this->iVersionId = $aValues['iVersionId']; + + $this->shWhatWorks = $aValues['shWhatWorks']; + $this->shWhatDoesnt = $aValues['shWhatDoesnt']; + $this->shWhatNotTested = $aValues['shWhatNotTested']; + $this->sTestedDate = $aValues['sTestedDate']; + $this->iDistributionId = $aValues['iDistributionId']; + $this->sTestedRelease = $aValues['sTestedRelease']; + $this->sInstalls = $aValues['sInstalls']; + $this->sRuns = $aValues['sRuns']; + $this->sTestedRating = $aValues['sTestedRating']; + $this->sComments = $aValues['sComments']; + } + + function make_Installs_list($sVarname, $sSelectedValue) + { + echo "\n"; + } + + function make_Runs_list($sVarname, $sSelectedValue) + { + echo "\n"; + } + + function getTestResultsForUser($iUserId, $iVersionId) + { + $oVersion = new version($iVersionId); + $hResult = query_parameters("SELECT * FROM testResults WHERE + submitterId = '?' + AND versionId = '?' + AND state = '?' + ORDER BY testingId DESC", $iUserId, $iVersionId, $oVersion->objectGetState()); + + if(!$hResult) + return null; + + $aRet = array(); + + if(!mysql_num_rows($hResult)) + return $aRet; + + while(($oRow = mysql_fetch_object($hResult))) + $aRet[] = new testData(0, $oRow); + + return $aRet; + } + + /* List test data submitted by a given user. Ignore test results for queued applications/versions */ + function listSubmittedBy($iUserId, $bQueued = true) + { + $hResult = query_parameters("SELECT testResults.versionId, testResults.testedDate, testResults.testedRelease, testResults.testedRating, testResults.submitTime, testResults.testingId, appFamily.appName, appVersion.versionName from testResults, appFamily, appVersion WHERE testResults.versionId = appVersion.versionId AND appVersion.appId = appFamily.appId AND testResults.submitterId = '?' AND testResults.state = '?' ORDER BY testResults.testingId", $iUserId, $bQueued ? 'queued' : 'accepted'); + + if(!$hResult || !query_num_rows($hResult)) + return false; + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetAlign("center"); + + // setup the table header + $oTableRow = new TableRow(); + $oTableRow->AddTextCell('Version'); + $oTableRow->AddTextCell('Rating'); + $oTableRow->AddTextCell('Wine version'); + $oTableRow->AddTextCell('Submission date'); + + if($bQueued) + $oTableRow->addTextCell('Action'); + + $oTableRow->SetClass('color4'); + $oTable->AddRow($oTableRow); + + for($i = 1; $oRow = query_fetch_object($hResult); $i++) + { + $oTableRow = new TableRow(); + + $oTableRow->AddTextCell(version::fullNameLink($oRow->versionId)); + $oTableRow->AddTextCell($oRow->testedRating); + $oTableRow->AddTextCell($oRow->testedRelease); + $oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($oRow->submitTime))); + + if($bQueued) + { + $oM = new objectManager('testData_queue'); + $oM->setReturnTo(array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : ""); + $shDeleteLink = 'delete'; + $shEditLink = 'edit'; + $oTableRow->addTextCell("[ $shEditLink ]   [ $shDeleteLink ]"); + } + + $oTableRow->SetClass($oRow->testedRating); + $oTable->AddRow($oTableRow); + } + + return $oTable->GetString(); + } + + // return the number of test data entries for a particular version id + function get_testdata_count_for_versionid($iVersionId) + { + $sQuery = "SELECT count(*) as cnt + FROM testResults + WHERE versionId = '?' + AND + state = '?';"; + + $hResult = query_parameters($sQuery, $iVersionId, 'accepted'); + + $oRow = query_fetch_object($hResult); + return $oRow->cnt; + } + + function objectGetEntriesCount($sState) + { + $oTest = new testData(); + + if($sState != 'accepted' && !$oTest->canEdit()) + { + if($sState == 'rejected') + { + $sQuery = "SELECT COUNT(testingId) AS count FROM + testResults WHERE + testResults.submitterId = '?' + AND + testResults.state = '?'"; + } else + { + $sQuery = "SELECT COUNT(testingId) AS count FROM + testResults, appVersion, appMaintainers WHERE + testResults.versionId = appVersion.versionId + AND + appMaintainers.userId = '?' + AND + appMaintainers.state = 'accepted' + AND + ( + ( + appMaintainers.superMaintainer = '1' + AND + appMaintainers.appId = appVersion.appid + ) + OR + ( + appMaintainers.superMaintainer = '0' + AND + appMaintainers.versionId = appVersion.versionId + ) + ) + AND + testResults.state = '?'"; + } + + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sState); + } else + { + $sQuery = "SELECT COUNT(testingId) as count FROM testResults WHERE + testResults.state = '?'"; + $hResult = query_parameters($sQuery, $sState); + } + + if(!$hResult) + return FALSE; + + if(!$oRow = query_fetch_object($hResult)) + return FALSE; + + return $oRow->count; + } + + public static function objectGetDefaultSort() + { + return 'testingId'; + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "testingId", $bAscending = true) + { + $oTest = new testData(); + + $sLimit = ""; + + /* Should we add a limit clause to the query? */ + if($iRows || $iStart) + { + $sLimit = " LIMIT ?,?"; + + /* Selecting 0 rows makes no sense, so we assume the user wants to select all of them + after an offset given by iStart */ + if(!$iRows) + $iRows = testData::objectGetEntriesCount($sState); + } + + if($sState != 'accepted' && !$oTest->canEdit()) + { + if($sState == 'rejected') + { + $sQuery = "SELECT testResults.* FROM testResults WHERE + testResults.submitterId = '?' + AND + testResults.state = '?' ORDER BY ?$sLimit"; + } else + { + $sQuery = "SELECT testResults.* FROM testResults, appVersion, + appMaintainers WHERE + testResults.versionId = appVersion.versionId + AND + appMaintainers.userId = '?' + AND + ( + ( + appMaintainers.superMaintainer = '1' + AND + appMaintainers.appId = appVersion.appid + ) + OR + ( + appMaintainers.superMaintainer = '0' + AND + appMaintainers.versionId = appVersion.versionId + ) + ) + AND + appMaintainers.state = 'accepted' + AND + testResults.state = '?' ORDER BY ?$sLimit"; + } + if($sLimit) + { + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sState, $sOrderBy, $iStart, $iRows); + } else + { + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sState, $sOrderBy); + } + } else + { + $sQuery = "SELECT testResults.* FROM testResults WHERE + testResults.state = '?' ORDER by ?$sLimit"; + if($sLimit) + $hResult = query_parameters($sQuery, $sState, $sOrderBy, $iStart, $iRows); + else + $hResult = query_parameters($sQuery, $sState, $sOrderBy); + } + + if(!$hResult) + return FALSE; + + return $hResult; + } + + function objectGetHeader() + { + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("Submission Date"); + $oTableRow->AddTextCell("Submitter"); + $oTableRow->AddTextCell("Application"); + $oTableRow->AddTextCell("Version"); + $oTableRow->AddTextCell("Release"); + $oTableRow->AddTextCell("Has maintainer"); + $oTableRow->AddTextCell("Rating"); + return $oTableRow; + } + + function objectGetTableRow() + { + $oVersion = new version($this->iVersionId); + $oApp = new application($oVersion->iAppId); + $oUser = new user($this->iSubmitterId); + + $hMaintainers = maintainer::getMaintainersForAppIdVersionId(null, $this->iVersionId); + $bHasMaintainer = (query_num_rows($hMaintainers) == 0) ? false : true; + + $oTableRow = new TableRow(); + $oTableRow->AddCell(new TableCell(print_date(mysqldatetime_to_unixtimestamp($this->sSubmitTime)))); + $oTableRow->AddCell(new TableCell($oUser->objectMakeLink())); + $oTableRow->AddCell(new TableCell($oApp->objectMakeLink())); + $oTableRow->AddCell(new TableCell($oVersion->objectMakeLink())); + $oTableRow->AddCell(new TableCell($this->sTestedRelease)); + $oTableRow->AddCell(new TableCell($bHasMaintainer ? "YES" : "no")); + $oTableRow->AddCell(new TableCell($this->sTestedRating)); + + $oTableRow->SetClass($this->sTestedRating); + + $oOMTableRow = new OMTableRow($oTableRow); + $oOMTableRow->SetHasDeleteLink(true); + + return $oOMTableRow; + } + + public function objectGetState() + { + return $this->sState; + } + + function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + return TRUE; + else if($this->iVersionId) + { + if($this->iSubmitterId == $_SESSION['current']->iUserId && + $this->sState != 'accepted') + return TRUE; + + $oVersion = new version($this->iVersionId); + if($_SESSION['current']->hasAppVersionModifyPermission($oVersion)) + return TRUE; + else + return FALSE; + } else + return FALSE; + } + + public function objectDisplayQueueProcessingHelp() + { + echo "

    This is the list of test results waiting to be processed.

    \n"; + echo "

    To view and process an entry, use the links under ‘Action’

    "; + } + + function objectShowPreview() + { + return TRUE; + } + + function display() + { + $this->ShowTestResult(); + $iOldSubmitterId = $this->iSubmitterId; + + if(!$this->iSubmitterId) + $this->iSubmitterId = $_SESSION['current']->iUserId; + + $oTable = $this->CreateTestTable(); + + $oTable->AddRow($this->CreateTestTableRow($this->iTestingId, "")); + + echo $oTable->GetString(); + + $this->iSubmitterId = $iOldSubmitterId; + } + + + function objectMakeUrl() + { + $oObject = new objectManager("testData", "Edit Test Results", $this->iTestingId); + return $oObject->makeUrl("edit", $this->iTestingId); + } + + function objectMakeLink() + { + $oObject = new objectManager("testData", "Edit Test Results", $this->iTestingId); + return 'iTestingId).'">test report'; + } + + public function isOld() + { + /* If no id is defined that means the test report is not in the database, which means it can't be old */ + if(!$this->iTestingId) + return false; + + return ((mktime() - mysqltimestamp_to_unixtimestamp($this->sSubmitTime)) > (60 * 60 * 24 * TESTDATA_AGED_THRESHOLD)); + } + + public function objectSetParent($iNewId, $sClass = 'version') + { + $this->iVersionId = $iNewId; + } + + function objectGetParent() + { + return new version($this->iVersionId); + } + + /* Only show children of (grand)parents in the Move Child Objects and Change Parent lists */ + public static function objectRestrictMoveObjectListsToParents() + { + return true; + } + + function objectGetChildren($bIncludeDeleted = false) + { + /* We have none */ + return array(); + } + + function objectDisplayAddItemHelp() + { + echo "

    This is the screen for inputing test information so that others "; + echo "looking at the database will know \n"; + echo "what was working on a particular release of Wine.

    \n"; + echo "

    Please DO NOT include crash or Wine debug output.\n"; + echo " Instead report the crash as a bug in the Wine bugzilla at \n"; + echo "http://bugs.winehq.org.\n"; + echo "We ask that you use bugzilla because developers do not monitor the AppDB \n"; + echo "for bugs.

    \n"; + echo "

    Please be as detailed as you can but do not paste large \n"; + echo "chunks of output from the terminal. Type out your report \n"; + echo "clearly and in proper English so that it is easily readable.

    \n"; + } + + function mustBeQueued() + { + if($_SESSION['current']->hasPriv("admin")) + { + return FALSE; + } else if($this->iVersionId) + { + // if the user can edit the version and the version isn't queued then + // they can also submit test results without them being queued + // this is the case where they maintain the version and the version isn't queued + $oVersion = new version($this->iVersionId); + if($oVersion->canEdit() && $oVersion->objectGetState() == 'accepted') + return FALSE; + else + return TRUE; + } else + { + return TRUE; + } + } + + function allowAnonymousSubmissions() + { + return FALSE; + } + + function objectAllowPurgingRejected() + { + return TRUE; + } + + public function objectGetSubmitTime() + { + return mysqltimestamp_to_unixtimestamp($this->sSubmitTime); + } + + function objectGetItemsPerPage($sState = 'accepted') + { + $aItemsPerPage = array(25, 50, 100, 200); + $iDefaultPerPage = 25; + return array($aItemsPerPage, $iDefaultPerPage); + } + + function objectGetId() + { + return $this->iTestingId; + } + + function objectGetSubmitterId() + { + return $this->iSubmitterId; + } +} + +?> diff --git a/include/testData_queue.php b/include/testData_queue.php new file mode 100644 index 0000000..fcc5992 --- /dev/null +++ b/include/testData_queue.php @@ -0,0 +1,242 @@ +oTestData = new testData($iTestId, $oRow); + $this->oDistribution = new distribution($this->oTestData->iDistributionId); + } + + function create() + { + if(!$this->oTestData->iDistributionId) + { + $this->oDistribution->create(); + $this->oTestData->iDistributionId = $this->oDistribution->iDistributionId; + } + + return $this->oTestData->create(); + } + + function purge() + { + $bSuccess = $this->oTestData->purge(); + + /* We delete the distribution if it has not been approved and is not associated + with any other testData. Otherwise we would have to have a distribution + queue for admins to clean up unused, queued entries */ + $this->oDistribution = new distribution($this->oDistribution->iDistributionId); + if(!sizeof($this->oDistribution->aTestingIds) && + $this->oDistribution->canEdit()) + $this->oDistribution->purge(); + + return $bSuccess; + } + + function delete() + { + $bSuccess = $this->oTestData->delete(); + + /* We delete the distribution if it has not been approved and is not associated + with any other testData. Otherwise we would have to have a distribution + queue for admins to clean up unused, queued entries */ + $this->oDistribution = new distribution($this->oDistribution->iDistributionId); + if(!sizeof($this->oDistribution->aTestingIds) && + $this->oDistribution->canEdit()) + $this->oDistribution->delete(); + + return $bSuccess; + } + + function reQueue() + { + $this->oTestData->reQueue(); + + $this->oDistribution->reQueue(); + } + + function unQueue() + { + $this->oTestData->unQueue(); + + /* Avoid a misguiding message about the distribution being unqueued */ + if($this->oDistribution->objectGetState() != 'accepted') + $this->oDistribution->unQueue(); + } + + function reject() + { + $this->oTestData->reject(); + } + + function update() + { + $this->oTestData->update(); + + /* If the distribution was already un-queued the form for editing it would + not have been displayed and getOutputEditorValues() wouldn't have + retrieved a valid sName for the distribution. If sName isn't valid + we shouldn't update the distribution */ + if($this->oDistribution->sName) + $this->oDistribution->update(); + } + + function outputEditor() + { + $this->oTestData->outputEditor(); + + /* If we are processing queued test results with a queued distribution, + we display some additional help here */ + if($this->oDistribution->iDistributionId && + $this->oDistribution->objectGetState() != 'accepted' && $this->canEdit()) + { + echo "The user submitted a new distribution, which will be un-queued ". + "together with the test data unless you select an existing one ". + "from the list above."; + } + + /* If the testData is already associated with a distribution and the + distribution is un-queued, there is no need to display the + distribution form here */ + if(!$this->oTestData->iDistributionId or + $this->oDistribution->objectGetState() != 'accepted') + { + echo html_frame_start("New Distribution", "90%"); + $this->oDistribution->outputEditor(); + echo html_frame_end(); + } + } + + function getOutputEditorValues($aClean) + { + $this->oTestData->getOutputEditorValues($aClean); + $this->oDistribution->getOutputEditorValues($aClean); + } + + function checkOutputEditorInput($aClean) + { + return $this->oTestData->checkOutputEditorInput($aClean); + } + + function objectGetState() + { + return $this->oTestData->objectGetState(); + } + + function canEdit() + { + return $this->oTestData->canEdit(); + } + + function mustBeQueued() + { + return $this->oTestData->mustBeQueued(); + } + + function objectDisplayAddItemHelp() + { + $this->oTestData->objectDisplayAddItemHelp(); + } + + public static function objectGetDefaultSort() + { + return testData::objectGetDefaultSort(); + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "testingId", $bAscending = true) + { + return $this->oTestData->objectGetEntries($sState, $iRows, $iStart, $sOrderBy, $bAscending); + } + + function objectGetEntriesCount($sState) + { + return testData::objectGetEntriesCount($sState); + } + + function objectGetHeader() + { + return $this->oTestData->objectGetHeader(); + } + + function objectGetTableRow() + { + return $this->oTestData->objectGetTableRow(); + } + + function objectDisplayQueueProcessingHelp() + { + $oTest = new testData(); + $oTest->objectDisplayQueueProcessingHelp(); + } + + function objectShowPreview() + { + return $this->oTestData->objectShowPreview(); + } + + function display() + { + return $this->oTestData->display(); + } + + function objectMakeUrl() + { + return $this->oTestData->objectMakeUrl(); + } + + function objectMakeLink() + { + return $this->oTestData->objectMakeLink(); + } + + function allowAnonymousSubmissions() + { + return testData::allowAnonymousSubmissions(); + } + + function objectAllowPurgingRejected() + { + return $this->oTestData->objectAllowPurgingRejected(); + } + + public function objectGetSubmitTime() + { + return $this->oTestData->objectGetSubmitTime(); + } + + function objectGetItemsPerPage($sState = 'accepted') + { + return testData::objectGetItemsPerPage($sState); + } + + function objectGetId() + { + return $this->oTestData->objectGetId(); + } + + function objectGetSubmitterId() + { + return $this->oTestData->objectGetSubmitterId(); + } + + function objectGetChildren($bIncludeDeleted = false) + { + return $this->oTestData->objectGetChildren($bIncludeDeleted); + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return $this->oTestData->objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + return $this->oTestData->objectGetMail($sAction, $bMailSubmitter, $bParentAction); + } +} + +?> diff --git a/include/url.php b/include/url.php new file mode 100644 index 0000000..0419168 --- /dev/null +++ b/include/url.php @@ -0,0 +1,558 @@ +iUrlId = $oRow->id; + $this->sDescription = $oRow->description; + $this->iAppId = $oRow->appId; + $this->iVersionId = $oRow->versionId; + $this->sUrl = Url::normalize($oRow->url); + $this->bQueued = ($oRow->state == 'accepted') ? false : true; + $this->sSubmitTime = $oRow->submitTime; + $this->iSubmitterId = $oRow->submitterId; + } + } + + + /** + * Creates a new url. + */ + function create($sDescription = null, $sUrl = null, $iVersionId = null, + $iAppId = null, $bSilent = false) + { + global $aClean; + + // Security, if we are not an administrator or a maintainer, the url must be queued. + if(($iAppId && !url::canEdit(NULL, $iAppId)) || + ($iVersionId && !url::canEdit($iVersionId))) + $this->bQueued = true; + + $hResult = query_parameters("INSERT INTO appData (appId, versionId, type, + description, state, submitTime, submitterId, url) + VALUES ('?', '?', '?', '?', '?', ?, '?', '?')", + $iAppId, $iVersionId, "url", $sDescription, + $this->bQueued ? 'queued' : 'accepted', + "NOW()", $_SESSION['current']->iUserId, $sUrl); + + if(!$hResult) + { + addmsg("Error while creating a new url.", "red"); + return false; + } + + $this->iUrlId = query_appdb_insert_id(); + $this->url($this->iUrlId,$this->bQueued); + + if(!$bSilent) + $this->SendNotificationMail(); + + return true; + } + + function purge() + { + return $this->delete(); + } + + /** + * Deletes the url from the database. + * and request its deletion from the filesystem (including the thumbnail). + */ + function delete() + { + $sQuery = "DELETE FROM appData + WHERE id = '?' + AND type = 'url' + LIMIT 1"; + if(!$hResult = query_parameters($sQuery, $this->iUrlId)) + return false; + + return true; + } + + + /** + * Move url out of the queue. + */ + function unQueue() + { + // If we are not in the queue, we can't move the url out of the queue. + if(!$this->bQueued) + return false; + + if(query_parameters("UPDATE appData SET state '?' WHERE id='?'", + 'accepted', $this->iUrlId)) + { + // we send an e-mail to interested people + $this->mailSubmitter(); + $this->SendNotificationMail(); + // the url has been unqueued + addmsg("The url has been unqueued.", "green"); + } + } + + + /** + * Update url. + * Returns true on success and false on failure. + */ + function update($sDescription = null, $sUrl = null, $iVersionId = null, $iAppId = null, $bSilent = false) + { + if(!$this->iUrlId) + return FALSE; + + $oUrl = new url($this->iUrlId); + + if($this->iVersionId && !$iVersionId) + $iVersionId = $this->iVersionId; + + $sWhatChanged = ""; + + if ($sDescription && $sDescription!=$this->sDescription) + { + if (!query_parameters("UPDATE appData SET description = '?' WHERE id = '?'", + $sDescription, $this->iUrlId)) + return false; + $sWhatChanged .= "Description was changed from\n ".$this->sDescription."\n to \n".$sDescription.".\n\n"; + $this->sDescription = $sDescription; + } + + if ($sUrl && $sUrl!=$this->sUrl) + { + if (!query_parameters("UPDATE appData SET url = '?' WHERE id = '?'", + $sUrl, $this->iUrlId)) + return false; + $sWhatChanged .= "Url was changed from ".$this->sUrl." to ".$sUrl.".\n\n"; + $this->sUrl = $sUrl; + } + + if ($iVersionId && $iVersionId!=$oUrl->iVersionId) + { + if (!query_parameters("UPDATE appData SET versionId = '?' WHERE id = '?'", + $iVersionId, $this->iUrlId)) + return false; + $oVersionBefore = new Version($this->iVersionId); + $oVersionAfter = new Version($iVersionId); + $sWhatChanged .= "Version was changed from ".$oVersionBefore->sName." to ".$oVersionAfter->sName.".\n\n"; + $this->iVersionId = $iVersionId; + $this->iAppId = $oVersionAfter->iAppId; + } + + if ($iAppId && $iAppId!=$this->iAppId) + { + if (!query_parameters("UPDATE appData SET appId = '?' WHERE id = '?'", + $iAppId, $this->iUrlId)) + return false; + $oAppBefore = new Application($this->iAppId); + $oAppAfter = new Application($iAppId); + $sWhatChanged .= "Application was changed from ".$oAppBefore->sName." to ".$oAppAfter->sName.".\n\n"; + $this->iAppId = $iAppId; + } + if($sWhatChanged && !$bSilent) + $this->SendNotificationMail("edit",$sWhatChanged); + return true; + } + + + function mailSubmitter($bRejected=false) + { + global $aClean; + + if($this->iSubmitterId) + { + $sAppName = Application::lookup_name($this->iAppId)." ".Version::lookup_name($this->iVersionId); + $oSubmitter = new User($this->iSubmitterId); + if(!$bRejected) + { + $sSubject = "Submitted url accepted"; + $sMsg = "The url you submitted for ".$sAppName." has been accepted."; + } else + { + $sSubject = "Submitted url rejected"; + $sMsg = "The url you submitted for ".$sAppName." has been rejected."; + } + $sMsg .= $aClean['sReplyText']."\n"; + $sMsg .= "We appreciate your help in making the Application Database better for all users."; + + mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg); + } + } + + + function SendNotificationMail($bDeleted=false) + { + /* Set variables depending on whether the url is for an app or version */ + if($this->iVersionId) + { + $oVersion = new version($this->iVersionId); + $sAppName = version::fullName($this->iVersionId); + $sUrl = $oVersion->objectMakeUrl(); + } else + { + $oApp = new application($this->iAppId); + $sAppName = $oApp->sName; + $sUrl = $oApp->objectMakeUrl(); + } + + if(!$bDeleted) + { + if(!$this->bQueued) + { + $sSubject = "Url for $sAppName added by ".$_SESSION['current']->sRealname; + $sMsg = "$sUrl\n"; + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + $sMsg .= "This url has been submitted by ".$oSubmitter->sRealname."."; + $sMsg .= "\n"; + } + addmsg("The url was successfully added into the database.", "green"); + } else // Url queued. + { + $sSubject = "Url for $sAppName submitted by ". + $_SESSION['current']->sRealname; + $sMsg = "$sUrl\n"; + $sMsg .= "This url has been queued."; + $sMsg .= "\n"; + addmsg("The url you submitted will be added to the database ". + "database after being reviewed.", "green"); + } + } + + $sEmail = User::get_notify_email_address_list(null, $this->iVersionId); + if($sEmail) + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + /* Output an editor for URL fields */ + function outputEditor($sFormAction, $oVersion, $oApp = NULL) + { + /* Check for correct permissions */ + if(($oVersion && !url::canEdit($oVersion->iVersionId)) || + ($oApp && !url::canEdit(NULL, $oApp->iAppId))) + return FALSE; + + if($oVersion) + $hResult = appData::getData($oVersion->iVersionId, "url"); + else + $hResult = appData::getData($oApp->iAppId, "url", FALSE); + + $sReturn .= html_frame_start("URLs", "90%", "", 0); + $sReturn .= "
    \n"; + $sReturn .= html_table_begin("border=0 cellpadding=5 cellspacing=0 width=100%"); + $sReturn .= html_tr(array( + array("Remove", "width=\"90\""), + "Description", + "URL" + ), + "color0"); + + $sReturn .= html_tr(array( + " ", + "", + ""), + "color4"); + + if($hResult) + { + for($i = 1; $oRow = query_fetch_object($hResult); $i++) + { + $sReturn .= html_tr(array( + "id\" ". + "value=\"true\">", + "id\" value=\"$oRow->description\">", + "id\" ". + "value=\"$oRow->url\">"), + ($i % 2) ? "color0" : "color4"); + } + } + + if($oVersion) + $iAppId = $oVersion->iAppId; + else + $iAppId = $oApp->iAppId; + + $sReturn .= html_table_end(); + $sReturn .= "
    \n"; + + if($oVersion) + $sReturn .=" iVersionId\">\n"; + + $sReturn .= "\n"; + $sReturn .= "
    \n"; + $sReturn .= html_frame_end(" "); + + return $sReturn; + } + + /* Process data from a URL form */ + function ProcessForm($aValues) + { + + /* Check that we are processing a Download URL form */ + if($aValues["sSubmit"] != "Update URLs") + return FALSE; + + /* Check permissions */ + if(($aValues['iVersionId'] && !url::canEdit($aValues["iVersionId"])) || + (!$aValues['iVersionId'] && !url::canEdit(NULL, $aValues['iAppId']))) + return FALSE; + + if($aValues["iVersionId"]) + { + if(!($hResult = query_parameters("SELECT COUNT(*) as num FROM appData + WHERE TYPE = '?' AND versionId = '?'", + "url", $aValues["iVersionId"]))) + return FALSE; + } else + { + if(!($hResult = query_parameters("SELECT COUNT(*) as num FROM appData + WHERE TYPE = '?' AND appId = '?'", + "url", $aValues["iAppId"]))) + return FALSE; + } + + if(!($oRow = query_fetch_object($hResult))) + return FALSE; + + $num = $oRow->num; + + /* Update URLs. Nothing to do if none are present in the database */ + if($num) + { + if($aValues['iVersionId']) + { + if(!$hResult = appData::getData($aValues["iVersionId"], "url")) + return FALSE; + } else + { + if(!$hResult = appData::getData($aValues['iAppId'], "url", FALSE)) + return FALSE; + } + + while($oRow = query_fetch_object($hResult)) + { + $url = new url($oRow->id); + + /* Remove URL */ + if($aValues["bRemove$oRow->id"]) + { + if(!$url->delete(TRUE)) + return FALSE; + + $sWhatChangedRemove .= "Removed\nURL: $oRow->url\n". + "Description: $oRow->description\n\n"; + } + + /* Change description/URL */ + if(($aValues["sDescription$oRow->id"] != $oRow->description or + $aValues["sUrl$oRow->id"] != $oRow->url) && + $aValues["sDescription$oRow->id"] && $aValues["sUrl$oRow->id"]) + { + if(!$url->update($aValues["sDescription$oRow->id"], + $aValues["sUrl$oRow->id"], $aValues["iVersionId"], + $aValues["iVersionId"] ? 0 : $aValues["iAppId"], TRUE)) + return FALSE; + + $sWhatChangedModify .= "Modified\nOld URL: $oRow->url\nOld ". + "Description: $oRow->description\nNew URL: ". + $aValues["sUrl$oRow->id"]."\nNew Description: ". + $aValues["sDescription$oRow->id"]."\n\n"; + } + } + } + + /* Insert new URL */ + if($aValues["sDescriptionNew"] && $aValues["sUrlNew"]) + { + $url = new Url(); + + if(!$url->create($aValues["sDescriptionNew"], $aValues["sUrlNew"], + $aValues["iVersionId"] ? $aValues["iVersionId"] : "0", + $aValues["iVersionId"] ? "0" : $aValues["iAppId"], TRUE)) + return FALSE; + + $sWhatChanged = "Added\nURL: ".$aValues["sUrlNew"]."\nDescription: ". + $aValues["sDescriptionNew"]."\n\n"; + } + + $sWhatChanged .= "$sWhatChangedRemove$sWhatChangedModify"; + + if($aValues["iVersionId"]) + $sEmail = User::get_notify_email_address_list($aValues['iVersionId']); + else + $sEmail = User::get_notify_email_address_list($aValues['iAppId']); + if($sWhatChanged && $sEmail) + { + $oApp = new Application($aValues["iAppId"]); + + if($aValues["iVersionId"]) + { + $oVersion = new Version($aValues["iVersionId"]); + $sVersionName = " $oVersion->sName"; + } + + $sSubject = "Links for $oApp->sName$sVersionName updated by ". + $_SESSION['current']->sRealname; + + $sMsg = $aValues["iVersionId"] ? + $oVersion->objectMakeUrl() : + $oApp->objectMakeUrl(); + $sMsg .= "\n\n"; + $sMsg .= "The following changed were made\n\n"; + $sMsg .= "$sWhatChanged\n\n"; + + mail_appdb($sEmail, $sSubject, $sMsg); + } + + return TRUE; + } + + function canEdit($iVersionId = NULL, $iAppId = NULL) + { + if($_SESSION['current']->hasPriv("admin")) + return TRUE; + else if($iVersionId) + { + $oVersion = new version($iVersionId); + return $oVersion->canEdit(); + } else if($iAppId) + { + $oApp = new application($iAppId); + return $oApp->canEdit(); + } else + return FALSE; + } + + /* Display links for a given version/application */ + function display($iVersionId, $iAppId = NULL) + { + if($iVersionId) + { + if(!($hResult = appData::getData($iVersionId, "url"))) + return FALSE; + } else + { + if(!($hResult = appData::getData($iAppId, "url", FALSE))) + return FALSE; + } + + $sReturn = ''; + for($i = 0; $oRow = query_fetch_object($hResult); $i++) + { + // create a url object + $oUrl = new Url(null, $oRow); + + $sReturn .= html_tr(array( + "Link", + "sUrl\">$oUrl->sDescription"), + "color1"); + } + + return $sReturn; + } + + function objectGetId() + { + return $this->iUrlId; + } + + function objectGetSubmitterId() + { + return $this->iSubmitterId; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + /* We don't do this at the moment */ + return array(null, null, null); + } + + public function objectGetParent($sClass = '') + { + $oAppData = new appData($this->iUrlId, null, $this); + return $oAppData->objectGetParent(); + } + + public function objectSetParent($iNewId, $sClass = '') + { + if($this->iVersionId) + $this->iVersionId = $iNewId; + else + $this->iAppId = $iNewId; + } + + function objectGetChildren($bIncludeDeleted = false) + { + return array(); + } + + // if a url lacks "://" assume the url is an http one + // and prepend "http://" + function normalize($sTheUrl) + { + // return if we have an empty string + if($sTheUrl == "") + return $sTheUrl; + + // if we already have "://" in the url + // we can leave the url alone + if(strpos($sTheUrl, "://") === false) + { + // assume this is a website and prepend "http://" + return "http://".$sTheUrl; + } else + { + // leave the url alone + return $sTheUrl; + } + } +} +?> diff --git a/include/user.php b/include/user.php new file mode 100644 index 0000000..73d47eb --- /dev/null +++ b/include/user.php @@ -0,0 +1,866 @@ +sRealname = "an anonymous user"; + if(is_numeric($iUserId)) + { + $sQuery = "SELECT * + FROM user_list + WHERE userId = '?'"; + $hResult = query_parameters($sQuery, $iUserId); + $oRow = query_fetch_object($hResult); + if($oRow) + { + $this->iUserId = $oRow->userid; + $this->sEmail = $oRow->email; + $this->sRealname = $oRow->realname; + $this->sStamp = $oRow->stamp; + $this->sDateCreated = $oRow->created; + $this->sWineRelease = $oRow->CVSrelease; + $this->bInactivityWarned = $oRow->inactivity_warned; + } + } + return $this->isLoggedIn(); + } + + + /** + * Logs in an user using e-mail and password. + */ + function login($sEmail, $sPassword) + { + $sQuery = "SELECT * + FROM user_list + WHERE email = '?' AND password = "; + + $sMysqlSHAPasswordPart = "SHA1('?');"; + $sMysqlPasswordPart = "password('?');"; + $sMysql40xPasswordPart = "old_password('?');"; + + // if true we used an old style password and we need to + // update the users password to the new style + $bUsedOldStylePassword = false; + + $oRow = null; // null out the row object + + // if we aren't logged in yet + // try to login with the mysql sha1() value of the password + if(!$oRow) + { + $hResult = query_parameters($sQuery.$sMysqlSHAPasswordPart, + $sEmail, $sPassword); + $oRow = query_fetch_object($hResult); + } + + // if we aren't logged in yet + // try to login with the mysql password() value of the password + if(!$oRow) + { + $hResult = query_parameters($sQuery.$sMysqlPasswordPart, + $sEmail, $sPassword); + $oRow = query_fetch_object($hResult); + if($oRow) $bUsedOldStylePassword = true; + } + + // if we aren't logged in yet + // try to login with the mysql old_password() value of the password + if(!$oRow) + { + // make sure we have a newer version, older versions may not + $sResult = mysql_get_server_info(); + $fVersion = substr($sResult, 0, 3); + + // if we have a newer version of mysql, try with the 'old_password()' function + if($fVersion >= 4.1) + { + $hResult = query_parameters($sQuery.$sMysql40xPasswordPart, + $sEmail, $sPassword); + $oRow = query_fetch_object($hResult); + if($oRow) $bUsedOldStylePassword = true; + } + } + + if($oRow) + { + $this->iUserId = $oRow->userid; + $this->sEmail = $oRow->email; + $this->sRealname = $oRow->realname; + $this->sStamp = $oRow->stamp; + $this->sDateCreated = $oRow->created; + $this->sWineRelease = $oRow->CVSrelease; + + // if we used an old style password, update the users password + if($bUsedOldStylePassword) + { + $this->update_password($sPassword); + } + } + + if($this->isLoggedIn()) + { + // Update timestamp and clear the inactivity flag if it was set + query_parameters("UPDATE user_list SET stamp = ?, inactivity_warned = '?' WHERE userid='?'", + "NOW()", "false", $this->iUserId); + + /* set the session variable for the current user to this user object */ + $_SESSION['current'] = $this; + + return SUCCESS; + } + + /* destroy all session variables since we failed to login */ + $GLOBALS['session']->destroy(); + + return USER_LOGIN_FAILED; + } + + function logout() + { + /* destroy all session variables since we are logging out */ + $GLOBALS['session']->destroy(); + } + + + /* + * Creates a new user. + * returns SUCCESS on success, USER_CREATE_EXISTS if the user already exists + */ + function create($sEmail, $sPassword, $sRealname, $sWineRelease) + { + if(User::exists($sEmail)) + { + return USER_CREATE_EXISTS; + } else + { + $hResult = query_parameters("INSERT INTO user_list (realname, email, CVSrelease, password, stamp,". + "created) VALUES ('?', '?', '?', SHA1('?'), ?, ?)", + $sRealname, $sEmail, $sWineRelease, $sPassword, "NOW()", "NOW()"); + + if(!$hResult) return USER_CREATE_FAILED; + + $retval = $this->login($sEmail, $sPassword); + if($retval == SUCCESS) + $this->setPref("comments:mode", "threaded"); /* set the users default comments:mode to threaded */ + $this->logout(); + + return $retval; + } + } + + + /** + * Update User Account; + */ + function update() + { + if(!$this->isLoggedIn()) return USER_UPDATE_FAILED_NOT_LOGGED_IN; + + /* create an instance of ourselves so we can see what has changed */ + $oUser = new User($this->iUserId); + + if($this->sEmail && ($this->sEmail != $oUser->sEmail)) + { + /* make sure this email isn't already in use */ + if(User::exists($this->sEmail)) + { + addMsg("An account with this e-mail exists already.","red"); + return USER_UPDATE_FAILED_EMAIL_EXISTS; + } + if (!query_parameters("UPDATE user_list SET email = '?' WHERE userid = '?'", + $this->sEmail, $this->iUserId)) + return USER_UPDATE_FAILED; + } + + if ($this->sRealname && ($this->sRealname != $oUser->sRealname)) + { + if (!query_parameters("UPDATE user_list SET realname = '?' WHERE userid = '?'", + $this->sRealname, $this->iUserId)) + return USER_UPDATE_FAILED; + } + + if ($this->sWineRelease && ($this->sWineRelease != $oUser->sWineRelease)) + { + if (!query_parameters("UPDATE user_list SET CVSrelease = '?' WHERE userid = '?'", + $this->sWineRelease, $this->iUserId)) + return USER_UPDATE_FAILED; + } + + return SUCCESS; + } + + /** + * NOTE: we can't update the users password like we can update other + * fields such as their email or username because the password is hashed + * in the database so we can't keep the users password in a class member variable + * and use update() because we can't check if the password changed without hashing + * the newly supplied one + */ + function update_password($sPassword) + { + if($sPassword) + { + if (query_parameters("UPDATE user_list SET password = SHA1('?') ". + "WHERE userid = '?'", + $sPassword, $this->iUserId)) + return true; + } + + return false; + } + + + /** + * Removes the current, or specified user and preferences from the database. + * returns true on success and false on failure. + */ + function delete() + { + $hResult2 = query_parameters("DELETE FROM user_privs WHERE userid = '?'", $this->iUserId); + $hResult3 = query_parameters("DELETE FROM user_prefs WHERE userid = '?'", $this->iUserId); + $hResult4 = query_parameters("DELETE FROM appVotes WHERE userid = '?'", $this->iUserId); + $hResult5 = Maintainer::deleteMaintainer($this); + $hResult6 = query_parameters("DELETE FROM appComments WHERE userId = '?'", $this->iUserId); + return($hResult = query_parameters("DELETE FROM user_list WHERE userid = '?'", $this->iUserId)); + } + + + /** + * Get a preference for the current user. + */ + function getPref($sKey, $sDef = null) + { + if(!$this->isLoggedIn() || !$sKey) + return $sDef; + + $hResult = query_parameters("SELECT * FROM user_prefs WHERE userid = '?' AND name = '?'", + $this->iUserId, $sKey); + if(!$hResult || query_num_rows($hResult) == 0) + return $sDef; + $oRow = query_fetch_object($hResult); + return $oRow->value; + } + + + /** + * Set a preference for the current user. + */ + function setPref($sKey, $sValue) + { + if(!$this->isLoggedIn() || !$sKey || !$sValue) + return false; + + $hResult = query_parameters("DELETE FROM user_prefs WHERE userid = '?' AND name = '?'", + $this->iUserId, $sKey); + $hResult = query_parameters("INSERT INTO user_prefs (userid, name, value) VALUES". + "('?', '?', '?')", $this->iUserId, $sKey, $sValue); + return $hResult; + } + + + /** + * Check if this user has $priv. + */ + function hasPriv($sPriv) + { + if(!$this->isLoggedIn() || !$sPriv) + return false; + + $hResult = query_parameters("SELECT * FROM user_privs WHERE userid = '?' AND priv = '?'", + $this->iUserId, $sPriv); + if(!$hResult) + return false; + return query_num_rows($hResult); + } + + + /* Check if this user is a maintainer of a given appId/versionId */ + function isMaintainer($iVersionId=null) + { + return Maintainer::isUserMaintainer($this, $iVersionId); + } + + /* Check if this user is a maintainer of a given appId/versionId */ + function isSuperMaintainer($iAppId=null) + { + return Maintainer::isUserSuperMaintainer($this, $iAppId); + } + + function addPriv($sPriv) + { + if(!$this->isLoggedIn() || !$sPriv) + return false; + + if($this->hasPriv($sPriv)) + return true; + + $hResult = query_parameters("INSERT INTO user_privs (userid, priv) VALUES". + " ('?', '?')", $this->iUserId, $sPriv); + return $hResult; + } + + + function delPriv($sPriv) + { + if(!$this->isLoggedIn() || !$sPriv) + return false; + + $hResult = query_parameters("DELETE FROM user_privs WHERE userid = '?' AND priv = '?'", + $this->iUserId, $sPriv); + return $hResult; + } + + + /** + * Checks if the current user is valid. + */ + function isLoggedIn() + { + return $this->iUserId; + } + + + /** + * Checks if user should see debugging infos. + */ + function showDebuggingInfos() + { + return (($this->isLoggedIn() && $this->getPref("debug") == "yes") || APPDB_DEBUG == 1); + } + + + /** + * Checks if user wants to get e-mails. + */ + function wantsEmail() + { + return ($this->isLoggedIn() && $this->getPref("send_email","yes")=="yes"); + } + + function isAppSubmitter($iAppId) + { + $hResult = query_parameters("SELECT appId FROM appFamily + WHERE submitterId = '?' + AND appId = '?'", + $this->iUserId, $iAppId); + if(query_num_rows($hResult)) + return true; + else + return false; + } + + function isVersionSubmitter($iVersionId) + { + $hResult = query_parameters("SELECT appVersion.versionId FROM appVersion, appFamily + WHERE appFamily.appId = appVersion.appId + AND appVersion.submitterId = '?' + AND appVersion.versionId = '?'", + $this->iUserId, $iVersionId); + if(query_num_rows($hResult)) + return true; + else + return false; + } + + /* if this user has data associated with them we will return true */ + /* otherwise we return false */ + function hasDataAssociated() + { + $hResult = query_parameters("SELECT count(userId) as c FROM appComments WHERE userId = '?'", + $this->iUserId); + $oRow = query_fetch_object($hResult); + if($oRow->c != 0) return true; + + if($this->isMaintainer() || $this->isSuperMaintainer()) + return true; + + $hResult = query_parameters("SELECT count(userId) as c FROM appVotes WHERE userId = '?'", + $this->iUserId); + $oRow = query_fetch_object($hResult); + if($oRow->c != 0) return true; + + return false; + } + + /* warn the user that their account has been marked as inactive */ + function warnForInactivity() + { + /* we don't want to warn users that have data associated with them */ + if($this->hasDataAssociated()) + { + return false; + } + + if($this->isMaintainer()) + { + $sSubject = "Warning: inactivity detected"; + $sMsg = "You didn't log in in the past six months to the AppDB.\r\n"; + $sMsg .= "As a maintainer we would be pleased to see you once in a while.\r\n"; + $sMsg .= "Please log in or you will lose your maintainer's abilities in one month.\r\n"; + } else + { + $sSubject = "Warning: inactivity detected"; + $sMsg = "You didn't log in in the past six months to the AppDB.\r\n"; + $sMsg .= "Please log in or your account will automatically be deleted in one month.\r\n"; + } + $sMsg .= APPDB_ROOT."account.php?sCmd=login\r\n"; + + mail_appdb($this->sEmail, $sSubject, $sMsg); + + /* mark this user as being inactive and set the appropriate timestamp */ + $sQuery = "update user_list set inactivity_warned='true', inactivity_warn_stamp=NOW() where userid='?'"; + query_parameters($sQuery, $this->iUserId); + + return true; + } + + + /** + * Creates a new random password. + */ + function generate_passwd($pass_len = 10) + { + $nps = ""; + mt_srand ((double) microtime() * 1000000); + while (strlen($nps)<$pass_len) + { + $c = chr(mt_rand (0,255)); + if (eregi("^[a-z0-9]$", $c)) $nps = $nps.$c; + } + return ($nps); + } + + /** + * Check if a user exists. + * returns the userid if the user exists + */ + function exists($sEmail) + { + $hResult = query_parameters("SELECT userid FROM user_list WHERE email = '?'", + $sEmail); + if(!$hResult || query_num_rows($hResult) != 1) + { + return 0; + } else + { + $oRow = query_fetch_object($hResult); + return $oRow->userid; + } + } + + /** + * Get the number of users in the database + * The parameters are only included for compatibility; we don't queue users + */ + function objectGetEntriesCount($bQueued = null, $bRejected = null) + { + $hResult = query_parameters("SELECT count(*) as num_users FROM user_list;"); + $oRow = query_fetch_object($hResult); + return $oRow->num_users; + } + + /** + * Get the number of active users within $days of the current day + */ + function active_users_within_days($days) + { + $hResult = query_parameters("SELECT count(*) as num_users FROM user_list WHERE stamp >= DATE_SUB(CURDATE(), interval '?' day);", + $days); + $oRow = query_fetch_object($hResult); + return $oRow->num_users; + } + + /** + * Get the count of users who have been warned for inactivity and are + * pending deletion after the X month grace period + */ + function get_inactive_users_pending_deletion() + { + /* retrieve the number of users that have been warned and are pending deletion */ + $hResult = query_parameters("select count(*) as count from user_list where inactivity_warned = 'true'"); + $oRow = query_fetch_object($hResult); + return $oRow->count; + } + + /** + * Get the email address of people to notify for this appId and versionId. + */ + function get_notify_email_address_list($iAppId = null, $iVersionId = null) + { + $aUserId = array(); + $sRetval = ""; + + /* + * Retrieve version maintainers. + */ + $hResult = Maintainer::getMaintainersForAppIdVersionId($iAppId, $iVersionId); + + if($hResult) + { + if(query_num_rows($hResult) > 0) + { + while($oRow = query_fetch_object($hResult)) + $aUserId[] = $oRow->userId; + } + } + + /* + * Retrieve version Monitors. + */ + /* + * If versionId was supplied we fetch superMonitors of application and Monitors of version. + */ + if($iVersionId) + { + $hResult = query_parameters("SELECT appMonitors.userId + FROM appMonitors, appVersion + WHERE appVersion.appId = appMonitors.appId + AND appVersion.versionId = '?'", + $iVersionId); + } + /* + * If versionId was not supplied we fetch superMonitors of application and Monitors of all versions. + */ + elseif($iAppId) + { + $hResult = query_parameters("SELECT userId + FROM appMonitors + WHERE appId = '?'", + $iAppId); + } + if($hResult) + { + if(query_num_rows($hResult) > 0) + { + while($oRow = query_fetch_object($hResult)) + $aUserId[] = $oRow->userId; + } + } + + /* + * Retrieve administrators. + */ + $hResult = query_parameters("SELECT * FROM user_privs WHERE priv = 'admin'"); + if(query_num_rows($hResult) > 0) + { + while($oRow = query_fetch_object($hResult)) + { + $i = array_search($oRow->userid, $aUserId); + + // if we didn't find this entry in the $aUserId + // array then we should add it + if($i === false) + $aUserId[] = $oRow->userid; + } + } + + // go through the email entries and only add the emails for the users + // that want to receive it + if (sizeof($aUserId) > 0) + { + foreach($aUserId as $iUserId) + { + $oUser = new User($iUserId); + if ($oUser->wantsEmail()) + $sRetval .= $oUser->sEmail." "; + } + } + + return $sRetval; + } + + + /************************/ + /* Permission functions */ + /************************/ + + /** + * Returns true or false depending on whether the user can view the image + */ + function canViewImage($iImageId) + { + $oScreenshot = new Screenshot($iImageId); + + if(!$oScreenshot->bQueued || + ($oScreenshot->bQueued && ($this->hasPriv("admin") || + $this->isMaintainer($oScreenshot->iVersionId) || + $this->isSuperMaintainer($oScreenshot->iAppId)))) + return true; + + return false; + } + + /***************************/ + /* application permissions */ + function canViewApplication($oApp) + { + /* If there is no id the app is not in the database, which means the current user must have created the object */ + if(!$oApp->iAppId) + return true; + + /* if the application isn't queued */ + if($oApp->objectGetState() == 'accepted') + return true; + + if($this->hasPriv("admin")) + return true; + + /* if this user is the submitter and the application is queued */ + if(($this->iUserId == $oApp->iSubmitterId) && + ($oApp->objectGetState() != 'accepted')) + return true; + + return false; + } + + /** + * Does the user have permission to modify this application? + */ + function canModifyApplication($oApp) + { + if($this->hasPriv("admin")) + return true; + + /* is this user a super maintainer of this app? */ + if($this->isSuperMaintainer($oApp->iAppId)) + return true; + + /* if the user is the submitter of the application */ + /* and the application is still queued */ + /* the user can modify the app */ + if(($this->iUserId == $oApp->iSubmitterId) && + ($oApp->objectGetState() != 'accepted')) + return true; + + return false; + } + + /** + * Can this user create applications? + */ + function canCreateApplication() + { + return $this->isLoggedIn(); + } + + /** + * Returns 'true' if the current user has the permission to delete + * this application, 'false' otherwise + */ + function canDeleteApplication($oApp) + { + if($this->hasPriv("admin")) + return true; + + /* is this the user that submitted the application and is still queued */ + if(($oApp->objectGetState() != 'accepted') && ($oApp->iSubmitterId == $this->iUserId)) + return true; + + return false; + } + + /* Can this user unQueue applications? */ + function canUnQueueApplication() + { + return $this->hasPriv("admin"); + } + + /* Can this user Requeue an application? */ + function canRequeueApplication($oApp) + { + if($oApp->objectGetState() == 'accepted') + return false; + + if($this->hasPriv("admin")) + return true; + + if(($oApp->objectGetState() != 'accepted') && ($oApp->iSubmitterId == $this->iUserId)) + return true; + + return false; + } + + /* Can the user reject application? */ + function canRejectApplication() + { + return $this->hasPriv("admin"); + } + + /***********************/ + /* version permissions */ + + function canViewVersion($oVersion) + { + /* If there is no id that means data must have been generated by the user */ + if(!$oVersion->iVersionId) + return true; + + /* if the version isn't queued */ + if($oVersion->objectGetState() == 'accepted') + return true; + + if($this->hasPriv("admin")) + return true; + + /* if the user is the submitter and the version is still queued */ + if(($this->iUserId == $oVersion->iSubmitterId) && + ($oVersion->objectGetState() != 'accepted')) + return true; + + /* if this user supermaintains the application this version belongs to */ + if($this->isSupermaintainer($oVersion->iAppId)) + return true; + + return false; + } + + /** + * Does the user have permission to modify on this version? + */ + function hasAppVersionModifyPermission($oVersion) + { + if(!$this->isLoggedIn()) + return false; + + if($this->hasPriv("admin")) + return true; + + if($this->isSuperMaintainer($oVersion->iAppId)) + return true; + + if($this->isMaintainer($oVersion->iVersionId)) + return true; + + /* the version is queued and the user is the submitter */ + if(($oVersion->objectGetState() != 'accepted') && ($this->iUserId == $oVersion->iSubmitterId)) + return true; + + return false; + } + + /** + * Can this user create a version? + */ + function canCreateVersion() + { + return $this->isLoggedIn(); + } + + /** + * Returns 'true' if the current user has the permission to delete + * this version, 'false' otherwise + */ + function canDeleteVersion($oVersion) + { + if($this->hasPriv("admin")) + return true; + + /* if the app is anything other than not queued and if the user is the submitter */ + /* then allow the user to delete the app */ + if(($oVersion->objectGetState() != 'accepted') && ($oVersion->iSubmitterId == $this->iUserId)) + return true; + + /* is this user a supermaintainer of the application this version is under? */ + if($this->isSuperMaintainer($oVersion->iAppId)) + return true; + + return false; + } + + /** + * Can the user unqueue this version? + */ + function canUnQueueVersion($oVersion) + { + if($this->hasPriv("admin")) + return true; + + if($this->hasAppVersionModifyPermission($oVersion)) + return true; + + return false; + } + + /** + * Can the user reject this version? + */ + function canRejectVersion($oVersion) + { + if($this->hasPriv("admin")) + return true; + + if($this->hasAppVersionModifyPermission($oVersion)) + return true; + + return false; + } + + /** + * Can the user reject this version? + */ + function canRequeueVersion($oVersion) + { + if($this->hasPriv("admin")) + return true; + + if($this->hasAppVersionModifyPermission($oVersion)) + return true; + + if(($this->iUserId == $oVersion->iSubmitterId) && + ($oVersion->objectGetState() != 'accepted')) + return true; + + return false; + } + + function objectMakeUrl() + { + if(!$this->iUserId) + return; + + $sUrl = BASE."contact.php?iRecipientId=$this->iUserId"; + return $sUrl; + } + + function objectMakeLink() + { + if(!$this->iUserId) + return $this->sRealname; + + $sLink = "objectMakeUrl()."\">$this->sRealname"; + return $sLink; + } +} + +?> diff --git a/include/util.php b/include/util.php new file mode 100644 index 0000000..a8bce6c --- /dev/null +++ b/include/util.php @@ -0,0 +1,1073 @@ +logged in to perform that operation."; + } + header("HTTP/1.0 404 Object not found or user is not logged in"); + apidb_header("Oops"); + echo "
    $text
    \n"; + echo "

    $message

    \n"; + apidb_footer(); + exit; +} + +/** + * redirect to $url + */ +function util_redirect_and_exit($url) +{ + header("Location: ".html_entity_decode($url)); + exit; +} + +function build_urlarg($vars) +{ + $arr = array(); + while(list($key, $val) = each($vars)) + { + if(is_array($val)) + { + while(list($idx, $value) = each($val)) + { + //echo "Encoding $key / $value
    "; + $arr[] = rawurlencode($key."[]")."=".rawurlencode($value); + } + } else + { + $arr[] = $key."=".rawurlencode($val); + } + } + return implode("&", $arr); +} + +/* + * return all values of a mapping as an array + */ +function values($arr) +{ + $res = array(); + while(list($k, $v) = each($arr)) + $res[] = $v; + return $res; +} + +/* Display a login form */ +function login_form($bShowHeader = true) +{ + global $aClean; + $aClean['sReturnTo'] = urlencode($_SERVER['REQUEST_URI']); + + if($bShowHeader) + apidb_header("Login"); + include(BASE."include/"."form_login.php"); + + if($bShowHeader) + apidb_footer(); +} + +// print the month, day, year, hour, minute, second +function print_date($sTimestamp) +{ + return date("F d Y H:i:s", $sTimestamp); +} + +// print the month, day and year +function print_short_date($sTimestamp) +{ + return date("F d Y", $sTimestamp); +} + +function mysqltimestamp_to_unixtimestamp($sTimestamp) +{ + $sResult = mysql_get_server_info(); + $fVersion = substr($sResult, 0, 3); + + /* This differs between MySQL versions, newer ones are in the form + yyyy-mm-dd hh:mm:ss */ + if($fVersion >= 4.1) + { + $iDay = substr($sTimestamp, 8, 2); + $iMonth = substr($sTimestamp, 5, 2); + $iYear = substr($sTimestamp, 0, 4); + $iHours = substr($sTimestamp, 11, 2); + $iMinutes = substr($sTimestamp, 14, 2); + $iSeconds = substr($sTimestamp, 17, 2); + } else + /* The old ones are in the form yyyymmddhhmmss */ + { + $iDay = substr($sTimestamp,6,2); + $iMonth = substr($sTimestamp,4,2); + $iYear = substr($sTimestamp,0,4); + $iHours = substr($sTimestamp,8,2); + $iMinutes = substr($sTimestamp,10,2); + $iSeconds = substr($sTimestamp,12,2); + } + return mktime($iHours, $iMinutes, $iSeconds, $iMonth, $iDay, $iYear); +} + +function mysqldatetime_to_unixtimestamp($sDatetime) +{ + return strtotime($sDatetime); +} + +function get_remote() +{ + global $REMOTE_HOST, $REMOTE_ADDR; + + if($REMOTE_HOST) + $ip = $REMOTE_HOST; + else + $ip = $REMOTE_ADDR; + + return $ip; +} + +function htmlify_urls($text) +{ + //FIXME: wonder what the syntax is, this doesn't seem to work + // $text = strip_tags($text, ",,,
      ,
    • "); + + // html-ify urls + $urlreg = "([a-zA-Z]+://([^\t\r\n ]+))"; + $text = ereg_replace($urlreg, " \\2 ", $text); + + $emailreg = "([a-zA-Z0-9_%+.-]+@[^\t\r\n ]+)"; + $text = ereg_replace($emailreg, " \\1", $text); + + $text = str_replace("\n", "
      ", $text); + + return $text; +} + +// open file and display contents of selected tag +function get_xml_tag ($file, $mode = null) +{ + if ($mode and file_exists($file)) + { + $fp = @fopen($file, "r"); + $data = fread($fp, filesize($file)); + @fclose($fp); + if (eregi("<" . $mode . ">(.*)", $data, $out)) + { + return $out[1]; + } + } + else + { + return null; + } +} + +/* bugzilla functions */ + +// Returns an array containg the Wine versions stored in our Bugzilla DB +// If bReturnIds is true, version ids are returned instead of names +function get_bugzilla_versions($bReturnIds = false) +{ + $sFetchColumn = $bReturnIds ? 'id' : 'value'; + $aVersions = array(); + $sTable = BUGZILLA_DB.".versions"; + + // The empty string will fetch the most recent versions + $aBranches = array(''); + + // Get a list of stable branches + if(STABLE_BRANCHES) + $aBranches = array_merge($aBranches, explode(',', STABLE_BRANCHES)); + + foreach($aBranches as $sBranch) + { + $sWhere = "WHERE product_id =".BUGZILLA_PRODUCT_ID." AND value LIKE '$sBranch%'"; + $sQuery = "SELECT $sFetchColumn FROM $sTable $sWhere ORDER BY id desc limit 6"; + $hResult = query_bugzilladb($sQuery); + if($hResult) + { + while(list($sValue) = query_fetch_row($hResult)) + { + if(!in_array($sValue, $aVersions)) + $aVersions[] = $sValue; + } + } + } + + return $aVersions; +} + +// Returns an array containing the IDs of the Wine versions stored in Bugzilla +function get_bugzilla_version_ids() +{ + return get_bugzilla_versions(true); +} + +// $sVarname - name of the selection array that this function will output +// this is the name to use to retrieve the selection on the form postback +// $sSelectedValue - the currently selected entry +// returns a string that contains the version list output +function make_bugzilla_version_list($sVarname, $sSelectedValue) +{ + $sStr = ""; + + // build the list of versions + $aVersions = get_bugzilla_versions(); + + // build the selection array + $sStr.= "\n"; + + return $sStr; +} + +// returns a string containing the html for the maintainer rating list +function make_maintainer_rating_list($varname, $cvalue) +{ + $sTxt = "  \n"; + + return $sTxt; +} + +/* Get the element with specified key from an array if it is defined */ +function getInput($sVar, $aInput) +{ + if(array_key_exists($sVar, $aInput)) + return $aInput[$sVar]; + + return null; +} + +/* Get the number of users in the database */ +function getNumberOfComments() +{ + $hResult = query_parameters("SELECT count(*) as num_comments FROM appComments;"); + $oRow = query_fetch_object($hResult); + return $oRow->num_comments; +} + +/* used by outputTopXRowAppsFromRating() to reduce duplicated code */ +function outputTopXRow($oRow) +{ + $oVersion = new Version($oRow->versionId); + $oApp = new Application($oVersion->iAppId); + $img = Screenshot::get_random_screenshot_img(null, $oRow->versionId, false); // image, disable extra formatting + + // create the table row + $oTableRow = new TableRow(); + $oTableRow->SetClass("white"); + + // create the cells that represent the row + $oTableCell = new TableCell(version::fullNameLink($oVersion->iVersionId)); + $oTableCell->SetClass("app_name"); + $oTableRow->AddCell($oTableCell); + $oTableRow->AddTextCell(util_trim_description($oApp->sDescription)); + $oTableCell = new TableCell($img); + $oTableCell->SetStyle("text-align:center;"); + $oTableRow->AddCell($oTableCell); + + // create a new TableRowHighlight instance + $oHighlightColor = new color(0xf0, 0xf6, 0xff); + $oInactiveColor = new color(); + $oInactiveColor->SetColorByName("White"); + $oTableRowHighlight = new TableRowHighlight($oHighlightColor, $oInactiveColor); + + // create a new TableRowclick + $oTableRowClick = new TableRowClick($oVersion->objectMakeUrl()); + $oTableRowClick->SetHighlight($oTableRowHighlight); + + // set the click property of the html table row + $oTableRow->SetRowClick($oTableRowClick); + + // output the entire table row + echo $oTableRow->GetString(); + echo "\n"; +} + +/* Output the rows for the Top-X tables on the main page */ +function outputTopXRowAppsFromRating($sRating, $iNumApps) +{ + /* clean the input values so we can continue to use query_appdb() */ + $sRating = query_escape_string($sRating); + $iNumApps = query_escape_string($iNumApps); + + /* list of versionIds we've already output, so we don't output */ + /* them again when filling in any empty spots in the list */ + $aVersionId = array(); + + $sQuery = "SELECT appVotes.versionId, COUNT( appVotes.versionId ) AS c + FROM appVotes, appVersion + WHERE appVersion.rating = '?' + AND appVersion.versionId = appVotes.versionId + AND appVersion.state = 'accepted' + GROUP BY appVotes.versionId + ORDER BY c DESC + LIMIT ?"; + $hResult = query_parameters($sQuery, $sRating, $iNumApps); + $iNumApps -= query_num_rows($hResult); /* take away the rows we are outputting here */ + while($oRow = query_fetch_object($hResult)) + { + /* keep track of the apps we've already output */ + $aVersionId[] = $oRow->versionId; + outputTopXRow($oRow); + } + + /* if we have no more app entries we should stop now and save ourselves a query */ + if(!$iNumApps) return; + + /* if we have any empty spots in the list, get these from applications with images */ + $sQuery = "SELECT DISTINCT appVersion.versionId + FROM appVersion, appData + WHERE appVersion.rating = '$sRating' + AND appVersion.versionId = appData.versionId + AND appVersion.state = 'accepted' + AND appData.type = 'screenshot' + AND appData.state = 'accepted'"; + + /* make sure we exclude any apps we've already output */ + foreach($aVersionId as $key=>$value) + $sQuery.="AND appVersion.versionId != '".$value."' "; + + $sQuery .= " LIMIT $iNumApps"; + + /* get the list that will fill the empty spots */ + $hResult = query_appdb($sQuery); + while($oRow = query_fetch_object($hResult)) + outputTopXRow($oRow); +} + +/* return true if this word is in the list of words to ignore */ +function isIgnoredWord($sWord) +{ + $ignore_words = array('I', 'a', 'about', 'an', 'are', 'as', 'at', 'be', 'by', 'com', + 'de', 'en', 'for', 'from', 'how', 'in', 'is', 'it', 'la', 'of', + 'on', 'or', 'that', 'the', 'this', 'to', 'was', 'what', 'when', + 'where', 'who', 'will', 'with', 'und', 'the', 'www', 'game'); + + $found = false; + + /* search each item in the $ignore_words array */ + foreach($ignore_words as $ik=>$iv) + { + /* if we find a match we should flag it as so */ + if(strtoupper($sWord) == strtoupper($iv)) + { + $found = true; + break; /* break out of this foreach loop */ + } + } + + return $found; +} + +/* remove common words from $search_words to improve our searching results */ +function cleanupSearchWords($search_words) +{ + /* trim off leading and trailing spaces in $search_words */ + /* to improve matching accuracy */ + $search_words = trim($search_words); + + $filtered_search = ""; + + /* search each word in $search_words */ + $split_words = split(" ", $search_words); + + $removed_words = ''; + foreach($split_words as $key=>$value) + { + /* see if this word is in the ignore list */ + /* we remove any of the words in the ignore_words array. these are far too common */ + /* and will result in way too many matches if we leave them in */ + /* We will also remove any single letter search words */ + $found = isIgnoredWord($value); + + /* remove all single letters */ + if((strlen($value) == 1) && !is_numeric($value)) + $found = true; + + /* if we didn't find this word, keep it */ + if($found == false) + { + if($filtered_search) + $filtered_search.=" $value"; + else + $filtered_search="$value"; + } else + { + if($removed_words == "") + $removed_words.="'".$value."'"; + else + $removed_words.=", '".$value."'"; + } + } + + /* replace the existing search with the filtered_search */ + $search_words = $filtered_search; + + return $search_words; +} + +/* A common error for users is to submit a new app entry for a new app version, + such as C&C Red Alert 2 Yuri's Revenge when we already have C&C Red Alert 2. + Search for the first word in the search query. + iExcludeAppId can be useful when showing a list of duplicate entries */ +function searchForApplicationPartial($sSearchWords, $iExcludeAppId = null) +{ + /* This would yield too many results and stress MySQL */ + if(strlen($sSearchWords) < 4) + return null; + + $sSearchWords = cleanupSearchWords($sSearchWords); + + /* The search string may have gotten shorter; even empty */ + if(strlen($sSearchWords) < 4) + return null; + + $aWords = explode(' ', $sSearchWords); + $sSearchString = ''; + $sEnsureExactWord = ''; // Used to ensure we don't match partial words when prepending + // a wildcard to the search string + + for($i = 0; $i < sizeof($aWords); $i++) + { + if($i) + $sSearchString .= '%'; + $sSearchString .= $aWords[$i]; + if(strlen($aWords[$i]) > 4) + { + if($i < (sizeof($aWords) - 1)) + $sEnsureExactWord = ' '; + break; + } + } + + $sExcludeApps = ''; + if($iExcludeAppId && is_numeric($iExcludeAppId)) + $sExcludeApps = " AND appId != '$iExcludeAppId' "; + + $hResult = query_parameters("SELECT * FROM appFamily WHERE state = 'accepted' AND + (appName LIKE '?%' OR appName LIKE '?')$sExcludeApps", $sSearchString.$sEnsureExactWord, $sSearchString); + + return $hResult; +} + +/* search the database and return a hResult from the query_appdb() */ +function searchForApplication($search_words, $iExcludeAppId = null) +{ + /* This would yield too many results and stress MySQL */ + if(strlen($search_words) < 4) + return null; + + /* cleanup search words */ + $search_words = cleanupSearchWords($search_words); + + /* The search string may have gotten shorter; even empty */ + if(strlen($search_words) < 4) + return null; + + /* remove any search words less than 4 letters */ + $split_words = array(); + $split_search_words = split(" ", $search_words); + foreach($split_search_words as $key=>$value) + { + if(strlen($value) >= 4) + array_push($split_words, $value); + } + + $search_words = str_replace(' ', '%', query_escape_string($search_words)); + + $sExcludeApps = ''; + if($iExcludeAppId && is_numeric($iExcludeAppId)) + $sExcludeApps = " AND appId != '$iExcludeAppId' "; + + /* base query */ + $sQuery = "SELECT * + FROM appFamily + WHERE appName != 'NONAME' + AND appFamily.state = 'accepted' + AND (appName LIKE '%?%' + OR keywords LIKE '%?%'"; + + $sQuery.=" ) $sExcludeApps ORDER BY appName"; + + $hResult = query_parameters($sQuery, $search_words, $search_words); + return $hResult; +} + +function outputSearchTableForhResult($search_words, $hResult) +{ + if(($hResult == null) || (query_num_rows($hResult) == 0)) + { + // do something + echo html_frame_start("","98%"); + echo "No matches found for '". urlencode($search_words) . "'\n"; + echo html_frame_end(); + } else + { + echo html_frame_start("","98%","",0); + echo "\n\n"; + + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c = 0; + while($oRow = query_fetch_object($hResult)) + { + $oApp = new application($oRow->appId); + //skip if a NONAME + if ($oRow->appName == "NONAME") { continue; } + + //set row color + $bgcolor = ($c % 2) ? 'color0' : 'color1'; + + //count versions + $hResult2 = query_parameters("SELECT count(*) as versions FROM appVersion WHERE appId = '?' AND versionName != 'NONAME' and state = 'accepted'", + $oRow->appId); + $y = query_fetch_object($hResult2); + + //display row + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n\n"; + + $c++; + } + + echo "\n"; + echo "
      Application NameDescriptionNo. Versions
      ".html_ahref($oRow->appName,$oApp->objectMakeUrl())."".util_trim_description($oRow->description)."$y->versions  
      $c match(es) found
      \n\n"; + echo html_frame_end(); + } +} + +/* pass in $isVersion of true if we are processing changes for an app version */ +/* or false if processing changes for an application family */ +function process_app_version_changes($bIsVersion) +{ + global $aClean; + + /* load up the version or application depending on which values are set */ + if($bIsVersion) + $oVersion = new Version($aClean['iVersionId']); + else + $oApp = new Application($aClean['iAppId']); + + // commit changes of form to database + if(($aClean['sSubmit'] == "Update Database") && $bIsVersion) /* is a version */ + { + $oVersion->GetOutputEditorValues($aClean); + $oVersion->update(); + } else if(($aClean['sSubmit'] == "Update Database") && !$bIsVersion) /* is an application */ + { + $oApp->GetOutputEditorValues($aClean); + $oApp->update(); + } +} + +function perform_search_and_output_results($search_words) +{ + echo "Searching for '".$search_words."'"; + + echo "
      Like matches
      "; + $hResult = searchForApplication($search_words); + outputSearchTableForhResult($search_words, $hResult); + + echo "
      Partial matches
      "; + $hResult = searchForApplicationPartial($search_words); + outputSearchTableForhResult($search_words, $hResult); +} + +function display_page_range($iCurrentPage=1, $iPageRange=1, $iTotalPages=1, $sLinkurl=NULL) +{ + if($sLinkurl==NULL) + { + $sLinkurl = $_SERVER['PHP_SELF']."?"; + } + /* display the links to each of these pages */ + $iCurrentPage = max(1,(min($iCurrentPage,$iTotalPages))); + $iPageRange = min($iPageRange,$iTotalPages); + + if($iCurrentPage <= ceil($iPageRange/2)) + { + $iStartPage = 1; + $iEndPage = $iPageRange; + } else + { + if($iCurrentPage + ($iPageRange/2) > $iTotalPages) + { + $iStartPage = $iTotalPages - $iPageRange; + $iEndPage = $iTotalPages; + } else + { + $iStartPage = $iCurrentPage - floor($iPageRange/2); + $iEndPage = $iCurrentPage + floor($iPageRange/2); + } + } + $iStartPage = max(1,$iStartPage); + + if($iCurrentPage != 1) + { + echo "|< "; + $iPreviousPage = $iCurrentPage - 1; + echo "< "; + } else + { + echo "|< < "; + } + /* display the desired range */ + for($iPg = $iStartPage; $iPg <= $iEndPage; $iPg++) + { + if($iPg != $iCurrentPage) + echo "$iPg "; + else + echo "$iPg "; + } + + if($iCurrentPage < $iTotalPages) + { + $iNextPage = $iCurrentPage + 1; + echo "> "; + echo ">| "; + } else + { + echo "> >|"; + } +} + +// Expand a path like /something/somedirectory/../ to /something +// from http://us2.php.net/realpath +function SimplifyPath($path) { + $dirs = explode('/',$path); + + for($i=0; $igetPref('htmleditor', 'for supported browsers')) + { + case 'never': + return; + case 'for supported browsers': + if(strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') || + strstr($_SERVER['HTTP_USER_AGENT'], 'Konqueror')) + { + return; + } + break; + case 'always': + break; + } + + echo ' + '; + + echo ' + + + + + '; + + $outputIndex++; /* increment the output index */ +} + +/** + * Cuts the link text to the specified number of chars if it's longer, + * and adds an ellipsis + */ +function trimmed_link($shUrl, $iLength) +{ + $shText = $shUrl; + $shEnd = ''; + if(strlen($shUrl) > $iLength) + { + $shText = substr($shUrl, 0, $iLength); + $shText .= '...'; + } + return "$shText"; +} + +/** + * Remove html formatting from description and extract the first part of the description only. + * This is to be used for search results, application summary tables, etc. + */ +function util_trim_description($sDescription) +{ + // 1) maybe it's an html description and lines are separated with tags + $aReplace = array('
      ','
      ','

      '); + $sDescription = str_replace($aReplace, "\n", $sDescription); + + // 2) let's split the dsecription into lines + $aDesc = explode("\n",trim($sDescription)); + + // 3) Avoid empty lines + for($i = 0; $i < sizeof($aDesc); $i++) + if(($sText = trim(strip_tags($aDesc[$i])))) + return $sText; + + return ''; +} + +/* This allows us to pass on the current URL to the login form so that the user is returned + to the current page once he has logged in */ +function login_url() +{ + $sCurrentUrl = urlencode($_SERVER['REQUEST_URI']); + $sLoginUrl = BASE."account.php?sCmd=login"; + + /* If we are on the login page that means the URL already contains an sReturnTo value, + and we don't want two. Besides, there is little point in redirecting to the login page + after login. */ + if(!strpos($sCurrentUrl, "sReturnTo") && !strpos($sCurrentUrl, "account.php")) + $sLoginUrl .= "&sReturnTo=".$sCurrentUrl; + + return $sLoginUrl; +} + +// representation of an html color value +class color +{ + var $iRed; + var $iGreen; + var $iBlue; + + function color($iRed = 0, $iGreen = 0, $iBlue = 0) + { + $this->iRed = $iRed; + $this->iGreen = $iGreen; + $this->iBlue = $iBlue; + } + + function SetColorByName($sColorName) + { + switch(strtolower($sColorName)) + { + case "platinum": + $this->iRed = 0xEC; + $this->iGreen = 0xEC; + $this->iBlue = 0xEC; + break; + case "gold": + $this->iRed = 0xFF; + $this->iGreen = 0xF6; + $this->iBlue = 0x00; + break; + case "silver": + $this->iRed = 0xC0; + $this->iGreen = 0xC0; + $this->iBlue = 0xC0; + break; + case "bronze": + $this->iRed = 0xFC; + $this->iGreen = 0xBA; + $this->iBlue = 0x0A; + break; + case "garbage": + $this->iRed = 0x99; + $this->iGreen = 0x96; + $this->iBlue = 0x66; + break; + case "white": + $this->iRed = 0xff; + $this->iGreen = 0xff; + $this->iBlue = 0xff; + break; + case "color0": + $this->iRed = 0xe0; + $this->iGreen = 0xe0; + $this->iBlue = 0xe0; + break; + case "color1": + $this->iRed = 0xc0; + $this->iGreen = 0xc0; + $this->iBlue = 0xc0; + break; + default: + break; + } + } + + // convert the color value into a html rgb hex string + function GetHexString() + { + return sprintf("#%02X%02X%02X", $this->iRed, $this->iGreen, $this->iBlue); + } + + // add $iAmount to each color value, maxing out at 0xFF, the largest + // color value allowed + function Add($iAmount) + { + if($this->iRed + $iAmount > 0xFF) + $this->iRed = 0xFF; + else + $this->iRed += $iAmount; + + if($this->iGreen + $iAmount > 0xFF) + $this->iGreen = 0xFF; + else + $this->iGreen += $iAmount; + + if($this->iBlue + $iAmount > 0xFF) + $this->iBlue = 0xFF; + else + $this->iBlue += $iAmount; + } +} + +?> diff --git a/include/vendor.php b/include/vendor.php new file mode 100644 index 0000000..6242978 --- /dev/null +++ b/include/vendor.php @@ -0,0 +1,485 @@ +iVendorId = $oRow->vendorId; + $this->sName = $oRow->vendorName; + $this->sWebpage = $oRow->vendorURL; + $this->sState = $oRow->state; + } + + /* + * We fetch applicationsIds. + */ + $sQuery = "SELECT appId + FROM appFamily + WHERE vendorId = '?' ORDER by appName"; + if($hResult = query_parameters($sQuery, $this->iVendorId)) + { + while($oRow = query_fetch_object($hResult)) + { + $this->aApplicationsIds[] = $oRow->appId; + } + } + } + + /** + * Creates a new vendor. + * + * NOTE: If creating a vendor with the same name as an existing vendor + * we retrieve the existing vendors information and return true, + * even though we didn't create the vendor, this makes it easier + * for the user of the vendor class. + */ + function create() + { + /* Check for duplicates */ + $hResult = query_parameters("SELECT * FROM vendor WHERE vendorName = '?'", + $this->sName); + if($hResult && $oRow = query_fetch_object($hResult)) + { + if(query_num_rows($hResult)) + { + $this->vendor($oRow->vendorId); + + /* Even though we did not create a new vendor, the caller is provided + with an id and can proceed as normal, so we return TRUE */ + return TRUE; + } + } + + $hResult = query_parameters("INSERT INTO vendor (vendorName, vendorURL, state) ". + "VALUES ('?', '?', '?')", + $this->sName, $this->sWebpage, + $this->mustBeQueued() ? 'queued' : 'accepted'); + if($hResult) + { + $this->iVendorId = query_appdb_insert_id(); + $this->vendor($this->iVendorId); + return true; + } + else + { + addmsg("Error while creating a new developer.", "red"); + return false; + } + } + + /** + * Un-queue vendor + * Returns TRUE or FALSE + */ + function unQueue() + { + $hResult = query_parameters("UPDATE vendor SET state = '?' WHERE vendorId = '?'", + 'accepted', $this->iVendorId); + + if(!$hResult) + return FALSE; + + $this->sState = 'accepted'; + + return TRUE; + } + + /** + * Update vendor. + * Returns true on success and false on failure. + */ + function update() + { + if(!$this->iVendorId) + return $this->create(); + + if($this->sName) + { + if (!query_parameters("UPDATE vendor SET vendorName = '?' WHERE vendorId = '?'", + $this->sName, $this->iVendorId)) + return false; + $this->sName = $sName; + } + + if($this->sWebpage) + { + if (!query_parameters("UPDATE vendor SET vendorURL = '?' WHERE vendorId = '?'", + $this->sWebpage, $this->iVendorId)) + return false; + $this->sWebpage = $sWebpage; + } + return true; + } + + /** + * Remove the vendor from the database. + */ + function purge() + { + if(sizeof($this->aApplicationsIds)>0) + { + return FALSE; + } else + { + $sQuery = "DELETE FROM vendor + WHERE vendorId = '?' + LIMIT 1"; + if(query_parameters($sQuery, $this->iVendorId)) + { + return TRUE; + } + + return FALSE; + } + + return false; + } + + /** + * Flag the vendor as deleted + */ + function delete() + { + if(sizeof($this->aApplicationsIds)>0) + { + return FALSE; + } else + { + $sQuery = "UPDATE vendor SET state = 'deleted' + WHERE vendorId = '?' + LIMIT 1"; + if(query_parameters($sQuery, $this->iVendorId)) + { + return TRUE; + } + + return FALSE; + } + + return false; + } + + function checkOutputEditorInput($aClean) + { + if(!getInput('sVendorName', $aClean)) + return '

    • You need to enter the developer\'s name
    • '; + } + + function outputEditor() + { + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetBorder(0); + $oTable->SetCellPadding(2); + $oTable->SetCellSpacing(0); + + // name + $oTableRow = new TableRow(); + + $oTableCell = new TableCell("Developer name:"); + $oTableCell->SetAlign("right"); + $oTableCell->SetClass("color0"); + $oTableCell->SetBold(true); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell(''); + $oTableCell->SetClass("color0"); + $oTableRow->AddCell($oTableCell); + + $oTable->AddRow($oTableRow); + + // Url + $oTableRow = new TableRow(); + + $oTableCell = new TableCell("Developer URL:"); + $oTableCell->SetAlign("right"); + $oTableCell->SetClass("color0"); + $oTableCell->SetBold(true); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell(''); + $oTableCell->SetClass("color0"); + $oTableRow->AddCell($oTableCell); + + $oTable->AddRow($oTableRow); + + echo $oTable->GetString(); + + echo '',"\n"; + } + + public static function objectGetSortableFields() + { + return array('vendorName'); + } + + public static function objectGetDefaultSort() + { + return 'vendorName'; + } + + function objectGetFilterInfo() + { + $oFilter = new FilterInterface(); + + $oFilter->AddFilterInfo('vendorName', 'Name', array(FILTER_CONTAINS, FILTER_STARTS_WITH, FILTER_ENDS_WITH), FILTER_VALUES_NORMAL); + return $oFilter; + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = 'vendorName', $bAscending = TRUE, $oFilter = null) + { + /* Not implemented */ + if($sState == 'rejected') + return FALSE; + + $sWhereFilter = $oFilter ? $oFilter->getWhereClause() : ''; + $sOrder = $bAscending ? 'ASC' : 'DESC'; + + if($sWhereFilter) + $sWhereFilter = " AND $sWhereFilter"; + + if(!$iRows) + $iRows = Vendor::objectGetEntriesCount($sState, $oFilter); + + $hResult = query_parameters("SELECT * FROM vendor WHERE state = '?' $sWhereFilter + ORDER BY $sOrderBy $sOrder LIMIT ?,?", + $sState, $iStart, $iRows); + + if(!$hResult) + return FALSE; + + return $hResult; + } + + function objectGetHeader() + { + $oTableRow = new TableRowSortable(); + + $oTableRow->AddSortableTextCell('Name', 'vendorName'); + + $oTableCell = new TableCell('Applications'); + $oTableRow->AddCell($oTableCell); + + $oTableRow->AddTextCell("Website"); + + return $oTableRow; + } + + // returns an OMTableRow instance + function objectGetTableRow() + { + $bDeleteLink = sizeof($this->aApplicationsIds) ? FALSE : TRUE; + + // create the html table row + $oTableRow = new TableRow(); + $oTableRow->AddTextCell($this->objectMakeLink()); + + $oTableCell = new TableCell(sizeof($this->aApplicationsIds)); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell($this->sWebpage); + $oTableCell->SetCellLink($this->sWebpage); + $oTableRow->AddCell($oTableCell); + + // create the object manager specific row + $oOMTableRow = new OMTableRow($oTableRow); + $oOMTableRow->SetHasDeleteLink($bDeleteLink); + + return $oOMTableRow; + } + + public function objectGetState() + { + return $this->sState; + } + + function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + return TRUE; + else + return FALSE; + } + + function mustBeQueued() + { + if($_SESSION['current']->hasPriv("admin")) + return FALSE; + else + return TRUE; + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return new mailOptions(); + } + + function objectGetChildren($bIncludeDeleted = false) + { + /* We don't have any */ + return array(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + /* We don't send notification mails */ + return array(null, null, null); + } + + function objectGetSubmitterId() + { + /* We don't record the submitter id */ + return NULL; + } + + function getOutputEditorValues($aClean) + { + $this->sName = $aClean['sVendorName']; + $this->sWebpage = $aClean['sVendorWebpage']; + } + + function display() + { + echo 'Developer name: '.$this->sName,"\n"; + if($this->canEdit()) + { + echo "[iVendorId&sTitle=Edit%20Developer\">edit]"; + } + + echo '
      ',"\n"; + if ($this->sWebpage) + { + echo 'Developer URL: '. + $this->sWebpage.'
      ',"\n"; + } + + + if($this->aApplicationsIds) + { + echo '
      Applications by '.$this->sName.'
        ',"\n"; + foreach($this->aApplicationsIds as $iAppId) + { + $oApp = new Application($iAppId); + + if($oApp->objectGetState() == 'accepted') + echo '
      1. '.$oApp->objectMakeLink().'
      2. ',"\n"; + } + echo '
      ',"\n"; + } + } + + public function objectGetClassDisplayName() + { + return 'developer'; + } + + /* Make a URL for viewing the specified vendor */ + function objectMakeUrl() + { + $oManager = new objectManager("vendor", "View Developer"); + return $oManager->makeUrl("view", $this->iVendorId); + } + + /* Make a HTML link for viewing the specified vendor */ + function objectMakeLink() + { + return "objectMakeUrl()."\">$this->sName"; + } + + function objectGetEntriesCount($sState, $oFilter = null) + { + /* Not implemented */ + if($sState == 'rejected') + return FALSE; + + $sWhereClause = $oFilter ? $oFilter->getWhereClause() : ''; + if($sWhereClause) + $sWhereClause = " AND $sWhereClause"; + + $hResult = query_parameters("SELECT COUNT(vendorId) as count FROM vendor WHERE state = '?' $sWhereClause", + $sState); + + if(!$hResult) + return FALSE; + + if(!$oRow = query_fetch_object($hResult)) + return FALSE; + + return $oRow->count; + } + + function allowAnonymousSubmissions() + { + return FALSE; + } + + function objectMoveChildren($iNewId) + { + /* Keep track of how many children we have modified */ + $iCount = 0; + + foreach($this->aApplicationsIds as $iAppId) + { + $oApp = new application($iAppId); + $oApp->iVendorId = $iNewId; + if($oApp->update(TRUE)) + $iCount++; + else + return FALSE; + } + + return $iCount; + } + + function objectGetId() + { + return $this->iVendorId; + } + + function objectGetItemsPerPage($sState = 'accepted') + { + $aItemsPerPage = array(25, 50, 100, 200); + $iDefaultPerPage = 25; + return array($aItemsPerPage, $iDefaultPerPage); + } + + function objectShowAddEntry() + { + return TRUE; + } +} + +?> diff --git a/include/version.php b/include/version.php new file mode 100644 index 0000000..6af2864 --- /dev/null +++ b/include/version.php @@ -0,0 +1,1903 @@ +aTestResults = array(); // should always be an array + // we are working on an existing version + if(!$iVersionId && !$oRow) + return; + + /* + * We fetch the data related to this version. + */ + if(!$oRow) + { + $sQuery = "SELECT * + FROM appVersion + WHERE versionId = '?'"; + if($hResult = query_parameters($sQuery, $iVersionId)) + $oRow = query_fetch_object($hResult); + } + + if($oRow) + { + $this->iVersionId = $oRow->versionId; + $this->iAppId = $oRow->appId; + $this->iSubmitterId = $oRow->submitterId; + $this->sSubmitTime = $oRow->submitTime; + $this->sName = $oRow->versionName; + $this->sDescription = $oRow->description; + $this->sTestedRelease = $oRow->ratingRelease; + $this->sTestedRating = $oRow->rating; + $this->sState = $oRow->state; + $this->sLicense = $oRow->license; + $this->iObsoleteBy = $oRow->obsoleteBy; + } + } + + + /** + * Creates a new version. + */ + public function create() + { + if(!$_SESSION['current']->canCreateVersion()) + return; + + $oApp = new application($this->iAppId); + if($oApp->objectGetState() != 'accepted') + $this->sState = 'pending'; + else + $this->sState = $this->mustBeQueued() ? 'queued' : 'accepted'; + + $hResult = query_parameters("INSERT INTO appVersion + (versionName, description, ratingRelease, + rating, appId, submitTime, submitterId, + state, license) + VALUES ('?', '?', '?', '?', '?', ?, '?', '?', '?')", + $this->sName, $this->sDescription, $this->sTestedRelease, + $this->sTestedRating, $this->iAppId, "NOW()", + $_SESSION['current']->iUserId, $this->sState, + $this->sLicense); + + if($hResult) + { + $this->iVersionId = query_appdb_insert_id(); + $this->Version($this->iVersionId); + $this->SendNotificationMail(); + + /* Submit maintainer request if asked to */ + switch($this->iMaintainerRequest) + { + case MAINTAINER_REQUEST; + $oMaintainer = new Maintainer(); + $oMaintainer->iAppId = $this->iAppId; + $oMaintainer->iVersionId = $this->iVersionId; + $oMaintainer->iUserId = $_SESSION['current']->iUserId; + $oMaintainer->sMaintainReason = "This user submitted the version;". + "auto-queued."; + $oMaintainer->bSuperMaintainer = 0; + $oMaintainer->create(); + break; + + case MONITOR_REQUEST: + $oMonitor = new Monitor(); + $oMonitor->iVersionId = $this->iVersionId; + $oMonitor->iUserId = $_SESSION['current']->iUserId; + $oMonitor->iAppId = $this->iAppId; + $oMonitor->create(); + break; + } + return true; + } + else + { + addmsg("Error while creating a new version", "red"); + return false; + } + } + + + /** + * Update version. + */ + public function update($bSilent=false) + { + $sWhatChanged = ""; + + if(!$_SESSION['current']->hasAppVersionModifyPermission($this)) + return; + + $oVersion = new Version($this->iVersionId); + + if ($this->sName && ($this->sName!=$oVersion->sName)) + { + if (!query_parameters("UPDATE appVersion SET versionName = '?' WHERE versionId = '?'", + $this->sName, $this->iVersionId)) + return false; + $sWhatChanged .= "Name was changed from:\n\t'".$oVersion->sName."'\nto:\n\t'".$this->sName."'\n\n"; + } + + if ($this->sDescription && ($this->sDescription!=$oVersion->sDescription)) + { + if (!query_parameters("UPDATE appVersion SET description = '?' WHERE versionId = '?'", + $this->sDescription, $this->iVersionId)) + return false; + + if($oVersion->sDescription != "") + $sWhatChanged .= "Description was changed from\n ".$oVersion->sDescription."\n to \n".$this->sDescription.".\n\n"; + else + $sWhatChanged .= "Description was changed to \n".$this->sDescription.".\n\n"; + } + + if ($this->sTestedRelease && ($this->sTestedRelease!=$oVersion->sTestedRelease)) + { + if (!query_parameters("UPDATE appVersion SET ratingRelease = '?' WHERE versionId = '?'", + $this->sTestedRelease, $this->iVersionId)) + return false; + + if($oVersion->sTestedRelease != "") + $sWhatChanged .= "Last tested release was changed from ".$oVersion->sTestedRelease." to ".$this->sTestedRelease.".\n\n"; + else + $sWhatChanged .= "Last tested release was changed to ".$this->sTestedRelease.".\n\n"; + } + + if ($this->sTestedRating && ($this->sTestedRating!=$oVersion->sTestedRating)) + { + if (!query_parameters("UPDATE appVersion SET rating = '?' WHERE versionId = '?'", + $this->sTestedRating, $this->iVersionId)) + return false; + + if($this->sTestedRating != "") + $sWhatChanged .= "Rating was changed from ".$oVersion->sTestedRating." to ".$this->sTestedRating.".\n\n"; + else + $sWhatChanged .= "Rating was changed to ".$this->sTestedRating.".\n\n"; + } + + if ($this->iAppId && ($this->iAppId!=$oVersion->iAppId)) + { + $oAppBefore = new Application($oVersion->iAppId); + $oAppAfter = new Application($this->iAppId); + + if($oAppAfter->objectGetState() == 'accepted' && $this->sState == 'pending') + $this->sState = 'queued'; + + if (!query_parameters("UPDATE appVersion SET appId = '?', state = '?' WHERE versionId = '?'", + $this->iAppId, $this->sState, $this->iVersionId)) + return false; + + $sWhatChanged .= "Version was moved from application ".$oAppBefore->sName." to application ".$oAppAfter->sName.".\n\n"; + } + + if ($this->sLicense && ($this->sLicense!=$oVersion->sLicense)) + { + if(!query_parameters("UPDATE appVersion SET license = '?' + WHERE versionId = '?'", + $this->sLicense, $this->iVersionId)) + return FALSE; + + $sWhatChanged .= "License was changed from $oVersion->sLicense to ". + "$this->sLicense.\n\n"; + } + + if($this->iObsoleteBy != $oVersion->iObsoleteBy) + { + if(!query_parameters("UPDATE appVersion SET obsoleteBy = '?' WHERE versionId = '?'", + $this->iObsoleteBy, $this->iVersionId)) + return FALSE; + + if($this->iObsoleteBy) + $sWhatChanged .= "The version was marked as obsolete.\n\n"; + else + $sWhatChanged .= "The version is no longer marked as obsolete.\n\n"; + + if($this->iObsoleteBy) + { + query_parameters("UPDATE appVotes SET versionId = '?' WHERE versionId = '?'", + $this->iObsoleteBy, $this->iVersionId); + } + } + + if($this->objectGetState() != $oVersion->objectGetState()) + query_parameters("UPDATE appVersion SET state = '?' WHERE versionId = '?'", $this->objectGetState(), $this->objectGetId()); + + if($sWhatChanged and !$bSilent) + $this->SendNotificationMail("edit",$sWhatChanged); + return true; + } + + /** + * Removes the version from the database and + * requests the same action for child entries + */ + public function purge() + { + /* We need the versionId to continue */ + if(!$this->iVersionId) + return; + + /* is the current user allowed to delete this version? */ + if(!$_SESSION['current']->canDeleteVersion($this)) + return false; + + $bSuccess = TRUE; + + foreach($this->objectGetChildren(TRUE) as $oChild) + { + if(!$oChild->purge()) + $bSuccess = FALSE; + } + + /* now remove the version from the DB */ + $hResult = query_parameters("DELETE FROM appVersion + WHERE versionId = '?' + LIMIT 1", $this->iVersionId); + if(!$hResult) + $bSuccess = FALSE; + + return $bSuccess; + } + + /** + * Flags the version as deleted + * and request the deletion of linked elements. + */ + public function delete() + { + /* We need the versionId to continue */ + if(!$this->iVersionId) + return; + + /* is the current user allowed to delete this version? */ + if(!$_SESSION['current']->canDeleteVersion($this)) + return false; + + $bSuccess = TRUE; + + foreach($this->objectGetChildren() as $oChild) + { + if(!$oChild->delete()) + $bSuccess = FALSE; + } + + /* now flag the version as deleted */ + $hResult = query_parameters("UPDATE appVersion SET state = 'deleted' + WHERE versionId = '?' + LIMIT 1", $this->iVersionId); + if(!$hResult) + $bSuccess = FALSE; + + return $bSuccess; + } + + /** + * Move version out of the queue. + */ + public function unQueue() + { + if(!$_SESSION['current']->canUnQueueVersion($this)) + return; + + // If we are not in the queue, we can't move the version out of the queue. + if($this->sState == 'accepted') + return false; + + if(query_parameters("UPDATE appVersion SET state = '?' WHERE versionId = '?'", + 'accepted', $this->iVersionId)) + { + $this->sState = 'accepted'; + // we send an e-mail to interested people + $this->mailSubmitter("add"); + $this->SendNotificationMail(); + + /* Unqueue matching maintainer request */ + $hResultMaint = query_parameters("SELECT maintainerId FROM + appMaintainers WHERE userId = '?' AND versionId = '?'", + $this->iSubmitterId, $this->iVersionId); + + if($hResultMaint && query_num_rows($hResultMaint)) + { + $oMaintainerRow = query_fetch_object($hResultMaint); + $oMaintainer = new Maintainer($oMaintainerRow->maintainerId); + $oMaintainer->unQueue("OK"); + } + } + } + + public function Reject($bSilent=false) + { + if(!$_SESSION['current']->canRejectVersion($this)) + return; + + // If we are not in the queue, we can't move the version out of the queue. + if($this->sState != 'queued') + return false; + + if(query_parameters("UPDATE appVersion SET state = '?' WHERE versionId = '?'", + 'rejected', $this->iVersionId)) + { + $this->sState = 'rejected'; + // we send an e-mail to interested people + if(!$bSilent) + { + $this->mailSubmitter("reject"); + $this->SendNotificationMail("reject"); + } + // the version has been unqueued + addmsg("The version has been rejected.", "green"); + } + } + + public function ReQueue() + { + if(!$_SESSION['current']->canRequeueVersion($this)) + return; + + if(query_parameters("UPDATE appVersion SET state = '?' WHERE versionId = '?'", + 'queued', $this->iVersionId)) + { + $this->sState = 'queued'; + // we send an e-mail to interested people + $this->SendNotificationMail(); + + // the version has been unqueued + addmsg("The version has been re-submitted", "green"); + } + } + + public function objectGetSubmitterId() + { + return $this->iSubmitterId; + } + + public static function objectGetMailOptions($sAction, $bMailSubmitter, + $bParentAction) + { + return new mailOptions(); + } + + public function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + $oApp = new application($this->iAppId); + + if($bMailSubmitter) + { + switch($sAction) + { + case "delete": + $sSubject = "Submitted version deleted"; + $sMsg = "The version you submitted (".$oApp->sName." ".$this->sName. + ") has been deleted."; + break; + } + $aMailTo = null; + } else + { + switch($sAction) + { + case "delete": + $sSubject = "Version '".$this->sName."' of '".$oApp->sName."' ". + "deleted"; + $sMsg = ""; + break; + } + $aMailTo = User::get_notify_email_address_list(null, $this->iVersionId); + } + return array($sSubject, $sMsg, $aMailTo); + } + + private function mailSubmitter($sAction="add") + { + global $aClean; //FIXME: we should pass the sReplyText value in + + // use 'sReplyText' if it is defined, otherwise define the value as an empty string + if(!isset($aClean['sReplyText'])) + $aClean['sReplyText'] = ""; + + if($this->iSubmitterId) + { + $oApp = new Application($this->iAppId); + $oSubmitter = new User($this->iSubmitterId); + switch($sAction) + { + case "add": + $sSubject = "Submitted version accepted"; + $sMsg = "The version you submitted (".$oApp->sName." ".$this->sName.") has been accepted by ".$_SESSION['current']->sRealname.".\n"; + $sMsg .= "Administrators response:\n"; + break; + case "reject": + $sSubject = "Submitted version rejected"; + $sMsg = "The version you submitted (".$oApp->sName." ".$this->sName.") has been rejected by ".$_SESSION['current']->sRealname."."; + $sMsg .= "Clicking on the link in this email will allow you to modify and resubmit the version. "; + $sMsg .= "A link to your queue of applications and versions will also show up on the left hand side of the Appdb site once you have logged in. "; + $sMsg .= APPDB_ROOT."objectManager.php?sClass=version_queue". + "&bIsQueue=true&bIsRejected=true&iId=".$this->iVersionId."&". + "sTitle=Edit+Version\n"; + break; + } + $sMsg .= $aClean['sReplyText']."\n"; + $sMsg .= "We appreciate your help in making the Version Database better for all users."; + + mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg); + } + } + + private function SendNotificationMail($sAction="add",$sMsg=null) + { + global $aClean; + + // use 'sReplyText' if it is defined, otherwise define the value as an empty string + if(!isset($aClean['sReplyText'])) + $aClean['sReplyText'] = ""; + + $oApp = new Application($this->iAppId); + switch($sAction) + { + case "add": + if($this->sState == 'accepted') + { + $sSubject = "Version ".$this->sName." of ".$oApp->sName." added by ".$_SESSION['current']->sRealname; + $sMsg = $this->objectMakeUrl()."\n"; + if($this->iSubmitterId) + { + $oSubmitter = new User($this->iSubmitterId); + $sMsg .= "This version has been submitted by ".$oSubmitter->sRealname."."; + $sMsg .= "\n"; + } + if($aClean['sReplyText']) + { + $sMsg .= "Appdb admin reply text:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + + addmsg("The version was successfully added into the database.", "green"); + } else // Version queued. + { + $sSubject = "Version '".$this->sName."' of '".$oApp->sName."' submitted by ".$_SESSION['current']->sRealname; + $sMsg .= "This version has been queued."; + $sMsg .= "\n"; + addmsg("The version you submitted will be added to the database after being reviewed.", "green"); + } + break; + case "edit": + $sSubject = "'".$oApp->sName." ".$this->sName."' has been modified by ".$_SESSION['current']->sRealname; + $sMsg .= $this->objectMakeUrl()."\n"; + addmsg("Version modified.", "green"); + break; + case "delete": + + // if sReplyText is set we should report the reason the application was deleted + if($aClean['sReplyText']) + { + $sMsg .= "Reason given:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + + addmsg("Version deleted.", "green"); + break; + case "reject": + $sSubject = "Version '".$this->sName."' of '".$oApp->sName."' has been rejected by ".$_SESSION['current']->sRealname; + $sMsg .= APPDB_ROOT."objectManager.php?sClass=version_queue". + "&bIsQueue=true&bIsRejected=true&iId=".$this->iVersionId."&". + "sTitle=Edit+Version\n"; + + // if sReplyText is set we should report the reason the version was rejected + if($aClean['sReplyText']) + { + $sMsg .= "Reason given:\n"; + $sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any + } + + addmsg("Version rejected.", "green"); + break; + } + $sEmail = User::get_notify_email_address_list(null, $this->iVersionId); + if($sEmail) + mail_appdb($sEmail, $sSubject ,$sMsg); + } + + public function get_buglink_ids() + { + /* + * We fetch Bug linkIds. + */ + $aBuglinkIds = array(); + $sQuery = "SELECT * + FROM buglinks + WHERE versionId = '?' + ORDER BY bug_id"; + if($hResult = query_parameters($sQuery, $this->iVersionId)) + { + while($oRow = query_fetch_object($hResult)) + { + $aBuglinkIds[] = $oRow->linkId; + } + } + + return $aBuglinkIds; + } + + /* Makes a frame with title 'Mark as obsolete' and info about what it means, plus + caller-defined content */ + private static function makeObsoleteFrame($sContent = "") + { + $sMsg = html_frame_start("Mark as obsolete", "90%", "", 0); + + $sMsg .= "Some applications need to be updated from time to time in order to "; + $sMsg .= "be of any use. An example is online multi-player games, where you need "; + $sMsg .= "to be running a version compatible with the server. "; + $sMsg .= "If this is such an application, and this version is no longer usable, "; + $sMsg .= "you can mark it as obsolete and move its current votes to a usable "; + $sMsg .= "version instead.

      "; + + $sMsg .= $sContent; + + $sMsg .= html_frame_end(); + + return $sMsg; + } + + /* output html and the current versions information for editing */ + /* if $editParentApplication is true that means we need to display fields */ + /* to let the user change the parent application of this version */ + /* otherwise, if $editParentAppliation is false, we leave them out */ + public function outputEditor() + { + HtmlAreaLoaderScript(array("version_editor")); + echo html_frame_start("Version Form", "90%", "", 0); + + echo ''; + + $oTable = new Table(); + $oTable->SetClass("color0"); + $oTable->SetWidth("100%"); + $oTable->SetBorder(0); + $oTable->SetCellPadding(2); + $oTable->SetCellSpacing(0); + + /* Fill in appId value */ + global $aClean; + if(!$this->iAppId) + $this->iAppId = $aClean['iAppId']; + + if($this->sState == 'accepted' && $this->iVersionId) + { + // app parent + $x = new TableVE("view"); + $oTableRow = new TableRow(); + $oTableRow->SetValign("top"); + + $oTableCell = new TableCell("Application"); + $oTableCell->SetBold(true); + $oTableRow->AddCell($oTableCell); + + $sOptionList = $x->make_option_list("iAppId", $this->iAppId, + "appFamily", "appId", "appName"); + $oTableCell = new TableCell($sOptionList); + $oTableCell->SetClass("color0"); + + $oTableRow->AddCell($oTableCell); + + $oTable->AddRow($oTableRow); + } else + { + echo ''; + } + + // version name + $oTableRow = new TableRow(); + $oTableRow->SetValign("top"); + + $oTableCell = new TableCell("Version Name"); + $oTableCell->SetBold(true); + $oTableCell->SetClass("color0"); + $oTableRow->AddCell($oTableCell); + + $oTableRow->AddTextCell(''); + + $oTable->AddRow($oTableRow); + + // version license + $oTableRow = new TableRow(); + $oTableCell = new TableCell("License"); + $oTableCell->SetBold(true); + $oTableCell->SetClass("color0"); + $oTableRow->AddCell($oTableCell); + + $oTableRow->AddTextCell($this->makeLicenseList()); + + $oTable->AddRow($oTableRow); + + // version description + $oTableRow = new TableRow(); + $oTableRow->SetValign("top"); + + $oTableCell = new TableCell("Version description"); + $oTableCell->SetBold(true); + $oTableCell->SetClass("color0"); + $oTableRow->AddCell($oTableCell); + + $oTableRow->AddTextCell('

      '); + + $oTable->AddRow($oTableRow); + + // output the table + echo $oTable->GetString(); + + echo html_frame_end(); + + if($this->sState == 'accepted' && $this->iVersionId) + { + /* Mark as obsolete */ + $oApp = new application($this->iAppId); + $oVersionInDB = new version($this->iVersionId); + + if($oVersionInDB->iObsoleteBy) + { + $sObsoleteTxt = ""; + $sObsoleteTxt .= " This version is obsolete"; + echo $this->makeObsoleteFrame($sObsoleteTxt); + + echo "iObsoleteBy."\" type=\"hidden\" >\n"; + } else if(sizeof($oApp->getVersions(TRUE, FALSE)) > 1) + { + if($this->iObsoleteBy) + $sObsolete = "checked=\"checked\""; + else + $sObsolete = ""; + + $sObsoleteTxt = ""; + $sObsoleteTxt .= "Mark as obsolete and move votes to \n"; + $sObsoleteTxt .= $oApp->makeVersionDropDownList("iObsoleteBy", $this->iObsoleteBy, $this->iVersionId, FALSE); + + echo $this->makeObsoleteFrame($sObsoleteTxt); + } + } else + { + echo ''; + echo ''; + } + } + + public function CheckOutputEditorInput($aValues) + { + $errors = ""; + + if (empty($aValues['sVersionName'])) + $errors .= "
    • Please enter an application version.
    • \n"; + + if (empty($aValues['shVersionDescription'])) + $errors .= "
    • Please enter a version description.
    • \n"; + + return $errors; + } + + /* retrieves values from $aValues that were output by outputEditor() */ + /* $aValues can be $_REQUEST or any array with the values from outputEditor() */ + public function GetOutputEditorValues($aValues) + { + if($aValues['iAppId']) + $this->iAppId = $aValues['iAppId']; + + if($aValues['iVersionId']) + $this->iVersionId = $aValues['iVersionId']; + + $this->sName = $aValues['sVersionName']; + $this->sDescription = $aValues['shVersionDescription']; + $this->sLicense = $aValues['sLicense']; + $this->iMaintainerRequest = $aValues['iMaintainerRequest']; + + if($aValues['bObsolete'] == "true") + $this->iObsoleteBy = $aValues['iObsoleteBy']; + else + $this->iObsoleteBy = 0; + } + + public function objectGetCustomTitle($sAction) + { + switch($sAction) + { + case 'delete': + return 'Delete '.version::fullName($this->iVersionId); + case "view": + return version::fullName($this->iVersionId); + + default: + return null; + } + } + + public static function objectGetCustomVars($sAction) + { + switch($sAction) + { + case "view": + /* Allow the user to select which test report is + shown in the version view */ + return array("iTestingId"); + + default: + return null; + } + } + + public function objectShowPreview() + { + return TRUE; + } + + public function objectSetParent($iNewId, $sClass = '') + { + $this->iAppId = $iNewId; + } + + /* Not standard OM function yet, but will be in the future */ + public function objectGetParent($sClass = '') + { + /* No id so we can't query the DB, but perhaps an entry is cached? */ + if(!$this->iAppId && $this->oApp) + return $this->oApp; + + return new application($this->iAppId); + } + + /* Only show children of (grand)parents in the Move Child Objects and Change Parent lists */ + public static function objectRestrictMoveObjectListsToParents() + { + return true; + } + + public function getRatingInfo() + { + return testData::getRatingInfoForVersionId($this->iVersionId); + } + + public function updateRatingInfo() + { + $aRatingInfo = $this->getRatingInfo(); + + $hResult = query_parameters("UPDATE appVersion SET + rating = '?', + ratingRelease = '?' + WHERE versionId = '?'", + $aRatingInfo[0], + $aRatingInfo[1], + $this->iVersionId); + + if(!$hResult) + return false; + + return true; + } + + public function display($aVars = array()) + { + /* is this user supposed to view this version? */ + if(!$_SESSION['current']->canViewVersion($this)) + { + $sError = 'You do not have permission to view this entry'; + + if($this->objectGetState() == 'deleted') + $sError = 'This entry has been deleted; it\'s contents may have been moved to another entry'; + + objectManager::error_exit($sError); + } + + $iTestingId = $aVars['iTestingId'] ? $aVars['iTestingId'] : 0; + + $oApp = $this->objectGetParent(); + + // cat + $oCategory = new Category($oApp->iCatId); + $oCategory->displayPath($oApp->iAppId, $this->iVersionId); + + // set URL + $appLinkURL = ($oApp->sWebpage) ? trimmed_link($oApp->sWebpage,30) : " "; + + // start version display + echo html_frame_start("","98%","",0); + echo '',"\n"; + echo '',"\n"; + echo "\n"; + echo "\n"; + echo html_tr(array( + "License", + $this->sLicense), + "color0"); + + // main URL + echo " \n"; + + // Votes + if(!$this->iObsoleteBy) + { + $oM = new objectManager("voteManager", "Vote"); + $oM->setReturnTo($this->objectMakeUrl()); + + if($_SESSION['current']->isLoggedIn()) + $shVoteLink = '   iUserId).'&iVersionId='.$this->iVersionId.'">Vote'; + else + $shVoteLink = ''; + + // Allow admins to see which users have voted, in order to identify + // bogus votes + if($_SESSION['current']->hasPriv('admin')) + { + $oMVoteInspector = new objectManager('voteInspector', 'Vote inspector'); + $shVoteLink .= '   Inspect'; + } + + $shVoteText = vote_count_version_total($this->iVersionId).$shVoteLink; + } else + { + $shVoteText = 'Marked as obsolete'; + } + + echo html_tr(array('Votes', $shVoteText), 'color0'); + + $sRating = $this->sTestedRating; + $sRelease = $this->sTestedRelease; + if($sRating != "/" && $sRating) + $sRatingColor = $sRating; + else + $sRatingColor = 'color0'; + + // URLs + if($sUrls = url::display($this->iVersionId)) + { + echo $sUrls; + } + + // rating Area + echo "\n"; + echo "\n"; + + // Download URLs + if($sDownloadurls = downloadurl::display($this->iVersionId)) + echo $sDownloadurls; + + // image + $img = Screenshot::get_random_screenshot_img($oApp->iAppId, $this->iVersionId, false); + echo "\n"; + + // display all maintainers of this application + echo "\n"; + + // display the app maintainer button + echo '"; + + if ($_SESSION['current']->hasPriv("admin") || $_SESSION['current']->isMaintainer($this->iVersionId) || $_SESSION['current']->isSuperMaintainer($this->iAppId)) + { + $shAdd = ''."\n"; + echo ''."\n"; + echo "\t".''."\n"; + echo "\t".''."\n"; + echo "\t".''."\n"; + echo ''."\n"; + $url = BASE."objectManager.php?sClass=version&sAction=delete&bQueued=false&iId=".$this->iVersionId; + echo "\n"; + echo "\t".''."\n"; + echo ''."\n"; + echo $shAdd.'" />'; + echo "\t".''."\n"; + echo ''."\n"; + echo $shAdd.'&sNoteTitle=HOWTO" />'; + echo "\t".''."\n"; + echo ''."\n"; + echo $shAdd.'&sNoteTitle=WARNING" />'; + echo "\t".''."\n"; + echo ''; + echo ""; + } + $oMonitor = new Monitor(); + $oMonitor->find($_SESSION['current']->iUserId, $this->iVersionId); + if($oMonitor->iMonitorId) + { + echo '\n"; + } + echo "
      Name".$oApp->sName."
      Version".$this->sName."
      URL".$appLinkURL."
      Rating".$sRating."
      Wine Version".$sRelease."
      $img
      Maintainers of this version:\n"; + echo ""; + $aMaintainers = $this->getMaintainersUserIds(); + if(sizeof($aMaintainers)>0) + { + echo "\n"; + } else + { + echo "\n"; + } + echo "
        "; + while(list($index, $userIdValue) = each($aMaintainers)) + { + $oUser = new User($userIdValue); + echo "
      • ".$oUser->objectMakeLink()."
      • "; + } + echo "
      "; + echo "No maintainers. Volunteer today!
      '."\n"; + if($_SESSION['current']->isLoggedIn()) + { + /* is this user a maintainer of this version by virtue of being a super maintainer */ + /* of this app family? */ + if($_SESSION['current']->isSuperMaintainer($oApp->iAppId)) + { + echo '
      '."\n"; + echo "\t".''."\n"; + echo "\t".''."\n"; + echo "\tiAppId."\">\n"; + echo "\tiVersionId."\">\n"; + echo "
      \n"; + } else + { + /* are we already a maintainer? */ + if($_SESSION['current']->isMaintainer($this->iVersionId)) /* yep */ + { + echo '
      '."\n"; + echo "\t".''."\n"; + echo "\t".''."\n"; + echo "\t"."iAppId."\">\n"; + echo "\t"."iVersionId."\">\n"; + echo "
      \n"; + } else /* nope */ + { + echo '
      iVersionId)).'&sReturnTo='.urlencode($this->objectMakeUrl()).'">'."\n"; + echo "\t".''."\n"; + echo "\t"."iAppId."\">\n"; + echo "\t"."iVersionId."\">\n"; + echo "
      \n"; + $oMonitor = new Monitor(); + $oMonitor->find($_SESSION['current']->iUserId, $this->iVersionId); + if(!$oMonitor->iMonitorId) + { + echo '
      \n"; + echo "\tiAppId."\" >\n"; + echo "\tiVersionId."\" >\n"; + echo "\t\n"; + echo "\t\n"; + echo "\tobjectMakeUrl()."\" >\n"; + echo "\t".''."\n"; + echo "
      \n"; + } + } + } + + } else + { + echo '
      '."\n"; + echo "\t".''."\n"; + echo "\t".''."\n"; + echo '
      '."\n"; + } + + echo "
      '."\n"; + echo ''."\n"; + echo '
      \n"; + echo "\tiMonitorId."\">\n"; + echo "\t\n"; + echo "\t\n"; + echo "\tobjectMakeUrl()."\">\n"; + echo ''."\n"; + echo "
      \n"; + echo "
      \n"; + + // start of the right hand pane in the version display + echo "\n"; + echo "
      \n"; + + ///////////////////////// + // output the description + echo "
      \n"; + + // output the description title + echo "\t
      \n"; + echo "\t\tDescription\n"; + echo "\t
      \n"; + + // output the description + echo "\t
      \n"; + echo "\t\t".$this->sDescription."\n"; + echo "\t
      \n"; + + echo "
      \n"; // end the 'info_container' div + // end description + ///////////////////////// + + + ////////////////////// + // Show test data + + $iNewestId = 0; + $oTest = null; + + /* Set if the use chose to display a particular test report */ + if($iTestingId) + { + $oTest = new testData($iTestingId); + $oTestParent = $oTest->objectGetParent(); + + /* Check that the test report doesn't belong to another version */ + if($oTestParent->objectGetId() && $oTestParent->objectGetId() != $this->objectGetId()) + $oTest = null; + } + + if(!$oTest && $this->iVersionId) /* Let's query for the latest rest report */ + { + $iNewestId = testData::getNewestTestIdFromVersionId($this->iVersionId); + $iTestingId = $iNewestId; + + if($iTestingId) /* We want all entries to have test data, but old versions might lack + it, or data may have been deleted */ + $oTest = new testData($iTestingId); + } else if(!$oTest) /* Perhaps we have a cached entry? There should be */ + { + $aTests = $this->getTestResults(); + + if(sizeof($aTests)) /* ... but we cannot be certain */ + $oTest = $aTests[0]; + } + + if($oTest) + { + if($oTest->isOld()) + { + if($iNewestId != $oTest->objectGetId()) + { + $sWarnOldText = 'The test results you have selected are very old and may not represent the current state of Wine.'; + } else + { + $sWarnOldText = 'The test results for this version are very old, and as such they may not represent '. + 'the current state of Wine. Please consider submitting a new test report.'; + } + echo html_note('Old test results', $sWarnOldText); + } + + echo "
      \n"; + + echo "\t
      \n"; + echo "\t\tSelected Test Results (selected in 'Test Results' table below)\n"; + echo "\t
      \n"; + + echo "
      \n"; + + $oTest->ShowTestResult(); + + echo "
      \n"; + + echo "
      \n"; + } else /* Show a note saying that no test results are present, + and encourage the user to take action */ + { + echo html_note('No Test Results', + 'This version has no test results, please consider submitting some.
      '. + 'They may be part of the '. + 'version or application description. If they are, please '. + 'consider becoming a maintainer and remove them, submitting '. + 'a proper test report instead.'); + } + + // end the 'info_container' div + // end show test data + ///////////////////// + + + ////////////////////////////// + // show the test results table + if($oTest) + { + if($oTest->iTestingId) + { + $oTest->ShowVersionsTestingTable($this->objectMakeUrl()."&iTestingId=", 5); + } else /* We are previewing the version */ + { + $oTable = $oTest->CreateTestTable(); + $oTable->AddRow($oTest->CreateTestTableRow(0, "")); + echo $oTable->GetString(); + } + } + + if($_SESSION['current']->isLoggedIn()) + { + echo '
      iVersionId. + '&sTitle=Add+Test+Data&sReturnTo='. + urlencode($this->objectMakeUrl()).'>'."\n"; + echo "\t".''."\n"; + echo '
      '."\n"; + } else + { + echo '
      '."\n"; + echo "\t".''."\n"; + echo "\t".''."\n"; + echo '
      '."\n"; + } + + // end show test results table + ///////////////////////////// + + + echo "
      \n"; // end the version info pane, the right hand pane in the + // version display + + echo html_frame_end(); + + view_version_bugs($this->iVersionId, $this->get_buglink_ids()); + + echo note::displayNotesForEntry($this->iVersionId); + + // Comments Section + if($this->iVersionId) + Comment::view_app_comments($this->iVersionId); + } + + public static function lookup_name($versionId) + { + if(!$versionId) return null; + $result = query_parameters("SELECT versionName FROM appVersion WHERE versionId = '?'", + $versionId); + if(!$result || query_num_rows($result) != 1) + return null; + $ob = query_fetch_object($result); + return $ob->versionName; + } + + function fullName($iVersionId) + { + if(!$iVersionId) + return FALSE; + + $hResult = query_parameters( + "SELECT appFamily.appName, appVersion.versionName + FROM appVersion, appFamily WHERE appVersion.appId = appFamily.appId + AND versionId = '?'", + $iVersionId); + + if(!$hResult || !query_num_rows($hResult)) + return FALSE; + + $oRow = query_fetch_object($hResult); + return "$oRow->appName $oRow->versionName"; + } + + /* Creates a link to the version labelled with the full application name */ + public static function fullNameLink($iVersionId) + { + $oVersion = new version($iVersionId); + $sLink = "objectMakeUrl()."\">". + $oVersion->fullName($iVersionId).""; + return $sLink; + } + + // display the versions + public static function displayList($aVersions) + { + if ($aVersions) + { + echo html_frame_start("","98%","",0); + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetBorder(0); + $oTable->SetCellPadding(3); + $oTable->SetCellSpacing(1); + + $oTableRow = new TableRow(); + $oTableRow->SetClass("color4"); + + $oTableCell = new TableCell("Version"); + $oTableCell->SetWidth("80"); + $oTableRow->AddCell($oTableCell); + + $oTableRow->AddTextCell("Description"); + + $oTableCell = new TableCell("Rating"); + $oTableCell->SetWidth("80"); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell("Wine version"); + $oTableCell->SetWidth("80"); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell("Test results"); + $oTableCell->SetWidth("80"); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell("Comments"); + $oTableCell->SetWidth("40"); + $oTableRow->AddCell($oTableCell); + + $oTable->SetHeader($oTableRow); + + $c = 0; + foreach($aVersions as $oVersion) + { + $oApp = new application($oVersion->iAppId); + + if ($oVersion->sState == $oApp->objectGetState()) + { + // set row color + $bgcolor = ($c % 2 == 0) ? "color0" : "color1"; + + $oTableRowHighlight = null; + + // if we have a valid tested rating + if($oVersion->sTestedRating && ($oVersion->sTestedRating != "/") && + ($oVersion->sTestedRating != " ")) + { + $sClass = $oVersion->sTestedRating; + + $oInactiveColor = new Color(); + $oInactiveColor->SetColorByName($oVersion->sTestedRating); + + $oHighlightColor = GetHighlightColorFromInactiveColor($oInactiveColor); + + $oTableRowHighlight = new TableRowHighlight($oHighlightColor, $oInactiveColor); + } else + { + $sClass = $bgcolor; + + $oTableRowHighlight = GetStandardRowHighlight($c); + } + + //display row + $oTableRowClick = new TableRowClick($oVersion->objectMakeUrl()); + $oTableRowClick->SetHighlight($oTableRowHighlight); + + $oTableRow = new TableRow(); + $oTableRow->SetRowClick($oTableRowClick); // make the row clickable + $oTableRow->AddTextCell($oVersion->objectMakeLink()); + $oTableRow->SetClass($sClass); + $oTableRow->AddTextCell(util_trim_description($oVersion->sDescription)); + + $oTableCell = new TableCell($oVersion->sTestedRating); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell($oVersion->sTestedRelease); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell(testData::get_testdata_count_for_versionid($oVersion->iVersionId)); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + $oTableCell = new TableCell(Comment::get_comment_count_for_versionid($oVersion->iVersionId)); + $oTableCell->SetAlign("center"); + $oTableRow->AddCell($oTableCell); + + // add the row to the table + $oTable->AddRow($oTableRow); + + $c++; + } + } + + // output the table + echo $oTable->GetString(); + + echo html_frame_end("Click the Version Name to view the details of that Version"); + } + } + + /* returns the maintainers of this version in an array */ + public function getMaintainersUserIds() + { + $aMaintainers = array(); + + /* early out if the versionId isn't valid */ + if($this->iVersionId == 0) + return $aMaintainers; + + $hResult = Maintainer::getMaintainersForAppIdVersionId(null, $this->iVersionId); + $iCount = 0; + while($oRow = query_fetch_object($hResult)) + { + $aMaintainers[$iCount] = $oRow->userId; + $iCount++; + } + + return $aMaintainers; + } + + /* List the versions submitted by a user. Ignore versions for queued applications */ + public static function listSubmittedBy($iUserId, $bQueued = true) + { + $hResult = query_parameters("SELECT appFamily.appName, appVersion.versionName, appVersion.description, appVersion.versionId, appVersion.submitTime FROM appFamily, appVersion WHERE appFamily.appId = appVersion.appId AND appVersion.submitterId = '?' AND appVersion.state = '?' AND appFamily.state = '?'", $iUserId, $bQueued ? 'queued' : 'accepted', 'accepted'); + + if(!$hResult || !query_num_rows($hResult)) + return false; + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetAlign("center"); + + // setup the table header + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("Name"); + $oTableRow->AddTextCell("Description"); + $oTableRow->AddTextCell("Submission Date"); + $oTableRow->SetClass("color4"); + $oTable->SetHeader($oTableRow); + + if($bQueued) + $oTableRow->addTextCell('Action'); + + for($i = 1; $oRow = query_fetch_object($hResult); $i++) + { + $oTableRow = new TableRow(); + $oTableRow->AddTextCell(version::fullNameLink($oRow->versionId)); + $oTableRow->AddTextCell($oRow->description); + $oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($oRow->submitTime))); + $oTableRow->SetClass(($i % 2) ? "color0" : "color1"); + + if($bQueued) + { + $oM = new objectManager('version_queue'); + $oM->setReturnTo(array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : ""); + $shDeleteLink = 'delete'; + $shEditLink = 'edit'; + $oTableRow->addTextCell("[ $shEditLink ]   [ $shDeleteLink ]"); + } + + $oTable->AddRow($oTableRow); + } + + return $oTable->GetString(); + } + + /* Returns an array containg the different software licences */ + public function getLicenses() + { + return array(LICENSE_RETAIL, LICENSE_OPENSOURCE, LICENSE_FREETOUSE, + LICENSE_FREETOSHARE, LICENSE_DEMO, LICENSE_SHAREWARE); + } + + // returns a string containing the html for a selection list + public function makeLicenseList($sLicense = NULL) + { + if(!$sLicense) + $sLicense = $this->sLicense; + + $sReturn = "\n"; + + return $sReturn; + } + + /* In order to prevent MySQL injections. Returns matched license */ + public static function checkLicense($sLicense) + { + $aLicense = array(LICENSE_RETAIL, LICENSE_OPENSOURCE, LICENSE_FREETOUSE, + LICENSE_FREETOSHARE, LICENSE_DEMO, LICENSE_SHAREWARE); + + foreach($aLicense as $sElement) + { + if($sLicense == $sElement) + return $sElement; + } + + return FALSE; + } + + public function objectGetClassDisplayName() + { + return 'version'; + } + + public function objectMakeUrl() + { + return APPDB_ROOT."objectManager.php?sClass=version&iId=$this->iVersionId"; + } + + public function objectMakeLink() + { + $sLink = "objectMakeUrl()."\">". + $this->sName.""; + return $sLink; + } + + public static function objectGetEntriesCount($sState) + { + $oVersion = new version(); + if($sState != 'accepted' && !$oVersion->canEdit()) + { + /* Users should see their own rejected entries, but maintainers should + not be able to see rejected entries for versions they maintain */ + if($sState == 'rejected') + $sQuery = "SELECT COUNT(DISTINCT appVersion.versionId) as count FROM + appVersion WHERE + appVersion.submitterId = '?' + AND + appVersion.state = '?'"; + else + $sQuery = "SELECT COUNT(DISTINCT appVersion.versionId) as count FROM + appVersion, appMaintainers WHERE + appMaintainers.appId = appVersion.appId + AND + superMaintainer = '1' + AND + appMaintainers.userId = '?' + AND + appMaintainers.state = 'accepted' + AND + appVersion.state = '?'"; + + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, $sState); + } else + { + $sQuery = "SELECT COUNT(DISTINCT versionId) as count + FROM appVersion WHERE + appVersion.state = '?'"; + $hResult = query_parameters($sQuery, $sState); + } + + if(!$hResult) + return FALSE; + + if(!$oRow = query_fetch_object($hResult)) + return FALSE; + + return $oRow->count; + } + + public function objectGetState() + { + return $this->sState; + } + + public function objectSetState($sState) + { + $this->sState = $sState; + } + + public function canEdit() + { + if($_SESSION['current']->hasPriv("admin")) + return TRUE; + + if(isset($this) && is_object($this) && $this->iVersionId) + { + if(maintainer::isUserMaintainer($_SESSION['current'], $this->iVersionId)) + return TRUE; + + if($this->sState != 'accepted' && $this->iSubmitterId == $_SESSION['current']->iUserId) + return TRUE; + + return FALSE; + } else + { + return FALSE; + } + } + + public function mustBeQueued() + { + if($_SESSION['current']->hasPriv("admin")) + return FALSE; + + // if we have a valid iAppId or iVersionId we should + // check the status of these objects to determine whether + // we need to queue this version object + if($this->iVersionId or $this->iAppId) + { + // if the user is the super maintainer of the application then + // they are authorized to unqueue versions of this application + // so the version doesn't have to be queued + if($this->iAppId && + maintainer::isUserSuperMaintainer($_SESSION['current'], $this->iAppId)) + return FALSE; + + // if the user is a maintainer of this version then + // this version doesn't have to be queued + if($this->iVersionId && + maintainer::isUserMaintainer($_SESSION['current'], $this->iVersionId)) + return FALSE; + + return TRUE; + } else + { + return TRUE; + } + } + + public static function objectGetHeader() + { + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("Submission Date"); + $oTableRow->AddTextCell("Submitter"); + $oTableRow->AddTextCell("Developer"); + $oTableRow->AddTextCell("Application"); + $oTableRow->AddTextCell("Version"); + $oTableRow->AddTextCell("Has Maintainer"); + return $oTableRow; + } + + public static function objectGetItemsPerPage($sState = 'accepted') + { + $aItemsPerPage = array(25, 50, 100, 200); + $iDefaultPerPage = 25; + return array($aItemsPerPage, $iDefaultPerPage); + } + + public static function objectGetDefaultSort() + { + return 'versionId'; + } + + public static function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "versionId", $bAscending = true) + { + $sLimit = ""; + + /* Should we add a limit clause to the query? */ + if($iRows || $iStart) + { + $sLimit = " LIMIT ?,?"; + + /* Selecting 0 rows makes no sense, so we assume the user wants to select all of them + after an offset given by iStart */ + if(!$iRows) + $iRows = version::objectGetEntriesCount($sState); + } + + if($sState != 'accepted' && !version::canEdit()) + { + /* Users should see their own rejected entries, but maintainers should + not be able to see rejected entries for versions they maintain */ + if($sState == 'rejected') + $sQuery = "SELECT * FROM appVersion WHERE + appVersion.submitterId = '?' + AND + appVersion.state = '?' ORDER BY ?$sLimit"; + else + $sQuery = "SELECT appVersion.* FROM + appVersion, appMaintainers WHERE + appMaintainers.appId = appVersion.appId + and + superMaintainer = '1' + AND + appMaintainers.userId = '?' + AND + appMaintainers.state = 'accepted' + AND + appVersion.state = '?' ORDER BY ?$sLimit"; + + if($sLimit) + { + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sState, $sOrderBy, $iStart, $iRows); + } else + { + $hResult = query_parameters($sQuery, $_SESSION['current']->iUserId, + $sState, $sOrderBy); + } + } else + { + $sQuery = "SELECT * FROM appVersion WHERE + appVersion.state = '?' ORDER BY ?$sLimit"; + + if($sLimit) + { + $hResult = query_parameters($sQuery, $sState, $sOrderBy, + $iStart, $iRows); + } else + { + $hResult = query_parameters($sQuery, $sState, $sOrderBy); + } + } + + if(!$hResult) + return FALSE; + + return $hResult; + } + + public function objectGetTableRow() + { + $oUser = new user($this->iSubmitterId); + $oApp = new application($this->iAppId); + $oVendor = new vendor($oApp->iVendorId); + + $aMaintainers = Maintainer::getSuperMaintainersUserIdsFromAppId($this->iAppId); + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($this->sSubmitTime))); + $oTableRow->AddTextCell($oUser->objectMakeLink()); + $oTableRow->AddTextCell($oVendor->objectMakeLink()); + $oTableRow->AddTextCell($oApp->objectMakeLink()); + $oTableRow->AddTextCell($this->sName); + $oTableRow->AddTextCell(sizeof($aMaintainers) ? "YES" : "No"); + + $oOMTableRow = new OMTableRow($oTableRow); + return $oOMTableRow; + } + + public function objectDisplayQueueProcessingHelp() + { + echo "

      This is the list of version entries waiting to be processed.

      \n"; + echo "

      To view and process an entry, use the links under ‘Action’

      "; + } + + public function getTestResults($bIncludeDeleted = false) + { + /* If we don't have an id we can't query the database, but perhaps we + have some cached entries? */ + if(!$this->iVersionId) + return $this->aTestResults; + + $aTests = array(); + + if($bIncludeDeleted) + $sExcludeDeleted = ""; + else + $sExcludeDeleted = " AND state != 'deleted'"; + + /* Find test results */ + $sQuery = "SELECT * FROM testResults WHERE versionId = '?'$sExcludeDeleted"; + $hResult = query_parameters($sQuery, $this->iVersionId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + $aTests[] = new testData(0, $oRow); + + return $aTests; + } + + public function objectGetChildren($bIncludeDeleted = false, $bRecursive = true) + { + return $this->objectGetChildrenClassSpecific('', $bIncludeDeleted, $bRecursive); + } + + public function objectGetChildrenClassSpecific($sClass = '', $bIncludeDeleted = false, $bRecursive = true) + { + $aChildren = array(); + + foreach($this->getTestResults($bIncludeDeleted) as $oTest) + { + if($bRecursive) + $aChildren = array_merge($aChildren, $oTest->objectGetChildren($bIncludeDeleted)); + $aChildren[] = $oTest; + } + + /* Find maintainers */ + $sQuery = "SELECT * FROM appMaintainers WHERE versionId = '?'"; + $hResult = query_parameters($sQuery, $this->iVersionId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oMaintainer = new maintainer(0, $oRow); + + if($bRecursive) + $aChildren = array_merge($aChildren, $oMaintainer->objectGetChildren($bIncludeDeleted)); + $aChildren[] = $oMaintainer; + } + + /* Find monitors */ + $sQuery = "SELECT * FROM appMonitors WHERE versionId = '?'"; + $hResult = query_parameters($sQuery, $this->iVersionId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oMonitor = new monitor(0, $oRow); + + if($bRecursive) + $aChildren = array_merge($aChildren, $oMonitor->objectGetChildren($bIncludeDeleted)); + $aChildren[] = $oMonitor; + } + + /* Find notes */ + $sQuery = "SELECT * FROM appNotes WHERE versionId = '?' AND linkedWith = '0'"; + $hResult = query_parameters($sQuery, $this->iVersionId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oNote = new note(0, $oRow); + + // We always include notes' children, because they log the versionId + $aChildren = array_merge($aChildren, $oNote->objectGetChildren($bIncludeDeleted)); + $aChildren[] = $oNote; + } + + /* Find screenshots */ + $sQuery = "SELECT * FROM appData WHERE type = '?' AND versionId = '?'"; + $hResult = query_parameters($sQuery, "screenshot", $this->iVersionId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oScreenshot = new screenshot(0, $oRow); + + if($bRecursive) + $aChildren = array_merge($aChildren, $oScreenshot->objectGetChildren($bIncludeDeleted)); + $aChildren[] = $oScreenshot; + } + + /* Get bug links */ + foreach($this->get_buglink_ids() as $iBugId) + { + $oBug = new bug($iBugId); + + if($bRecursive) + $aChildren = array_merge($aChildren, $oBug->objectGetChildren($bIncludeDeleted)); + $aChildren[] = $oBug; + } + + /* Get comments */ + $sQuery = "SELECT * FROM appComments WHERE versionId = '?'"; + $hResult = query_parameters($sQuery, $this->iVersionId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oComment = new comment(0, $oRow); + + /* No need to grab child comments since they're all part of the SQL result */ + $aChildren[] = $oComment; + } + + /* Get urls */ + $sQuery = "SELECT * FROM appData WHERE type = '?' AND versionId = '?'"; + $hResult = query_parameters($sQuery, "url", $this->iVersionId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oUrl = new url(0, $oRow); + + if($bRecursive) + $aChildren = array_merge($aChildren, $oUrl->objectGetChildren($bIncludeDeleted)); + $aChildren[] = $oUrl; + } + + /* Get downloadurls */ + $sQuery = "SELECT * FROM appData WHERE type = '?' AND versionId = '?'"; + $hResult = query_parameters($sQuery, "downloadurl", $this->iVersionId); + + if(!$hResult) + return FALSE; + + while($oRow = mysql_fetch_object($hResult)) + { + $oDownload = new downloadurl(0, $oRow); + + if($bRecursive) + $aChildren = array_merge($aChildren, $oDownload->objectGetChildren($bIncludeDeleted)); + $aChildren[] = $oDownload; + } + + /* Get votes, include deleted ones */ + $aChildren = array_merge($aChildren, vote::getVotesForVersion($this->iVersionId)); + + return $aChildren; + } + + public function objectMoveChildren($iNewId) + { + /* Keep track of how many items we have updated */ + $iCount = 0; + + /* We also move entries marked as deleted */ + $aChildren = $this->objectGetChildren(true, false); + + foreach($aChildren as $oChild) + { + $oChild->objectSetParent($iNewId, 'version'); + if($oChild->update()) + $iCount++; + else + return false; + } + + /* Return the number of updated objects if everything was successful */ + return $iCount; + } + + public static function allowAnonymousSubmissions() + { + return FALSE; + } + + function objectAllowPurgingRejected() + { + return TRUE; + } + + public function objectGetSubmitTime() + { + return mysqltimestamp_to_unixtimestamp($this->sSubmitTime); + } + + public function objectGetId() + { + return $this->iVersionId; + } +} + +?> diff --git a/include/version_queue.php b/include/version_queue.php new file mode 100644 index 0000000..6dd5fe5 --- /dev/null +++ b/include/version_queue.php @@ -0,0 +1,369 @@ +oVersion = new version($iVersionId, $oRow); + $iTestingId = null; + $iDownloadUrlId = null; + + if(!$iVersionId) + $iVersionId = $this->oVersion->iVersionId; + + if($iVersionId) + { + $iTestingId = testData::getNewestTestIdFromVersionId($iVersionId, "pending"); + /* This illustrates the importance of converting downloadurl completely + to the objectManager model. If we don't get a match searching for + a queued entry, try finding a rejected one. */ + if(($hResult = appData::getData($iVersionId, "downloadurl", + TRUE, TRUE, FALSE)) || + $hResult = appData::getData($iVersionId, "downloadurl", + TRUE, TRUE, TRUE)) + { + if($oRow = query_fetch_object($hResult)) + $iDownloadUrlId = $oRow->id; + } + } + + $this->oTestDataQueue = new testData_queue($iTestingId); + $this->oDownloadUrl = new downloadurl($iDownloadUrlId); + + if(!$this->oDownloadUrl->objectGetId() && $iVersionId) + $this->oDownloadUrl->objectSetParent($iVersionId); + } + + function create() + { + global $aClean; + if(!$this->oVersion->create()) + return FALSE; + + $this->oTestDataQueue->oTestData->iVersionId = $this->oVersion->iVersionId; + $this->oTestDataQueue->create(); + $this->oDownloadUrl->objectSetParent($this->oVersion->objectGetId()); + $this->oDownloadUrl->create(); + + return TRUE; + } + + function reQueue() + { + $this->oDownloadUrl->reQueue(); + } + + function reject() + { + $oApp = new application($this->oVersion->iAppId); + + if($oApp->objectGetState() == 'accepted') + $this->oVersion->reject(); + + if($this->oDownloadUrl->iId) + $this->oDownloadUrl->reject(); + } + + function update() + { + $this->oVersion->update(); + + /* A downloadurl is optional and can thus be added later */ + if($this->oDownloadUrl->objectGetId()) + $this->oDownloadUrl->update(); + else + $this->oDownloadUrl->create(); + + $this->oTestDataQueue->update(); + } + + function purge() + { + $bSuccess = TRUE; + + if(!$this->oVersion->purge()) + $bSuccess = FALSE; + + if(!$this->oTestDataQueue->purge()) + $bSuccess = FALSE; + + if($this->oDownloadUrl->iId && !$this->oDownloadUrl->purge()) + $bSuccess = FALSE; + + return $bSuccess; + } + + function delete() + { + $bSuccess = TRUE; + + if(!$this->oVersion->delete()) + $bSuccess = FALSE; + + if(!$this->oTestDataQueue->delete()) + $bSuccess = FALSE; + + if($this->oDownloadUrl->iId && !$this->oDownloadUrl->delete()) + $bSuccess = FALSE; + + return $bSuccess; + } + + function unQueue() + { + $this->oVersion->unQueue(); + $this->oTestDataQueue->unQueue(); + $this->oDownloadUrl->unQueue(); + } + + function objectGetSubmitterId() + { + return $this->oVersion->objectGetSubmitterId(); + } + + function objectGetChildren($bIncludeDeleted = false) + { + return $this->oVersion->objectGetChildren($bIncludeDeleted); + } + + function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction) + { + return $this->oVersion->objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + return $this->oVersion->objectGetMail($sAction, $bMailSubmitter, $bParentAction); + } + + function outputEditor() + { + global $aClean; + + echo "
      \n"; + + /* Display duplicate list if this is a an existing version */ + if($this->oVersion->iVersionId) + $this->displayMoveTestTable(); + + $this->oVersion->outputEditor(); + + /* Allow the user to apply as maintainer if this is a new version. + If it is a new application as well, radio boxes will be displayed + by the application class instead. */ + if(!$this->oVersion->iVersionId && $this->oVersion->iAppId && + !$_SESSION['current']->isSuperMaintainer($this->oVersion->iAppId)) + { + echo html_frame_start("Become a Maintainer or Monitor Changes", "90%"); + echo "
      \n"; + $oTable = new Table(); + if($this->oVersion->iMaintainerRequest == MAINTAINER_REQUEST) + $sRequestMaintainerChecked = 'checked="checked" '; + else + $sRequestMaintainerChecked = ''; + if($this->oVersion->iMaintainerRequest == MONITOR_REQUEST) + $sRequestMonitorChecked = 'checked="checked"' ; + else + $sRequestMonitorChecked = ''; + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell(' '); + $oTableRow->AddTextCell(" ". + "Request being a maintainer for this version, allowing you to edit it later"); + $oTable->AddRow($oTableRow); + $oTableRow = new TableRow(); + $oTableRow->AddTextCell(' '); + $oTableRow->AddTextCell(" ". + "Monitor changes to this version, also after it has been accepted"); + $oTable->AddRow($oTableRow); + $oTableRow = new TableRow(); + $oTableRow->AddTextCell(' '); + $oTableRow->AddTextCell(' '. + 'None of the above'); + $oTable->AddRow($oTableRow); + + echo $oTable->GetString(); + echo "oDownloadUrl->outputEditorSingle($this->oVersion->iVersionId, + $aClean); + $this->oTestDataQueue->outputEditor(); + + echo "
      \n"; + } + + function getOutputEditorValues($aClean) + { + $this->oVersion->iAppId = $aClean['iAppId']; + $this->oVersion->getOutputEditorValues($aClean); + $this->oDownloadUrl->getOutputEditorValues($aClean); + $this->oTestDataQueue->getOutputEditorValues($aClean); + } + + function checkOutputEditorInput($aClean) + { + $sErrors = $this->oVersion->checkOutputEditorInput($aClean); + $sErrors .= $this->oTestDataQueue->checkOutputEditorInput($aClean); + return $sErrors; + } + + function objectGetState() + { + return $this->oVersion->objectGetState(); + } + + function canEdit() + { + return $this->oVersion->canEdit(); + } + + function mustBeQueued() + { + return $this->oVersion->mustBeQueued(); + } + + function objectDisplayAddItemHelp() + { + /* $this->oVersion->displayAddItemHelp(); */ + } + + function objectGetItemsPerPage($sState = 'accepted') + { + return $this->oVersion->objectGetItemsPerPage($sState); + } + + function objectGetEntriesCount($sState) + { + return $this->oVersion->objectGetEntriesCount($sState); + } + + public static function objectGetDefaultSort() + { + return version::objectGetDefaultSort(); + } + + function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "versionId", $bAscending = true) + { + return $this->oVersion->objectGetEntries($sState, $iRows, $iStart, + $sOrderBy, $bAscending); + } + + function objectGetHeader() + { + return $this->oVersion->objectGetHeader(); + } + + function objectGetTableRow() + { + return $this->oVersion->objectGetTableRow(); + } + + public function objectShowPreview() + { + return $this->oVersion->objectShowPreview(); + } + + function display() + { + /* Cache the test result object as it's not in the DB */ + $this->oVersion->aTestResults[] = $this->oTestDataQueue->oTestData; + $this->oVersion->display(); + } + + function objectMakeUrl() + { + return $this->oVersion->objectMakeUrl(); + } + + function objectMakeLink() + { + return $this->oVersion->objectMakeLink(); + } + + function displayMoveTestTable() + { + $oApp = new application($this->oVersion->iAppId); + + echo html_frame_start("Move test to version","90%","",0); + echo "\n\n"; + + echo html_tr(array( + array("Version", 'width="80"'), + "Description", + array("Rating", 'width="80"'), + array("Wine version", 'width="80"'), + array("Comments", 'width="40"'), + array("Move test results", 'width="80"') + ), + "color4"); + + $i = 0; + foreach($oApp->aVersionsIds as $iVersionId) + { + $oVersion = new Version($iVersionId); + if ($oVersion->objectGetState() == 'accepted') + { + //display row + echo html_tr(array( + $oVersion->objectMakeLink(), + util_trim_description($oVersion->sDescription), + array($oVersion->sTestedRating, 'align="center"'), + array($oVersion->sTestedRelease, 'align="center"'), + array(Comment::get_comment_count_for_versionid( + $oVersion->iVersionId), 'align="center"'), + html_ahref("Move here", + "objectManager.php?sClass=version_queue&bIsQueue=true&". + "sAction=moveChildren&iId=". + $this->oVersion->iVersionId."&iNewId=". + $oVersion->iVersionId."&sTitle=Version+Queue"), + ), + ($i % 2) ? "color0" : "color1"); + + $i++; + } + } + echo "
      \n"; + echo html_frame_end(" "); + } + + function objectDisplayQueueProcessingHelp() + { + version::objectDisplayQueueProcessingHelp(); + } + + function objectMoveChildren($iNewId) + { + return $this->oVersion->objectMoveChildren($iNewId); + } + + function allowAnonymousSubmissions() + { + return version::allowAnonymousSubmissions(); + } + + function objectAllowPurgingRejected() + { + return $this->oVersion->objectAllowPurgingRejected(); + } + + public function objectGetSubmitTime() + { + return $this->oVersion->objectGetSubmitTime(); + } + + function objectGetId() + { + return $this->oVersion->objectGetId(); + } +} + +?> diff --git a/include/vote.php b/include/vote.php new file mode 100644 index 0000000..520beca --- /dev/null +++ b/include/vote.php @@ -0,0 +1,505 @@ +iUserId = $oRow->userId; + $this->iVoteId = $oRow->id; + $this->iSlotIndex = $oRow->slot; + $this->iVersionId = $oRow->versionId; + } + } + + public function update() + { + /* Check for valid vote slot index */ + if($this->iSlotIndex < 1 || $this->iSlotIndex > MAX_VOTES) + return; + + /* Avoid pointless votes */ + if(!$this->iVersionId) + return; + + if(!$this->iVoteId) + { + $hResult = query_parameters("INSERT INTO appVotes (versionId,userId,slot) VALUES('?','?','?')", + $this->iVersionId, $_SESSION['current']->iUserId, $this->iSlotIndex); + } else + { + $hResult = query_parameters("UPDATE appVotes SET versionId = '?' WHERE id = '?'", $this->iVersionId, $this->iVoteId); + } + + if(!$hResult) + return FALSE; + + return TRUE; + } + + public function delete() + { + /* A vote needs to have a versionId, so if it doesn't that means it is not in the + database or it was not selected in the vote editor */ + if(!$this->iVersionId) + return TRUE; + + $hResult = query_parameters("DELETE FROM appVotes WHERE id = '?'", $this->iVoteId); + + if(!$hResult) + return FALSE; + + return TRUE; + } + + public function getVotesForVersion($iVersionId) + { + $aRet = array(); + $hResult = query_parameters("SELECT * FROM appVotes WHERE versionId = '?'", + $iVersionId); + + if(!$hResult) + return $aRet; + + while($oRow = mysql_fetch_object($hResult)) + $aRet[] = new vote(null, $oRow); + + return $aRet; + } + + public function objectGetId() + { + return $this->iVoteId; + } + + public function objectGetSubmitterId() + { + return $this->iUserId; + } + + public function objectGetParent($sClass = '') + { + return new version($this->iVersionId); + } + + public function objectSetParent($iNewId, $sClass = '') + { + $this->iVersionId = $iNewId; + } + + public function canEdit() + { + if($_SESSION['current']->iUserId == $this->iUserId) + return true; + + $oVersion = new version($this->iVersionId); + + return $oVersion->canEdit(); + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + return array(null, null, null); /* No mail */ + } + + public static function objectGetMailOptions($sAction, $bMailSubmitter, + $bParentAction) + { + return new mailOptions(); + } +} + +class voteManager +{ + private $iUserId; + private $aVotes; + + public function voteManager($iUserId = null, $oRow = null) + { + $this->iUserId = $iUserId; + } + + public function objectGetCustomVars($sAction) + { + switch($sAction) + { + case "edit": + return array("iVersionId"); + break; + + default: + return null; + } + } + + public function outputEditor($aClean = null) + { + echo "The following shows your current votes. Check the boxes next to the apps you wish to replace with a vote for ".version::fullNameLink($aClean['iVersionId'])." or delete."; + + $oTable = new table(); + $this->aVotes = $this->getVotes(); + + for($i = 0; $i < MAX_VOTES; $i++) + { + $sVersionText = $this->aVotes[$i]->iVersionId ? version::fullNameLink($this->aVotes[$i]->iVersionId) : "No app selected"; + $oTableRow = new tableRow(); + $oTableRow->addTextCell(''); + $oTableRow->addTextCell($sVersionText); + $oTable->addRow($oTableRow); + } + + echo $oTable->getString(); + } + + public function canEdit() + { + if($_SESSION['current']->iUserId == $this->iUserId) + return TRUE; + + return FALSE; + } + + function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + return array(null, null, null); /* No mail */ + } + + public function mustBeQueued() + { + return FALSE; + } + + public function objectGetEntries($bQueued, $bRejected) + { + return query_parameters("SELECT * FROM appVotes"); + } + + public function objectGetId() + { + return $this->iUserId; + } + + public function create() + { + return TRUE; + } + + function purge() + { + return $this->delete(); + } + + public function delete() + { + $bSuccess = TRUE; + + if(!is_array($this->aVotes)) + $this->aVotes = $this->getVotes(); + + foreach($this->aVotes as $oVote) + { + if(!$oVote->delete()) + $bSuccess = FALSE; + } + + return $bSuccess; + } + + public function update() + { + foreach($this->aVotes as $oVote) + $oVote->update(); + } + + public function getOutputEditorValues($aClean) + { + $this->aVotes = $this->getVotes(); + + for($i = 0; $i < MAX_VOTES; $i++) + $this->aVotes[$i]->iVersionId = $aClean["iSlot$i"]; + } + + public function objectGetEntriesCount() + { + $hResult = query_parameters("SELECT COUNT(id) as count FROM appVotes"); + + if(!$hResult) + return FALSE; + + if(!($oRow = mysql_fetch_object($hResult))) + return FALSE; + + return $oRow->count; + } + + public function objectGetSubmitterId() + { + return $this->iUserId; + } + + public function getVotes() + { + $aVotes = array(); + $hResult = query_parameters("SELECT * FROM appVotes WHERE userId = '?' ORDER BY slot", $this->iUserId); + + if(!$hResult) + return $aVotes; + + for($i = 0; $i < MAX_VOTES; $i++) + $aVotes[$i] = null; + + while($oRow = mysql_fetch_object($hResult)) + $aVotes[$oRow->slot-1] = new vote(null, $oRow); + + for($i = 0; $i < MAX_VOTES; $i++) + { + if(!$aVotes[$i]) + { + $aVotes[$i] = new vote(); + $aVotes[$i]->iSlotIndex = $i+1; + } + } + + return $aVotes; + } +} + +/** + * used by admins to check whether votes for a version are legit + */ +class voteInspector +{ + private $iVersionId; + private $aDeleteVoters; + + function voteInspector($iVersionId = null) + { + if(is_numeric($iVersionId)) + $this->iVersionId = $iVersionId; + + $this->aDeleteVoters = array(); + } + + public function objectGetId() + { + return $this->iVersionId; + } + + public function objectGetState() + { + return 'accepted'; + } + + public function canEdit() + { + return $_SESSION['current']->hasPriv('admin'); + } + + public function objectGetSubmitterId() + { + return -1; + } + + public function getVotes() + { + return query_parameters("SELECT userId, COUNT(userId) as count FROM appVotes WHERE + versionId = '?' + GROUP BY userId", $this->iVersionId); + } + + public function getVoteCount() + { + return vote_count_version_total($this->iVersionId); + } + + public function getVoterCount() + { + return mysql_num_rows($this->getVotes()); + } + + public function outputEditor() + { + $oVersion = new version($this->iVersionId); + + echo 'Inspecting votes for ' . version::fullNameLink($this->iVersionId).'
      '; + echo 'Total votes: '.$this->getVoteCount().'
      '; + echo 'To delete bogus user accounts, select them and press the Delete button below.

      '; + + $hResult = $this->getVotes(); + + if(!$hResult) + { + echo 'Failed to get list of votes'; + return; + } + + if(mysql_num_rows($hResult) == 0) + { + echo 'There are no votes for this version'; + return; + } + + $oTable = new Table(); + $oTable->setCellPadding(3); + + $oTableRow = new TableRow(); + $oTableRow->setClass('color4'); + $oTableRow->AddTextCell('Delete account'); + $oTableRow->AddTextCell('User'); + $oTableRow->AddTextCell('ID'); + $oTableRow->AddTextCell('E-mail'); + $oTableRow->AddTextCell('Created'); + $oTableRow->AddTextCell('Votes'); + $oTableRow->AddTextCell('Privileges'); + $oTableRow->AddTextCell('Test data'); + $oTableRow->AddTextcell('Comments'); + $oTable->AddRow($oTableRow); + + for($i = 0; $oRow = mysql_fetch_object($hResult); $i++) + { + $oVoter = new user($oRow->userId); + $oTableRow = new TableRow(); + $oTableRow->setClass(($i % 2) ? 'color0' : 'color1'); + + if($oVoter->hasPriv('admin')) + $shDelete = ''; + else + $shDelete = "iUserId}\" />"; + + $oTableRow->AddTextCell($shDelete); + $oTableRow->AddTextCell($oVoter->objectMakeLink()); + $oTableRow->AddTextCell($oVoter->iUserId); + $oTableRow->AddTextCell($oVoter->sEmail); + $oTableRow->AddTextCell($oVoter->sDateCreated); + $oTableRow->AddTextCell($oRow->count); + + $sPrivs = ''; + if($oVoter->hasPriv('admin')) + $sPrivs .= 'Admin
      '; + + if($oVoter->isMaintainer($this->iVersionId)) + $sPrivs .= 'Maintainer of this version
      '; + + if($oVoter->isMaintainer()) + { + $oM = new objectManager('maintainerView', 'View maintainership info'); + $sPrivs .= 'Maintainer (other entries)
      '; + } + + $oTableRow->AddTextCell($sPrivs); + + $hSubResult = query_parameters("SELECT COUNT(testingId) AS count FROM testResults WHERE submitterId = '?' AND state != 'deleted'", $oVoter->iUserId); + + if($hSubResult && ($oSubRow = mysql_fetch_object($hSubResult))) + $sSubmitted = $oSubRow->count; + else + $sSubmitted = 'DB failure'; + + $oTableRow->AddTextCell($sSubmitted); + + $hSubResult = query_parameters("SELECT COUNT(commentId) as count FROM appComments WHERE userId = '?'", $oVoter->iUserId); + + if($hSubResult && ($oSubRow = mysql_fetch_object($hSubResult))) + $sSubmitted = $oSubRow->count; + else + $sSubmitted = 'DB failure'; + + $oTableRow->AddTextCell($sSubmitted); + $oTable->AddRow($oTableRow); + } + + echo $oTable->getString(); + } + + public function getOutputEditorValues($aValues) + { + $iVoters = $this->getVoterCount(); + $this->aDeleteVoters = array(); + + for($i = 0; $i < $iVoters; $i++) + { + if(($iVoterId = getInput("iDelSlot$i", $aValues))) + $this->aDeleteVoters[] = new user($iVoterId); + } + } + + public function create() + { + return true; + } + + public function update() + { + return true; + } + + public function objectGetMail($sAction, $bMailSubmitter, $bParentAction) + { + $sSubject = ''; + $sMsg = ''; + $aMailTo = null; + + return array($sSubject, $sMsg, $aMailTo); + } + + public function delete() + { + $bSuccess = true; + + foreach($this->aDeleteVoters as $oVoter) + { + if(!$oVoter->delete()) + $bSuccess = false; + } + + return $bSuccess; + } +} + +/** + * count the number of votes for appId by userId + */ +function vote_count($iVersionId, $iUserId = null) +{ + if(!$iUserId) + { + if($_SESSION['current']->isLoggedIn()) + $iUserId = $_SESSION['current']->iUserId; + else + return 0; + } + $hResult = query_parameters("SELECT * FROM appVotes WHERE versionId = '?' AND userId = '?'", + $iVersionId, $iUserId); + return query_num_rows($hResult); +} + +/* + * total votes for versionId + */ +function vote_count_version_total($iVersionId) +{ + $hResult = query_parameters("SELECT * FROM appVotes WHERE versionId = '?'", + $iVersionId); + return query_num_rows($hResult); +} + +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..147045f --- /dev/null +++ b/index.php @@ -0,0 +1,178 @@ + + Wine AppDB + +
      +

      Welcome

      + +

      This is the Wine Application Database (AppDB). Here you can get information on application +compatibility with Wine.

      + +
    • Ability to vote on your favorite applications
    • +
    • Ability to customize the layout and behavior of the AppDB and comments system
    • +
    • Take credit for your witty posts
    • +
    • Ability to sign up to be an application maintainer
    • +
    • Submit new applications and versions
    • +
    • Submit new screenshots
    • +
    +"; +if(!$_SESSION['current']->isLoggedIn()) +{ + echo " +

    Most of the features of the Application Database require that you have a user account and + are logged in. Some of the benefits of membership are:

    + + $str_benefits + +

    So, what are you waiting for? [Log in] + or [register] now! Your help in + stomping out Wine issues will be greatly appreciated.

    "; +} else +{ + echo " +

    As an Application Database member you enjoy some exclusive benefits like:

    + + $str_benefits + +

    We’d like to thank you for being a member and being logged in to the system. Your help in + stomping out Wine issues will be greatly appreciated.

    "; + +} + +?> +$iNumApps
    applications currently in the database,"; + + // don't mention the top application if there are no votes yet + if( !empty($oRow) ) + { + if($oRow->versionId) + { + $shVoteAppLink = version::fullNameLink($oRow->versionId); + echo " with $shVoteAppLink being the\n"; + echo "top voted application.\n"; + } else + { + echo " please vote for your favourite application.\n"; + } + } +?> + +

    + +
    +
    +
    + Top-10 Platinum List +
    + Applications which install and run flawlessly on an out-of-the-box Wine installation +
    +
    + + + + + +
    ApplicationDescriptionScreenshot
    +
    +
    +
    + +
    +
    +
    + Top-10 Gold List +
    + Applications that work flawlessly with some special configuration +
    +
    + + + + + +
    ApplicationDescriptionScreenshot
    +
    +
    +
    + +
    +
    +
    + Top-10 Silver List +
    + Applications with minor issues that do not affect typical usage +
    +
    + + + + + +
    ApplicationDescriptionScreenshot
    +
    +
    + +

    + +

    Other Wine Application Compatibility Sites

    +

    +Wine-Reviews: Is a Wine application and game +Blog, with tips and how-to's on getting listed applications and games to run. +

    +
    + +\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "
    \n"; +echo 'Get Firefox'."\n"; +echo "\n"; +echo ' + Xinha'."\n"; +echo "
    \n"; +echo "\n"; + +apidb_footer(); +?> diff --git a/jquery.js b/jquery.js new file mode 100644 index 0000000..82b98e1 --- /dev/null +++ b/jquery.js @@ -0,0 +1,32 @@ +/* + * jQuery 1.2.6 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $ + * $Rev: 5685 $ + */ +(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else +return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else +return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else +selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else +this.value=value;});},html:function(value){return value==undefined?(this[0]?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else +return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else +jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}function now(){return+new Date;}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else +jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
    ","
    "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else +ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&¬xml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&¬xml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&¬xml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else +while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else +for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
    ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else +xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else +jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else +for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else +s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else +e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})(); \ No newline at end of file diff --git a/jquery.pngfix.js b/jquery.pngfix.js new file mode 100644 index 0000000..396503c --- /dev/null +++ b/jquery.pngfix.js @@ -0,0 +1,126 @@ +/** + * jQuery (PNG Fix) v1.2 + * Microsoft Internet Explorer 24bit PNG Fix + * + * The MIT License + * + * Copyright (c) 2007 Paul Campbell (pauljamescampbell.co.uk) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @param Object + * @return Array + */ +(function($) { + + $.fn.pngfix = function(options) { + + // Review the Microsoft IE developer library for AlphaImageLoader reference + // http://msdn2.microsoft.com/en-us/library/ms532969(VS.85).aspx + + // ECMA scope fix + var elements = this; + var settings = $.extend({ + imageFixSrc: false, + sizingMethod: false + }, options); + + if(!$.browser.msie || ($.browser.msie && $.browser.version >= 7)) { + return(elements); + } + + function setFilter(el, path, mode) { + var fs = el.attr("filters"); + var alpha = "DXImageTransform.Microsoft.AlphaImageLoader"; + if (fs[alpha]) { + fs[alpha].enabled = true; + fs[alpha].src = path; + fs[alpha].sizingMethod = mode; + } else { + el.css("filter", 'progid:' + alpha + '(enabled="true", sizingMethod="' + mode + '", src="' + path + '")'); + } + } + + function setDOMElementWidth(el) { + if(el.css("width") == "auto" & el.css("height") == "auto") { + el.css("width", el.attr("offsetWidth") + "px"); + } + } + + return( + elements.each(function() { + + // Scope + var el = $(this); + + if(el.attr("tagName").toUpperCase() == "IMG" && (/\.png/i).test(el.attr("src"))) { + if(!settings.imageFixSrc) { + + // Wrap the in a then apply style/filters, + // removing the tag from the final render + el.wrap(""); + var par = el.parent(); + par.css({ + height: el.height(), + width: el.width(), + display: "inline-block" + }); + setFilter(par, el.attr("src"), "scale"); + el.remove(); + } else if((/\.gif/i).test(settings.imageFixSrc)) { + + // Replace the current image with a transparent GIF + // and apply the filter to the background of the + // tag (not the preferred route) + setDOMElementWidth(el); + setFilter(el, el.attr("src"), "image"); + el.attr("src", settings.imageFixSrc); + } + + } else { + var bg = new String(el.css("backgroundImage")); + var matches = bg.match(/^url\("(.*)"\)$/); + if(matches && matches.length) { + + // Elements with a PNG as a backgroundImage have the + // filter applied with a sizing method relevant to the + // background repeat type + setDOMElementWidth(el); + el.css("backgroundImage", "none"); + + // Restrict scaling methods to valid MSDN defintions (or one custom) + var sc = "crop"; + if(settings.sizingMethod) { + sc = settings.sizingMethod; + } + setFilter(el, matches[1], sc); + + // Fix IE peek-a-boo bug for internal links + // within that DOM element + el.find("a").each(function() { + $(this).css("position", "relative"); + }); + } + } + + }) + ); + } + +})(jQuery) \ No newline at end of file diff --git a/maintainerdelete.php b/maintainerdelete.php new file mode 100644 index 0000000..5f5d4f1 --- /dev/null +++ b/maintainerdelete.php @@ -0,0 +1,86 @@ +isLoggedIn()) + util_show_error_page_and_exit("You need to be logged in to resign from being a maintainer."); + + +if($aClean['iConfirmed']) +{ + $oApp = new Application($aClean['iAppId']); + if($aClean['iSuperMaintainer']) + { + apidb_header("You have resigned as super maintainer of ".$oApp->sName); + $result = Maintainer::deleteMaintainer($_SESSION['current'], $aClean['iAppId'], null); + } else + { + $oVersion = new Version($aClean['iVersionId']); + apidb_header("You have resigned as maintainer of ".$oApp->sName." ".$oVersion->sName); + $result = Maintainer::deleteMaintainer($_SESSION['current'], $oApp->iAppId, $oVersion->iVersionId); + } +/* echo html_frame_start("Removing",400,"",0); +*/ + if($result) + { + if($aClean['iSuperMaintainer']) + echo "You were removed as a super maintainer of ".$oApp->sName; + else + echo "You were removed as a maintainer of ".$oApp->sName." ".$oVersion->sName; + } +} else +{ + if($aClean['iSuperMaintainer']) + apidb_header("Confirm super maintainer resignation of ".$oApp->sName); + else + apidb_header("Confirm maintainer resignation of ".$oApp->sName." ".$oVersion->sName); + + + echo '
    ',"\n"; + + echo html_frame_start("Confirm",400,"",0); + echo "\n"; + echo ""; + echo ""; + echo ""; + echo ""; + + if($aClean['iSuperMaintainer']) + { + echo "\n"; + echo '\n"; + echo '
    Are you sure that you want to be removed as a super maintainer of this application?
    ', "\n"; + } else + { + echo "
    Are you sure that you want to be removed as a maintainer of this application?
    ', "\n"; + } + + echo "
    "; +} + +echo html_frame_end(); + +apidb_footer(); + +?> diff --git a/objectManager.php b/objectManager.php new file mode 100644 index 0000000..65b867d --- /dev/null +++ b/objectManager.php @@ -0,0 +1,170 @@ +setState($aClean['sState']); +else if(getInput('bIsRejected', $aClean) == 'true') // Compatibility with old URLs + $oObject->setState('rejected'); +else if(getInput('bIsQueue', $aClean) == 'true') + $oObject->setState('queued'); +else + $oObject->setState('accepted'); + +if(isset($aClean['sReturnToTitle'])) + $oObject->setReturnToTitle($aClean['sReturnToTitle']); + +if(isset($aClean['sReturnTo'])) + $oObject->setReturnTo($aClean['sReturnTo']); + +$oObject->getMultiPageDataFromInput($aClean); +$oObject->setSortInfo($aClean); +$oObject->getFilterInfoFromInput($aClean); + +$sClass = $oObject->getClass(); +$oOtherObject = new $sClass($oObject->getId()); + +/* Certain actions must be performed before the header is set. */ +/* processForm returns TRUE on success, or a user-readable list of errors + on failure */ +$sErrors = $oObject->processForm($aClean); + +if(array_key_exists("sAction", $aClean)) + $sAction = $aClean['sAction']; +else + $sAction = ""; + +/* Handle things that need to be done before showing any output */ +if($sAction) +{ + switch($aClean['sAction']) + { + case 'add': + $oObject->handle_anonymous_submission($aClean); + break; + + case 'changeParent': + /* Provided the necessary values are present, an object may be moved + to another parent without any confirmation */ + if($oObject->getId() && getInput('iNewId', $aClean)) + $oObject->change_parent($aClean['iNewId']); + break; + + case 'moveChildren': + /* Provided the necessary values are present, an object's children may be moved + without any confirmation */ + if($oObject->getId() && $aClean['iNewId']) + $oObject->move_children($aClean['iNewId']); + break; + + case 'doPurgeRejected': + /* Purge some or all rejected entries */ + $oObject->purgeRejected($aClean); + break; + } +} + +/* If no action is specified, use a default depending on other parameters */ +if(!$sAction) +{ + if($oObject->getId()) + $sAction = "view"; +} + +apidb_header($oObject->get_title($sAction)); + +/* display a particular element */ +if(($oObject->getId() || $oObject->IsNullIdAllowed($sAction)) && $sAction != "add") +{ + switch($sAction) + { + case "cancel": + $oObject->display_table($aClean); /* go back to the queue */ + break; + + case "edit": + $oObject->display_entry_for_editing($aClean, $sErrors); + break; + + case 'moveToNewParent': + $oObject->move_to_new_parent($aClean, $sErrors); + break; + + case 'showChangeParent': + $oObject->display_change_parent(); + break; + + case "showMoveChildren": + $oObject->display_move_children(); + break; + + case "delete": + $oObject->delete_prompt(); + break; + + case "view": + $oObject->view($_SERVER['REQUEST_URI'], $aClean); + break; + } +} else +{ + switch($sAction) + { + case 'add': + $oObject->add_entry($aClean, $sErrors); + break; + + case 'purgeRejected': + $oObject->displayPurgeRejected(); + break; + + default: + $oObject->display_table($aClean); + } +} + +apidb_footer(); + +?> diff --git a/path.php b/path.php new file mode 100644 index 0000000..bf6d66d --- /dev/null +++ b/path.php @@ -0,0 +1,3 @@ + diff --git a/preferences.php b/preferences.php new file mode 100644 index 0000000..962939a --- /dev/null +++ b/preferences.php @@ -0,0 +1,231 @@ +hasPriv("admin")) + { + if($r->name == "query:mode") + continue; + if($r->name == "sidebar") + continue; + if($r->name == "window:query") + continue; + if($r->name == "query:hide_header") + continue; + if($r->name == "query:hide_sidebar") + continue; + if($r->name == "debug") + continue; + } + + $input = html_select("pref_$r->name", explode('|', $r->value_list), + $oUser->getpref($r->name, $r->def_value)); + + $oTableRow = new TableRow(); + $oTableCell = new TableCell("  $r->description"); + $oTableRow->AddCell($oTableCell); + $oTableCell = new TableCell($input); + $oTableRow->AddCell($oTableCell); + + $aTableRows[] = $oTableRow; + } + + return $aTableRows; +} + +// returns an array of TableRow instances +function show_user_fields($oUser) +{ + $aTableRows = array(); + + $sWineRelease = $oUser->sWineRelease; + if($oUser->hasPriv("admin")) + $sAdminChecked = 'checked="true"'; + else + $sAdminChecked = ""; + + // Edit admin privilege + if($_SESSION['current']->hasPriv("admin")) + { + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("  Administrator"); + $oTableRow->AddTextCell(""); + + $aTableRows[] = $oTableRow; + } + + + $oTableRow = new TableRow(); + $oTableRow->AddTextCell("  Wine version"); + + $sBugzillaVersionList = make_bugzilla_version_list("sWineRelease", + $sWineRelease); + $oTableRow->AddCell(new TableCell($sBugzillaVersionList)); + $aTableRows[] = $oTableRow; + + // return the table rows + return $aTableRows; +} + + +if(!$_SESSION['current']->isLoggedIn()) + util_show_error_page_and_exit("You must be logged in to edit preferences"); + +// we come from the administration to edit an user +if($_SESSION['current']->hasPriv("admin") && + isset($aClean['iUserId']) && + isset($aClean['iLimit']) && + isset($aClean['sOrderBy']) && + in_array($aClean['sOrderBy'],array("email","realname","created")) +) +{ + $oUser = new User($aClean['iUserId']); +} else +{ + $oUser = &$_SESSION['current']; +} + +if(isset($aClean['sSubmit']) && $aClean['sSubmit'] == "Update") +{ + while(list($sKey, $sValue) = each($aClean)) + { + /* if a parameter lacks 'pref_' at its head it isn't a */ + /* preference so skip over processing it */ + if(!ereg("^pref_(.+)$", $sKey, $arr)) + continue; + $oUser->setPref($arr[1], $sValue); + } + + /* make sure the user enters the same password twice */ + if ($aClean['sUserPassword'] == $aClean['sUserPassword2']) + { + $str_passwd = $aClean['sUserPassword']; + } + else if ($aClean['sUserPassword']) + { + addmsg("The Passwords you entered did not match.", "red"); + } + + /* update user data fields */ + $oUser->sEmail = $aClean['sUserEmail']; + $oUser->sRealname = $aClean['sUserRealname']; + $oUser->sWineRelease = $aClean['sWineRelease']; + + /* if the password was empty in both cases then skip updating the users password */ + if($str_passwd != "") + { + if(!$oUser->update_password($str_passwd)) + addmsg("Failed to update password", "red"); + } + + if ($oUser->update() == SUCCESS) + { + addmsg("Preferences Updated", "green"); + // we were managing an user, let's go back to the admin after + // updating tha admin status + if($oUser->iUserId == $aClean['iUserId'] && + $_SESSION['current']->hasPriv("admin")) + { + if($aClean['bIsAdmin'] == "true") + $oUser->addPriv("admin"); + else + $oUser->delPriv("admin"); + util_redirect_and_exit(BASE."admin/adminUsers.php?iUserId=".$oUser->iUserId. + "&sSearch=".$aClean['sSearch']."&iLimit=".$aClean['iLimit']. + "&sOrderBy=".$aClean['sOrderBy']."&sSubmit=true"); + } + } + else + { + addmsg("There was a problem updating your user info", "red"); + } +} + +apidb_header("User Preferences"); + +echo "
    \n"; + +echo "\n"; + +// if we manage another user we give the parameters to go back to the admin +if( isset($aClean['iUserId']) && $oUser->iUserId == $aClean['iUserId']) +{ + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; +} + +echo html_frame_start("Preferences for ".$oUser->sRealname, "80%"); + +// build a table +$oTable = new Table(); +$oTable->SetWidth("100%"); +$oTable->SetAlign("left"); +$oTable->SetCellSpacing(0); +$oTable->SetClass("box-body"); + +// retrieve the form editing rows +$aTableRows = GetEditAccountFormRows($oUser->sEmail, $oUser->sRealname); +foreach($aTableRows as $oTableRow) + $oTable->AddRow($oTableRow); + +// retrieve the user fields +$aTableRows = show_user_fields($oUser); +foreach($aTableRows as $oTableRow) + $oTable->AddRow($oTableRow); + +// if we don't manage another user +if( !isset($aClean['iUserId']) || $oUser->iUserId != $aClean['iUserId']) +{ + $aTableRows = build_prefs_list($oUser); + foreach($aTableRows as $oTableRow) + { + $oTable->AddRow($oTableRow); + } +} +echo $oTable->GetString(); + +echo html_frame_end(); +echo "

    \n"; +echo "\n"; + +echo "
    \n"; + +apidb_footer(); +?> diff --git a/queueditems.php b/queueditems.php new file mode 100644 index 0000000..52b4f03 --- /dev/null +++ b/queueditems.php @@ -0,0 +1,69 @@ +iUserId); + +if(!$oUser->isLoggedIn()) +{ + login_form(); + exit; +} + +apidb_header("View Your Queued Items"); + +/* Test data */ +if($sResult = testData::listSubmittedBy($oUser->iUserId)) +{ + echo html_frame_start("Your Queued Test Results","90%"); + echo $sResult; + echo html_frame_end(" "); +} +else + echo "You have no queued test results.

    \n"; + +/* Applications */ +if($sResult = Application::listSubmittedBy($oUser->iUserId)) +{ + echo html_frame_start("Your Queued Applications","90%"); + echo $sResult; + echo html_frame_end(" "); +} else + echo "You have no queued applications.

    \n"; + +/* Versions */ +if($sResult = Version::listSubmittedBy($oUser->iUserId)) +{ + echo html_frame_start("Your Queued Versions","90%"); + echo $sResult; + echo html_frame_end(" "); +} else + echo "You have no queued versions.

    \n"; + +/* Bug links */ +if($sResult = bug::listSubmittedBy($oUser->iUserId)) +{ + echo html_frame_start("Your Queued Bug Links","90%"); + echo $sResult; + echo html_frame_end(" "); +} else + echo "You have no queued bugs.

    \n"; + +/* Application data */ +if($sResult = appData::listSubmittedBy($oUser->iUserId)) +{ + echo html_frame_start("Your Queued Application Data","90%"); + echo $sResult; + echo html_frame_end(" "); +} else + echo "You have no queued application data.

    \n"; + +apidb_footer(); + +?> diff --git a/screenshots.php b/screenshots.php new file mode 100644 index 0000000..fdb1d0b --- /dev/null +++ b/screenshots.php @@ -0,0 +1,178 @@ +600000) + { + addmsg("Your screenshot was not accepted because it is too big. Please try to keep your screenshots under 600KB by saving games/video screenshots to jpeg and normal applications to png you might be able to achieve very good results with less bytes", "red"); + } else + { + $oScreenshot = new Screenshot(); + $oScreenshot->iVersionId = $aClean['iVersionId']; + $oScreenshot->sDescription = $aClean['sScreenshotDesc']; + $oScreenshot->hFile = $_FILES['sImageFile']; + $oScreenshot->create(); + $oScreenshot->free(); + } + } elseif($aClean['sCmd'] == "delete" && is_numeric($aClean['iImageId'])) // process screenshot deletion + { + $oScreenshot = new Screenshot($aClean['iImageId']); + $oScreenshot->delete(); + $oScreenshot->free(); + } + util_redirect_and_exit(apidb_fullurl("screenshots.php?iAppId=".$aClean['iAppId']."&iVersionId=".$aClean['iVersionId'])); +} + + +// we didn't issued any command +$hResult = Screenshot::get_screenshots($aClean['iAppId'], $aClean['iVersionId']); +apidb_header("Screenshots"); +$oApp = new Application($aClean['iAppId']); +$oVersion = new Version($aClean['iVersionId']); + +if($hResult && query_num_rows($hResult)) +{ + echo ' '; // Add some space between title bars + echo html_frame_start("Screenshot Gallery for ".$oApp->sName, 500); + + // display thumbnails + $c = 1; + + // optimization so we don't have to perform as many database queries + // only update this variable when $iCurrentVersionId changes + $bUserIsMaintainerOfVersion = false; + + echo "
    \n"; + echo ' '; // Add some space between title bars + + while($oRow = query_fetch_object($hResult)) + { + // if the current version changed then update the current version + // and close the previous html frame if this isn't the + // first frame + if($oRow->versionId != $iCurrentVersionId) + { + if($iCurrentVersionId) + { + echo "
    \n"; + echo html_frame_end(); + $c=1; + } + $iCurrentVersionId = $oRow->versionId; + $bUserIsMaintainerOfVersion = $_SESSION['current']->isMaintainer($iCurrentVersionId); + + echo html_frame_start("Version ".Version::lookup_name($iCurrentVersionId)); + echo "
    \n"; + } + $oScreenshot = new Screenshot($oRow->id); + $img = $oScreenshot->get_thumbnail_img(); + + // display image + echo "\n"; + + // end row if counter of 3 + if ($c % 3 == 0) echo "\n"; + + $c++; + } + echo "
    \n"; + echo $img; + echo "
    ". substr($oRow->description,0,20). "\n"; + + //show admin delete link + if($_SESSION['current']->isLoggedIn() && + ( + $_SESSION['current']->hasPriv("admin") || + $bUserIsMaintainerOfVersion + ) + ) + { + $oM = new objectManager("screenshot"); + $oM->setReturnTo("screenshots.php?iAppId=".$oScreenshot->iAppId."&iVersionId=".$oScreenshot->iVersionId); + echo '
    [iScreenshotId, "Delete Screenshot").'">Delete]'; + } + + echo "

    \n"; + + echo html_frame_end(); // close the current version we are displaying + echo html_frame_end(); // close the "Screenshot Gallary..." html frame +} else +{ + echo "

    There are currently no screenshots for the selected version of this application."; + echo "
    Please consider submitting a screenshot for the selected version yourself.

    "; +} + +// let's show the screenshot uploading box, but only +// if the user is logged in +if($aClean['iVersionId'] && $_SESSION['current']->isLoggedIn()) +{ + echo "

    "; + echo ""; + echo "
    Please follow these simple rules
      "; + echo "
    • Do not upload screenshots of error messages, installers, game menus etc.
    • "; + echo "
    • Crop the image so that only the application is shown and not your desktop.
    • "; + echo "

    "; + + echo '
    ',"\n"; + echo html_frame_start("Upload Screenshot","400","",0); + echo '',"\n"; + + echo '',"\n"; + echo '',"\n"; + + echo '',"\n"; + echo '
    Image
    Description
    ',"\n"; + echo html_frame_end(); + echo '',"\n"; + echo '',"\n"; + echo '
    ',"\n"; +} else if(!$_SESSION['current']->isLoggedIn()) // else let the person know that if they log in they can submit screenshots +{ + echo '
    '; + echo "Log in to submit screenshots
    \n"; +} else +{ + echo html_frame_start("Upload Screenshot", "30%"); + echo 'If you would like to submit screenshots, please select an application version below.
    '; + echo ''; + echo html_frame_end(); +} + +echo html_back_link(1); + +apidb_footer(); +?> diff --git a/scripts.js b/scripts.js new file mode 100644 index 0000000..524489d --- /dev/null +++ b/scripts.js @@ -0,0 +1,120 @@ +function openWin(fileToOpen,nameOfWindow,width,height) { + myWindow = window.open("",nameOfWindow,"menubar=no,scrollbars=yes,status=no,width="+width+",height="+height); + myWindow.document.open(); + myWindow.document.write(''); + myWindow.document.write('Screenshot Viewer') + myWindow.document.write(''); + myWindow.document.write('Screenshot'); + myWindow.document.write(''); + myWindow.document.close(); +} + +function deleteURL(text, url) { + if (confirm(text)) { + self.location = url; + } +} + +function ChangeTr(tableRow, bRowActive, sHighlightColor, sInactiveColor, + sTextDecorationHighlight, sTextDecorationInactive) +{ + if (bRowActive) + { + tableRow.style.backgroundColor = sHighlightColor; + tableRow.style.cursor = "hand"; + tableRow.style.textDecoration = sTextDecorationHighlight; + } + else + { + tableRow.style.backgroundColor = sInactiveColor; + tableRow.style.cursor = "pointer"; + tableRow.style.textDecoration = sTextDecorationInactive; + } +} + +function DoNav(sUrl) +{ + document.location.href = sUrl; +} + +/** + * commentId is the uniquely identifying comment id from the database. + * It is also used as the div id for the comment body. + */ +function showComment(commentid) +{ + elem = $(commentid); + if(elem.visible() && !elem.empty()) + { + elem.hide(); + } + else + { + // Cache the contents of the comment body so we don't need to hit db again. + if(elem.empty()) + { + new Ajax.Updater(commentid, 'comment_body.php', { + method: 'get', + parameters: { + iCommentId: commentid + } + }); + } + elem.show(); + } +} +/* provide a hint to the user about the selected rating */ +var ratingdesc=[ + "", + " Works flawlessly out of the box - no problems ", + " Works flawlessly with DLL overrides, third party software or other settings ", + " Works excellently for normal use;works fine in singleplayer but not multi ", + " Works but has issues for normal use ", + " Does not run or cannot be installed with Wine " + ]; +var ratingstyle =[ + "", + "platinum", + "gold", + "silver", + "bronze", + "garbage" + ]; +function showHint(o){ + if(o) + { + $('hint').innerHTML=ratingdesc[o.selectedIndex]; + $w($('hint').className).map( function(x){ $('hint').removeClassName(x); }) + $('hint').addClassName(ratingstyle[o.selectedIndex]); + } +} +/* too many people still call Wine "WINE" */ +function bind_tolowerWINE() +{ + [ + $('app_editor'), + $('version_editor'), + $('Test1'), + $('Test2'), + $('Test3'), + $('extra_comments')].map( function(x) + { + if(x) + { + x.observe('change', tolowerWINE); + } + }); +} +function tolowerWINE(o) + { + o.element().value = o.element().value.replace(/WINE([^A-Z]+)|(WINE)$/g,"Wine$1"); + } +/* executed when document is ready */ +document.observe("dom:loaded", function() { + showHint($('ratingSelect')); + bind_tolowerWINE(); + }); diff --git a/search.php b/search.php new file mode 100644 index 0000000..4841ad0 --- /dev/null +++ b/search.php @@ -0,0 +1,19 @@ + diff --git a/search_results.php b/search_results.php new file mode 100644 index 0000000..db181b5 --- /dev/null +++ b/search_results.php @@ -0,0 +1,39 @@ +\n"; + +echo ' + +
    + + + +'; + +echo "
    \n"; + +apidb_footer(); + +?> diff --git a/site_outage.html b/site_outage.html new file mode 100644 index 0000000..ec74e8c --- /dev/null +++ b/site_outage.html @@ -0,0 +1,12 @@ + + +AppDB temporarily offline + + +

    Wine Application Database

    +

    Sorry, the AppDB is temporarily offline

    +

    While we are down you might want to checkout the main +WineHQ site

    + + + diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..dc41329 --- /dev/null +++ b/styles.css @@ -0,0 +1,295 @@ +/* Body Document Defaults */ +BODY { + background-color: #000000; + color: #000000; + background-image: url('images/bg.jpg'); + background-repeat: no-repeat; + font-family: "bitstream vera sans", "verdana", "arial", "helvetica", sans-serif; + margin: 0; + font-size: 10pt; + } + +/* wine logo image */ +#logo_glass_big { + position: absolute; + z-index: 2; + top: 0px; + left: 0px; + width: 200px; + height: 313px; + } +#logo_glass { + position: absolute; + z-index: 2; + top: 20px; + left: 50px; + width: 100px; + height: 157px; + } +#logo_text { + position: absolute; + z-index: 3; + top: 40px; + left: 110px; + width: 186px; + height: 58px; + } +#logo_blurb { + position: absolute; + z-index: 4; + top: 92px; + left: 130px; + font-size: 12px; + color: #999999; + } + +/* search box */ +#search_box { + text-align: right; + position: absolute; + z-index: 5; + top: 50px; + right: 20px; + width: 250px; + margin: 0; + padding: 0; + font-size: 10px; + } +#search_box INPUT { font-size: 12px; width: 175px; margin: 0; padding: 2px; border: 1px inset red; } + +/* top tabs */ +#tabs { + position: absolute; + z-index: 6; + top: 0px; + right: 10px; + margin: 0px; + padding: 0px; + } +#tabs UL { + list-style: none; + padding: 0; + margin: 0; + } +#tabs LI { + float: left; + width: 112px; + height: 28px; + margin: 0px 2px 0px 2px; + padding: 0; + text-align: center; + background-image: url('images/tab_u.png'); + background-repeat: no-repeat; + } +#tabs LI.s { background-image: url('images/tab_s.png'); } +#tabs LI.s A { font-weight: bold; } +#tabs LI:hover { background-image: url('images/tab_h.png'); } +#tabs A { + display: block; + width: 108px; + height: 23px; + padding-top: 3px; + font-size: 16px; color: white; text-decoration: none; + } + +/* sidebar navigation */ +#sidebar { + position: absolute; + z-index: 6; + top: 200px; + left: 0px; + margin: 0px; + padding: 0px; + width: 156px; + } +#sidebar UL { + list-style: none; + width: 156px; + padding: 0; + margin: 0 0 10px 0; + } +#sidebar LI { + width: 156px; + margin: 0; + padding: 5px 0 0 0; + background-image: url('images/side_menu_bg.png'); + background-repeat: repeat-y; + font-size: 10px; + color: white; + } +#sidebar LI P { margin: 0; padding: 0 15px 5px 15px; } +#sidebar LI.top { + height: 33px; + margin: 0; + padding: 0; + background-image: url('images/side_menu_top.png'); + background-repeat: no-repeat; + font-weight: bold; + font-size: 10px; + } +#sidebar LI.top P { margin: 0; padding: 10px 0 0 5px; } +#sidebar LI.bot { + height: 16px; + margin: 0; + padding: 0; + background-image: url('images/side_menu_bot.png'); + background-repeat: no-repeat; + } +#sidebar A { font-size: 10px; color: white; text-decoration: none; } +#sidebar A:hover { font-size: 10px; text-decoration: underline; } + +/* main content well */ +#main_content { + padding: 85px 10px 10px 100px; + } + +/* main content well front page left column */ +#main_left { + width: 58%; + width: expression("55%"); /* For IE */ + margin: 0 10px 0 0; + float: left; + display: inline; + } + +/* main content well front page right column */ +#main_right { + width: 40%; + width: expression("30%"); /* For IE */ + margin: 0; + float: right; + display: inline; + } + +/* Language Select */ +#langsel { + clear: both; + color: #ffffff; + text-align: left; + margin: 0 0 0 110px; + font-size: 8pt; + } +#langsel A { color: #ffffff; text-decoration: none; } +#langsel A:hover { color: red; text-decoration: underline; } + +/* footer */ +#footer { + clear: both; + color: #ffffff; + text-align: right; + padding-right: 20px; + } +#footer IMG { vertical-align: middle; } + +/* header text */ +H1.title { color: #A50D0D; border-bottom: 1px solid #A50D0D; margin: 0px; } +H3.title { color: #A50D0D; border-bottom: 1px solid #A50D0D; margin: 0px; } +P.newsdate { color: #4e4e4e; font-size: 10pt; text-align: right; margin: 0 5px 10px 0;} +P.newstitle { color: #4e4e4e; font-size: 12pt; font-weight: bold; border-bottom: 1px solid #C0C0C0; margin-bottom: 5px; } +P.newstitle A { color: #4e4e4e; text-decoration: none; } +P.newstitle A:hover { color: #FF6666; text-decoration: none; } +DIV.newsblock { margin: 0 5px 25px 10px; padding: 0; } + +/* stuff */ +img { border: 0; } + +/* Link Colors */ +A { color: #A50D0D; } +A:visited { color: #FF0000; } +A:hover { color: #FF6666; text-decoration: underline; } +A:active { color: #FF0000; } +A.hidden { text-decoration: none; color: #000000; } + +/* General fonts and sizes */ +OL,UL,P { font-size: 10pt; } +TD,TR,TH { font-size: 10pt; } +INPUT { font-size: 10pt; } +PRE { + font-family: monospace; font-size: 10pt; + white-space: pre-wrap; + white-space: -moz-pre-wrap !important; + } +.small { font-size: 8pt; } + +/* Hn Sizes */ +H1 { font-size: 20pt; } +H2 { font-size: 18pt; } +H3 { font-size: 14pt; } +H4 { font-size: 12pt; } +H5 { font-size: 10pt; } + +/* HR */ +hr +{ + border: 0; + color: #A50D0D; + background-color: #A50D0D; + height: 1px; + width: 100%; + text-align: left; +} + +/* Rounded Corner Box */ +div.rbox { display:block; margin: 0px; } +div.rbox b.rtop, b.rbottom { display:block; margin: 0px; } +div.rbox b.rtop b, b.rbottom b { display:block; height: 1px; overflow: hidden; background: #FFFFFF; } +div.rbox b.r1 { margin: 0 5px; } +div.rbox b.r2 { margin: 0 3px; } +div.rbox b.r3 { margin: 0 2px; } +div.rbox b.rtop b.r4, b.rbottom b.r4 { margin: 0 1px; height: 2px} +div.rbox div.content { margin: 0; background-color: #FFFFFF; } + +/* template navigation links */ +.link-container { position: relative; height: 1.2em; } +.link-container p { position: absolute; width: 50%; margin: 0; } +.left-link { left: 0; } +.right-link { right: 0; text-align: right; } + +/* Status colors */ +.hdr { background-color: #000000; color: #ffffff; } +.pct0 { background-color: #ff5050; } +.pct5 { background-color: #ff5d4f; } +.pct10 { background-color: #ff694e; } +.pct15 { background-color: #ff764d; } +.pct20 { background-color: #ff824b; } +.pct25 { background-color: #ff8f4a; } +.pct30 { background-color: #ff9b49; } +.pct35 { background-color: #ffa848; } +.pct40 { background-color: #ffb447; } +.pct45 { background-color: #ffc146; } +.pct50 { background-color: #ffcd45; } +.pct55 { background-color: #ffda43; } +.pct60 { background-color: #ffe642; } +.pct65 { background-color: #fff341; } +.pct70 { background-color: #ffff40; } +.pct75 { background-color: #dcff48; } +.pct80 { background-color: #c8ff50; } +.pct85 { background-color: #b4ff58; } +.pct90 { background-color: #a0ff60; } +.pct95 { background-color: #8cff60; } +.pct100 { background-color: #60ff60; } +.nonexistent { background-color: #ff5050; } +.poor { background-color: #ff8f4a; } +.outdated { background-color: #ffcd45; } +.outdadeq { background-color: #ffff40; } +.adequate { background-color: #dcff48; } +.adeqgood { background-color: #c0ff54; } +.good { background-color: #60ff60; } + +/* ToDo colors */ +.todo { background-color: red; } +.inprogress { background-color: yellow; } +.done { background-color: limegreen; } +.invalid { color: gray; text-decoration: line-through; } + +/* Fun Projects */ +.works { background-color: lightblue; } +.abandoned { background-color: gray; } +.modified { font-weight: bold; } +.submitted { font-style: italic; } +.committed { font-style: italic; color: gray; } + +/* App Support status */ +.gold { background-color: wheat; } +.silver { background-color: silver; } + diff --git a/tables/.htaccess b/tables/.htaccess new file mode 100644 index 0000000..c9c4d1b --- /dev/null +++ b/tables/.htaccess @@ -0,0 +1,2 @@ +deny from all + diff --git a/tables/app_category.sql b/tables/app_category.sql new file mode 100644 index 0000000..7f6f14b --- /dev/null +++ b/tables/app_category.sql @@ -0,0 +1,66 @@ +use apidb; + +INSERT INTO appCategory VALUES ('0', 'MAIN', 'Root category', NULL); +UPDATE appCategory SET catId = '0' WHERE catName = 'MAIN' LIMIT 1; +INSERT INTO appCategory VALUES (1, 'Audio', 'Audio related applications', 29); +INSERT INTO appCategory VALUES (2, 'Games', 'Games', 0); +INSERT INTO appCategory VALUES (3, 'Graphics', 'Graphics viewers, editors, graphics demos, screensavers etc.', 29); +INSERT INTO appCategory VALUES (4, 'Productivity', 'Productivity applications', 0); +INSERT INTO appCategory VALUES (5, 'Networking & Communication', 'Network, Internet related programs and comm stuff', 0); +INSERT INTO appCategory VALUES (6, 'Programming / Software Engineering', 'Languages, Compilers, IDEs, CASE tools etc.', 0); +INSERT INTO appCategory VALUES (7, 'Utilities', 'Misc. Utilities', 0); +INSERT INTO appCategory VALUES (8, 'Scientific/Technical/Math', 'Scientific and mathematic applications', 0); +INSERT INTO appCategory VALUES (10, 'File System', 'File System Utilities (e.g. CD writer stuff, file managers, shells, ...)', 7); +INSERT INTO appCategory VALUES (11, 'Compression', 'Compression Tools', 7); +INSERT INTO appCategory VALUES (13, 'Sound Editing', 'Sound editing suites, recorders, mixing and sampling.', 1); +INSERT INTO appCategory VALUES (14, 'Audio Players', 'MP3, WAV, and other format audio players.', 1); +INSERT INTO appCategory VALUES (16, '1st Person Shooter', 'Games such as Doom, Quake, Half-Life.', 2); +INSERT INTO appCategory VALUES (18, 'Graphics Viewer', 'Image viewing', 3); +INSERT INTO appCategory VALUES (19, 'Graphics Editing', 'Image editing/vector drawing software', 3); +INSERT INTO appCategory VALUES (21, 'Animation/Rendering/3D', 'Image animation for multimedia or web', 3); +INSERT INTO appCategory VALUES (23, 'Word Processing', 'Type, edit, print, OCR!', 4); +INSERT INTO appCategory VALUES (24, 'Spreadsheet', 'Do it yourself Number crunching', 4); +INSERT INTO appCategory VALUES (25, 'Database', 'Relational Database', 4); +INSERT INTO appCategory VALUES (26, 'Presentation', 'Slide Shows with animation and sound and flowchart tools', 4); +INSERT INTO appCategory VALUES (27, 'Web Design', 'Create your own web page', 4); +INSERT INTO appCategory VALUES (29, 'Multimedia', 'Graphics, Audio and Video', 0); +INSERT INTO appCategory VALUES (31, 'Video', 'Video players, editors and codecs', 29); +INSERT INTO appCategory VALUES (33, 'Browsers', 'Netscape, Opera, Mozilla, Mosaic, IE, ...', 5); +INSERT INTO appCategory VALUES (35, 'Email, news and Groupware', 'Email and related programs.', 5); +INSERT INTO appCategory VALUES (37, 'Chat, Instant Messaging, Telephony', 'AIM, ICQ, NetMeeting, Speak Freely, ...', 5); +INSERT INTO appCategory VALUES (45, 'Net Tools', 'Tools such as proxies, web crawlers, search engines, ...', 5); +INSERT INTO appCategory VALUES (43, 'Office Suites', 'Productivity apps that contain bundles of applications.', 4); +INSERT INTO appCategory VALUES (47, 'Reference/Documentation/Info', 'Encyclopedias, information resources, data tracking, ...', 0); +INSERT INTO appCategory VALUES (49, 'EDA/Measurement', 'Electronics design tools, measurement and stuff', 8); +INSERT INTO appCategory VALUES (51, 'Mathematics', 'Mathematical and Statistical software.', 8); +INSERT INTO appCategory VALUES (53, 'Text Editors', 'Multipurpose text editing tool. No formatting just text.', 4); +INSERT INTO appCategory VALUES (55, 'Role Playing Games', 'Games where you build up your characters through battle and experience.', 2); +INSERT INTO appCategory VALUES (57, 'Strategy Games', 'Build your army, conquer the world', 2); +INSERT INTO appCategory VALUES (59, 'CAD/CAE', 'Computer Aided Design, Computer Aided Engineering', 8); +INSERT INTO appCategory VALUES (61, 'Office Utilities', 'Misc Office tools that usually work in conjunction with other Office software.', 4); +INSERT INTO appCategory VALUES (63, 'Finance/Accounting/Project/CRM', 'Personal and Business Finance Software and project planning, CRM (Customer Relationship Management).', 4); +INSERT INTO appCategory VALUES (65, 'Emulators', 'Software that emulates game hardware.', 2); +INSERT INTO appCategory VALUES (71, 'Flowchart/Diagraming/graphs', 'Software to design flowcharts and diagrams', 8); +INSERT INTO appCategory VALUES (69, 'Adventures', 'Graphical Adventure Games', 2); +INSERT INTO appCategory VALUES (74, 'File transfer/sharing', 'FTP, NFS, document sharing, Samba, scp, ...', 5); +INSERT INTO appCategory VALUES (76, 'Educational games / children', 'Games that encourage learning.', 2); +INSERT INTO appCategory VALUES (78, 'Card, Puzzle and Board Games', 'Card Games, mind puzzles and \\"traditional\\" stuff.', 2); +INSERT INTO appCategory VALUES (82, 'Educational Software, CBT', 'Educational tools, Computer Based Training', 0); +INSERT INTO appCategory VALUES (84, 'Action Games', 'Arcade and platform action games', 2); +INSERT INTO appCategory VALUES (86, 'Sports Games', 'Professional sports, car racing, and more.', 2); +INSERT INTO appCategory VALUES (88, 'Simulation Games', 'Flight and other real life simulators.', 2); +INSERT INTO appCategory VALUES (90, 'Remote Access', 'SSH, Telnet, VNC, Terminal Services, ...', 5); +INSERT INTO appCategory VALUES (92, 'Desktop Publishing', 'Various page layout, print, and publishing applications.', 4); +INSERT INTO appCategory VALUES (95, 'Graphics demos', '', 3); +INSERT INTO appCategory VALUES (97, 'Game Tools', 'Misc. tools related to games.', 2); +INSERT INTO appCategory VALUES (99, 'Astronomy', 'An endless (almost) empty space... ;-)', 8); +INSERT INTO appCategory VALUES (101, 'Screensavers', 'Run via \\"wine -- ssaver.scr /s\\" to setup', 3); +INSERT INTO appCategory VALUES (103, 'Online (MMORPG) Games', 'Massively Multiplayer Online Role Playing Games.', 2); +INSERT INTO appCategory VALUES (105, 'Special Purpose', 'Very special programs that whole businesses might rely on', 0); +INSERT INTO appCategory VALUES (107, 'Legal/law', '', 4); +INSERT INTO appCategory VALUES (110, 'Biology', 'All kinds of natural things.', 8); +INSERT INTO appCategory VALUES (112, 'Fun stuff', '', 2); +INSERT INTO appCategory VALUES (116, 'Chemistry', 'All kinds of application used for chemistry in science.', 8); +INSERT INTO appCategory VALUES (123, 'Installers', 'Program installers like installshield, windows installer etc.', 0); +INSERT INTO appCategory VALUES (124, 'Electronics design', '', 0); +INSERT INTO appCategory VALUES (125, 'Religious', 'Bible research software, tours of the holy land...', 0); diff --git a/tables/appdb_tables.sql b/tables/appdb_tables.sql new file mode 100644 index 0000000..701fb62 --- /dev/null +++ b/tables/appdb_tables.sql @@ -0,0 +1,176 @@ +create database if not exists apidb; + +use apidb; + +drop table if exists vendor; +drop table if exists appFamily; +drop table if exists appVersion; +drop table if exists appCategory; +drop table if exists appHitStats; +drop table if exists catHitStats; +drop table if exists appComments; +drop table if exists appData; +drop table if exists appBundle; +drop table if exists appVotes; +drop table if exists appNotes; + + +/* + * vendor information + */ +create table vendor ( + vendorId int not null auto_increment, + vendorName varchar(100) not null, + vendorURL varchar(200), + state enum('accepted','queued','deleted') NOT NULL default 'accepted', + key(vendorId) +); + + +/* + * application + */ +create table appFamily ( + appId int not null auto_increment, + appName varchar(100) not null, + vendorId int not null, + keywords text, + description text, + webPage varchar(100), + catId int, + submitTime datetime NOT NULL, + submitterId int(11) NOT NULL default '0', + state enum('accepted','queued','rejected','deleted') NOT NULL default 'accepted', + key(appId) +); + +/* + * a version of an application + */ +create table appVersion ( + versionId int not null auto_increment, + appId int not null, + versionName varchar(100) not null, + description text, + rating text, + ratingRelease text, + submitTime datetime NOT NULL, + submitterId int(11) NOT NULL default '0', + license enum('Retail','Open Source','Demo','Shareware','Free to use','Free to use and share'), + obsoleteBy int(11) NOT NULL default '0', + state enum('accepted','queued','rejected','pending','deleted') NOT NULL default 'accepted', + key(versionId), + index(appId) +); + + +/* + * application category + */ +create table appCategory ( + catId int not null auto_increment, + catName varchar(64) not null, + catDescription text, + catParent int default 0, + key(catId) +); + + +/* + * bundleId is the appId of the 'owner app' + */ +create table appBundle ( + bundleId int not null, + appId int not null, + key(bundleId), + index(appId) +); + + +/* + * appHitStats and catHitStats are to record statistics + */ +create table appHitStats ( + appHitId int not null auto_increment, + time datetime, + ip varchar(16), + appId int not null, + count int, + key(appHitId) +); + +create table catHitStats ( + catHitId int not null auto_increment, + time datetime, + ip varchar(16), + catId int not null, + count int, + key(catHitId) +); + + +/* + * user comments + */ +create table appComments ( + time datetime, + commentId int not null auto_increment, + parentId int default 0, + versionId int not null, + userId int, + hostname varchar(80), + subject varchar(128), + body text, + key(commentId), + index(versionId) +); + + + +/* + * links to screenshots and other stuff + */ +create table appData ( + id int not null auto_increment, + appId int not null, + versionId int default 0, + type enum('screenshot', 'url', 'bug','downloadurl'), + description text, + url varchar(255) default NULL, + submitTime datetime NOT NULL, + submitterId int(11) NOT NULL default '0', + state enum('accepted','queued','rejected') NOT NULL default 'accepted', + KEY id (id), + KEY versionId (versionId) +); + +/* + * allow users to vote for apps, as in, request that an app gets better support + */ +create table appVotes ( + id int not null auto_increment, + time datetime, + versionId int not null, + userId int not null, + slot int not null, + key(id), + index(versionId), + index(userId) +); + + +/* + * application notes + */ +create table appNotes ( + noteId int not null auto_increment, + noteTitle varchar(255), + noteDesc text, + versionId int not null, + appId int not null, + submitterId int not null, + submitTime datetime not null, + linkedWith int not null + key(noteId) +); + diff --git a/tables/banner.sql b/tables/banner.sql new file mode 100644 index 0000000..1089909 --- /dev/null +++ b/tables/banner.sql @@ -0,0 +1,12 @@ +CREATE TABLE banner ( + id int not null, + desc text, + img varchar(255), + url varchar(255), + alt varchar(255), + imp int not null, + clk int not null, + lastmod datetime, + + primary key(id) +) diff --git a/tables/buglinks.sql b/tables/buglinks.sql new file mode 100644 index 0000000..f32ecc0 --- /dev/null +++ b/tables/buglinks.sql @@ -0,0 +1,18 @@ +use apidb; + +drop table if exists buglinks; + +/* + * link a bug to a version of an application + */ +create table buglinks ( + linkId int not null auto_increment, + bug_id int not null, + versionId int not null, + submitTime datetime NOT NULL, + submitterId int(11) NOT NULL default '0', + state enum('accepted','queued') NOT NULL default 'accepted', + key(linkId), + index(bug_id), + index(versionId) +); diff --git a/tables/bugzilla_tables.sql b/tables/bugzilla_tables.sql new file mode 100644 index 0000000..3fb4df6 --- /dev/null +++ b/tables/bugzilla_tables.sql @@ -0,0 +1,219 @@ +create database if not exists bugs; + +use bugs; + +/* make sure the wineowner user has access to the bugs database */ +grant all on bugs.* to 'qemu'@'localhost'; +drop table if exists versions; + + +/* + * versions information + */ + +CREATE TABLE `versions` ( + `value` varchar(64) NOT NULL default '', + `product_id` smallint(6) NOT NULL default '0', + `id` mediumint(9) NOT NULL auto_increment, + PRIMARY KEY (`id`), + UNIQUE KEY `versions_product_id_idx` (`product_id`,`value`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=1; + +-- +-- Dumping data for table `versions` +-- + +INSERT INTO `versions` VALUES ('unspecified',1,1); +INSERT INTO `versions` VALUES ('CVS',1,2); +INSERT INTO `versions` VALUES ('unspecified',2,3); +INSERT INTO `versions` VALUES ('unspecified',3,4); +INSERT INTO `versions` VALUES ('unspecified',4,5); +INSERT INTO `versions` VALUES ('20010305',1,6); +INSERT INTO `versions` VALUES ('20010216',1,7); +INSERT INTO `versions` VALUES ('20010112',1,8); +INSERT INTO `versions` VALUES ('20010326',1,9); +INSERT INTO `versions` VALUES ('2.11',3,10); +INSERT INTO `versions` VALUES ('20010418',1,11); +INSERT INTO `versions` VALUES ('20020509',1,12); +INSERT INTO `versions` VALUES ('20010510',1,13); +INSERT INTO `versions` VALUES ('20010629',1,14); +INSERT INTO `versions` VALUES ('20010824',1,15); +INSERT INTO `versions` VALUES ('20011004',1,16); +INSERT INTO `versions` VALUES ('20011108',1,17); +INSERT INTO `versions` VALUES ('20020228',1,18); +INSERT INTO `versions` VALUES ('20020310',1,19); +INSERT INTO `versions` VALUES ('20020411',1,20); +INSERT INTO `versions` VALUES ('2.14.2',3,21); +INSERT INTO `versions` VALUES ('20020605',1,22); +INSERT INTO `versions` VALUES ('20020710',1,23); +INSERT INTO `versions` VALUES ('20020804',1,24); +INSERT INTO `versions` VALUES ('20020904',1,25); +INSERT INTO `versions` VALUES ('20021007',1,26); +INSERT INTO `versions` VALUES ('20021031',1,27); +INSERT INTO `versions` VALUES ('20021125',1,28); +INSERT INTO `versions` VALUES ('20021219',1,29); +INSERT INTO `versions` VALUES ('20030115',1,30); +INSERT INTO `versions` VALUES ('20030219',1,31); +INSERT INTO `versions` VALUES ('20030318',1,32); +INSERT INTO `versions` VALUES ('20030408',1,33); +INSERT INTO `versions` VALUES ('20030508',1,34); +INSERT INTO `versions` VALUES ('20030618',1,35); +INSERT INTO `versions` VALUES ('20030709',1,36); +INSERT INTO `versions` VALUES ('20030813',1,37); +INSERT INTO `versions` VALUES ('20030911',1,38); +INSERT INTO `versions` VALUES ('20031016',1,39); +INSERT INTO `versions` VALUES ('20031118',1,40); +INSERT INTO `versions` VALUES ('20031212',1,41); +INSERT INTO `versions` VALUES ('20040121',1,42); +INSERT INTO `versions` VALUES ('20040213',1,43); +INSERT INTO `versions` VALUES ('20040309',1,44); +INSERT INTO `versions` VALUES ('20040408',1,45); +INSERT INTO `versions` VALUES ('20040505',1,46); +INSERT INTO `versions` VALUES ('20040615',1,47); +INSERT INTO `versions` VALUES ('20040716',1,48); +INSERT INTO `versions` VALUES ('20040813',1,49); +INSERT INTO `versions` VALUES ('20040914',1,50); +INSERT INTO `versions` VALUES ('20041019',1,51); +INSERT INTO `versions` VALUES ('20041201',1,52); +INSERT INTO `versions` VALUES ('20050111',1,53); +INSERT INTO `versions` VALUES ('20050211',1,54); +INSERT INTO `versions` VALUES ('20050310',1,55); +INSERT INTO `versions` VALUES ('20050419',1,56); +INSERT INTO `versions` VALUES ('20050524',1,57); +INSERT INTO `versions` VALUES ('20050628',1,58); +INSERT INTO `versions` VALUES ('20050725',1,59); +INSERT INTO `versions` VALUES ('20050830',1,60); +INSERT INTO `versions` VALUES ('20050930',1,61); +INSERT INTO `versions` VALUES ('0.9',1,62); +INSERT INTO `versions` VALUES ('0.9.1.',1,63); +INSERT INTO `versions` VALUES ('0.9.2.',1,64); +INSERT INTO `versions` VALUES ('0.9.3.',1,65); +INSERT INTO `versions` VALUES ('0.9.4.',1,66); +INSERT INTO `versions` VALUES ('0.9.5.',1,67); +INSERT INTO `versions` VALUES ('0.9.6.',1,68); +INSERT INTO `versions` VALUES ('0.9.7.',1,69); +INSERT INTO `versions` VALUES ('0.9.8.',1,70); +INSERT INTO `versions` VALUES ('0.9.9.',1,71); +INSERT INTO `versions` VALUES ('0.9.10.',1,72); +INSERT INTO `versions` VALUES ('0.9.11.',1,73); +INSERT INTO `versions` VALUES ('0.9.12.',1,74); +INSERT INTO `versions` VALUES ('0.9.13.',1,75); +INSERT INTO `versions` VALUES ('0.9.14.',1,76); +INSERT INTO `versions` VALUES ('0.9.15.',1,77); +INSERT INTO `versions` VALUES ('0.9.16.',1,78); +INSERT INTO `versions` VALUES ('0.9.17.',1,79); +INSERT INTO `versions` VALUES ('0.9.18.',1,80); +INSERT INTO `versions` VALUES ('0.9.19.',1,81); +INSERT INTO `versions` VALUES ('0.9.20.',1,82); +INSERT INTO `versions` VALUES ('0.9.21.',1,83); +INSERT INTO `versions` VALUES ('0.9.22.',1,84); +INSERT INTO `versions` VALUES ('0.9.23.',1,85); +INSERT INTO `versions` VALUES ('0.9.24.',1,86); +INSERT INTO `versions` VALUES ('0.9.25.',1,87); +INSERT INTO `versions` VALUES ('0.9.26.',1,88); +INSERT INTO `versions` VALUES ('0.9.27.',1,89); +INSERT INTO `versions` VALUES ('0.9.28.',1,90); +INSERT INTO `versions` VALUES ('0.9.29.',1,91); +INSERT INTO `versions` VALUES ('0.9.30.',1,92); +INSERT INTO `versions` VALUES ('0.9.31.',1,93); +INSERT INTO `versions` VALUES ('0.9.32.',1,94); +INSERT INTO `versions` VALUES ('0.9.33.',1,95); +INSERT INTO `versions` VALUES ('0.9.34.',1,96); +INSERT INTO `versions` VALUES ('0.9.35.',1,97); +INSERT INTO `versions` VALUES ('0.9.36.',1,98); +INSERT INTO `versions` VALUES ('0.9.37.',1,99); +INSERT INTO `versions` VALUES ('0.9.38.',1,100); +INSERT INTO `versions` VALUES ('0.9.39.',1,101); +INSERT INTO `versions` VALUES ('0.9.40.',1,102); +INSERT INTO `versions` VALUES ('0.9.41.',1,103); +INSERT INTO `versions` VALUES ('0.9.42.',1,104); +INSERT INTO `versions` VALUES ('0.9.43.',1,105); +INSERT INTO `versions` VALUES ('0.9.44.',1,106); +INSERT INTO `versions` VALUES ('0.9.45.',1,107); +INSERT INTO `versions` VALUES ('0.9.46.',1,108); +INSERT INTO `versions` VALUES ('0.9.47.',1,109); +INSERT INTO `versions` VALUES ('0.9.48.',1,110); +INSERT INTO `versions` VALUES ('0.9.49.',1,111); +INSERT INTO `versions` VALUES ('0.9.50.',1,112); +INSERT INTO `versions` VALUES ('0.9.51.',1,113); +INSERT INTO `versions` VALUES ('0.9.52.',1,114); +INSERT INTO `versions` VALUES ('0.9.53.',1,115); +INSERT INTO `versions` VALUES ('0.9.54.',1,116); +INSERT INTO `versions` VALUES ('0.9.55.',1,117); +INSERT INTO `versions` VALUES ('0.9.56.',1,118); +INSERT INTO `versions` VALUES ('0.9.57.',1,119); +INSERT INTO `versions` VALUES ('0.9.58.',1,120); +INSERT INTO `versions` VALUES ('0.9.59.',1,121); +INSERT INTO `versions` VALUES ('0.9.60.',1,122); +INSERT INTO `versions` VALUES ('0.9.61.',1,123); +INSERT INTO `versions` VALUES ('1.0.rc1.',1,124); +INSERT INTO `versions` VALUES ('1.0.rc2.',1,125); +INSERT INTO `versions` VALUES ('1.0.rc3.',1,126); +INSERT INTO `versions` VALUES ('1.0.rc4.',1,127); +INSERT INTO `versions` VALUES ('1.0.rc5.',1,128); +INSERT INTO `versions` VALUES ('1.0.0.',1,129); +INSERT INTO `versions` VALUES ('1.1.0.',1,130); + +-- +-- Table structure for table `bugs` +-- + +DROP TABLE IF EXISTS `bugs`; +CREATE TABLE `bugs` ( + `bug_id` mediumint(9) NOT NULL auto_increment, + `assigned_to` mediumint(9) NOT NULL default '0', + `bug_file_loc` text, + `bug_severity` enum('blocker','critical','major','normal','minor','trivial','enhancement') +NOT NULL default 'blocker', + `bug_status` enum('UNCONFIRMED','NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED') +NOT NULL default 'UNCONFIRMED', + `creation_ts` datetime NOT NULL default '0000-00-00 00:00:00', + `delta_ts` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `short_desc` mediumtext, + `op_sys` enum('All','Windows 3.1','Windows 95','Windows 98','Windows ME','Windows +2000','Windows NT','Windows XP','Mac System 7','Mac System 7.5','Mac System 7.6.1','Mac System +8.0','Mac System 8.5','Mac System 8.6','Mac System 9.x','Mac OS X 10.0','Mac OS X 10.1','Mac OS +X +10.2','Linux','BSDI','FreeBSD','NetBSD','OpenBSD','AIX','BeOS','HP-UX','IRIX','Neutrino','OpenVMS','OS/2','OSF/1','Solaris','SunOS','other') +NOT NULL default 'All', + `priority` enum('P1','P2','P3','P4','P5') NOT NULL default 'P1', + `rep_platform` enum('All','DEC','HP','Macintosh','PC','PC-x86-64','SGI','Sun','Other') +default NULL, + `reporter` mediumint(9) NOT NULL default '0', + `version` varchar(64) NOT NULL default '', + `resolution` +enum('','FIXED','INVALID','WONTFIX','LATER','REMIND','DUPLICATE','WORKSFORME','MOVED','ABANDONED') +NOT NULL default '', + `target_milestone` varchar(20) NOT NULL default '---', + `qa_contact` mediumint(9) NOT NULL default '0', + `status_whiteboard` mediumtext NOT NULL, + `votes` mediumint(9) NOT NULL default '0', + `keywords` mediumtext NOT NULL, + `lastdiffed` datetime NOT NULL default '0000-00-00 00:00:00', + `everconfirmed` tinyint(4) NOT NULL default '0', + `environment` varchar(80) default NULL, + `reporter_accessible` tinyint(4) NOT NULL default '1', + `cclist_accessible` tinyint(4) NOT NULL default '1', + `estimated_time` decimal(5,2) NOT NULL default '0.00', + `remaining_time` decimal(5,2) NOT NULL default '0.00', + `alias` varchar(20) default NULL, + `product_id` smallint(6) NOT NULL default '0', + `component_id` smallint(6) NOT NULL default '0', + PRIMARY KEY (`bug_id`), + UNIQUE KEY `alias` (`alias`), + KEY `assigned_to` (`assigned_to`), + KEY `creation_ts` (`creation_ts`), + KEY `delta_ts` (`delta_ts`), + KEY `bug_severity` (`bug_severity`), + KEY `bug_status` (`bug_status`), + KEY `op_sys` (`op_sys`), + KEY `priority` (`priority`), + KEY `reporter` (`reporter`), + KEY `version` (`version`), + KEY `resolution` (`resolution`), + KEY `target_milestone` (`target_milestone`), + KEY `qa_contact` (`qa_contact`), + KEY `votes` (`votes`), + KEY `product_id` (`product_id`), + KEY `component_id` (`component_id`) +); diff --git a/tables/create_apidb_base.sql b/tables/create_apidb_base.sql new file mode 100644 index 0000000..dd33972 --- /dev/null +++ b/tables/create_apidb_base.sql @@ -0,0 +1,2 @@ +create database if not exists apidb; +grant all on apidb.* to 'wineowner'@'localhost'; diff --git a/tables/create_bugzilla_tables b/tables/create_bugzilla_tables new file mode 100755 index 0000000..3ea8a5a --- /dev/null +++ b/tables/create_bugzilla_tables @@ -0,0 +1,4 @@ +#! /bin/sh + +echo Creating fake Bugzilla tables +mysql -u root -p < bugzilla_tables.sql diff --git a/tables/create_tables b/tables/create_tables new file mode 100755 index 0000000..e7d53aa --- /dev/null +++ b/tables/create_tables @@ -0,0 +1,16 @@ +#! /bin/sh + +echo Create the base user +echo NOTE: It is ok for this to fail if the user already exists +echo there does not appear to be a way to create a user only +echo if they do not exist so we have to live with a potential +echo error after we try. +mysql -p -u root < create_user.sql + +echo Create the apidb database, and tables +cat create_apidb_base.sql appdb_tables.sql \ + prefs_list.sql user_list.sql user_prefs.sql \ + user_privs.sql app_category.sql \ + maintainers.sql buglinks.sql monitors.sql \ + error_log.sql distributions.sql testResults.sql \ + | mysql -p -u root diff --git a/tables/create_user.sql b/tables/create_user.sql new file mode 100644 index 0000000..5360c64 --- /dev/null +++ b/tables/create_user.sql @@ -0,0 +1,2 @@ +create user wineowner identified by 'lemonade'; + diff --git a/tables/distributions.sql b/tables/distributions.sql new file mode 100644 index 0000000..4118694 --- /dev/null +++ b/tables/distributions.sql @@ -0,0 +1,18 @@ +use apidb; + +drop table if exists distributions; + +/* + * Distributions table. + */ +create table distributions ( + distributionId int not null auto_increment, + name varchar(255) default NULL, + url varchar(255) default NULL, + submitTime datetime NOT NULL, + submitterId int(11) NOT NULL default '0', + state enum('accepted','queued','deleted') NOT NULL default 'accepted', + key(distributionId), + index(name) +); + diff --git a/tables/error_log.sql b/tables/error_log.sql new file mode 100644 index 0000000..22430d6 --- /dev/null +++ b/tables/error_log.sql @@ -0,0 +1,14 @@ +use apidb; + +drop table if exists error_log; + +create table error_log ( + id int not null auto_increment, + submitTime datetime, + userid int not null default '0', + type enum('sql_error', 'general_error'), + log_text text, + request_text text, + deleted bool, + key(id) +); \ No newline at end of file diff --git a/tables/maintainers.sql b/tables/maintainers.sql new file mode 100644 index 0000000..92e846b --- /dev/null +++ b/tables/maintainers.sql @@ -0,0 +1,26 @@ +use apidb; + +drop table if exists appMaintainerQueue; +drop table if exists appMaintainers; + +/* + * List of the application maintainers. These users have the rights + * to delete comments, edit the application description and otherwise + * care for an application. + * + * We also store the reason they asked to be a maintainer since we use this table + * for both queued and unqueued maintainers + */ +create table appMaintainers ( + maintainerId int not null auto_increment, + appId int, + versionId int, + userId int, + maintainReason text, + superMaintainer tinyint(1), + submitTime datetime, + state enum('accepted','queued','pending') NOT NULL default 'accepted', + notificationLevel int not null default '0', + notificationTime datetime, + key(maintainerId) +); diff --git a/tables/monitors.sql b/tables/monitors.sql new file mode 100644 index 0000000..048a6e1 --- /dev/null +++ b/tables/monitors.sql @@ -0,0 +1,18 @@ +use apidb; + +drop table if exists appMonitors; + +/* + * Let users monitor changes to applications + */ +create table appMonitors ( + monitorId int not null auto_increment, + appId int not null, + versionId int not null, + submitTime datetime NOT NULL, + userId int(11) NOT NULL default '0', + key(monitorId), + index(appid), + index(versionId), + index(userId) +); diff --git a/tables/prefs_list.sql b/tables/prefs_list.sql new file mode 100644 index 0000000..1952a03 --- /dev/null +++ b/tables/prefs_list.sql @@ -0,0 +1,25 @@ +use apidb; + +drop table if exists prefs_list; + +CREATE TABLE prefs_list ( + id int auto_increment not null, + name varchar(32), + def_value text, + value_list text, + description text, + + primary key(id) +); + +INSERT INTO prefs_list VALUES (0, 'debug', 'no', 'yes|no', 'Enable debugging information'); +INSERT INTO prefs_list VALUES (0, 'sidebar', 'left', 'left|right', 'Sidebar location'); +INSERT INTO prefs_list VALUES (0, 'window:query', 'no', 'yes|no', 'Display query results in a new window'); +INSERT INTO prefs_list VALUES (0, 'window:help', 'no', 'yes|no', 'Display help in a new window'); +INSERT INTO prefs_list VALUES (0, 'window:offsite', 'no', 'yes|no', 'Display offsite URLs in a new window'); +INSERT INTO prefs_list VALUES (0, 'confirm_comment_deletion', 'yes', 'yes|no', 'Ask why you are deleting a comment before deleting it'); +INSERT INTO prefs_list VALUES (0, 'query:mode', 'view', 'view|edit', 'Default API details mode'); +INSERT INTO prefs_list VALUES (0, 'query:hide_header', 'no', 'yes|no', 'Hide apidb header in query results'); +INSERT INTO prefs_list VALUES (0, 'query:hide_sidebar', 'no', 'yes|no', 'Hide apidb sidebar in query results'); +INSERT INTO prefs_list VALUES (0, 'send_email', 'yes', 'yes|no', 'Send email notifications'); +INSERT INTO prefs_list VALUES (0, 'htmleditor', 'for supported browsers', 'always|for supported browsers|never', 'Display a graphical HTML editor in certain text fields'); diff --git a/tables/testResults.sql b/tables/testResults.sql new file mode 100644 index 0000000..dd0d899 --- /dev/null +++ b/tables/testResults.sql @@ -0,0 +1,25 @@ +use apidb; + +drop table if exists testResults; + +/* + * Version Test results + */ +create table testResults ( + testingId int not null auto_increment, + versionId int not null, + whatWorks text, + whatDoesnt text, + whatNotTested text, + testedDate datetime not null, + distributionId int not null, + testedRelease tinytext, + installs enum('Yes','No','N/A') NOT NULL default 'Yes', + runs enum('Yes','No','Not Installable') NOT NULL default 'Yes', + testedRating enum('Platinum','Gold','Silver','Bronze','Garbage') NOT NULL, + comments text, + submitTime datetime NOT NULL, + submitterId int(11) NOT NULL default '0', + state enum('accepted','queued','rejected','pending','deleted') NOT NULL default 'accepted', + key(testingId) +); diff --git a/tables/user_list.sql b/tables/user_list.sql new file mode 100644 index 0000000..d7cb197 --- /dev/null +++ b/tables/user_list.sql @@ -0,0 +1,22 @@ +use apidb; + +drop table if exists user_list; + +create table user_list ( + stamp datetime not null, + userid int not null auto_increment, + password text not null, + realname text not null, + email varchar(255) not null, + created datetime not null, + inactivity_warn_stamp datetime not null, /* the time we warned the user */ + inactivity_warned enum('true','false') NOT NULL default 'false', /* if true, we warned the user */ + CVSrelease text, + unique key(userid), + unique(email) +); + +insert into user_list values (NOW(), 0, password('testing'), 'Administrator', + 'Admin@localhost', NOW(), NOW(), 'false' ,'' ); +update user_list set userid = 1000 where email = 'Admin@localhost'; + diff --git a/tables/user_prefs.sql b/tables/user_prefs.sql new file mode 100644 index 0000000..d3b1875 --- /dev/null +++ b/tables/user_prefs.sql @@ -0,0 +1,11 @@ +use apidb; + +drop table if exists user_prefs; + +CREATE TABLE user_prefs ( + userid int not null, + name varchar(64) not null, + value text, + key(userid), + key(name) +); diff --git a/tables/user_privs.sql b/tables/user_privs.sql new file mode 100644 index 0000000..a52fe8a --- /dev/null +++ b/tables/user_privs.sql @@ -0,0 +1,11 @@ +use apidb; + +drop table if exists user_privs; + +CREATE TABLE user_privs ( + userid int not null, + priv varchar(64) not null, + primary key(userid) +); + +insert into user_privs values (1000, 'admin'); diff --git a/unit_test/.htaccess b/unit_test/.htaccess new file mode 100644 index 0000000..4ba7518 --- /dev/null +++ b/unit_test/.htaccess @@ -0,0 +1,3 @@ +# default permissions +# prevent web access to this directory +deny from all diff --git a/unit_test/path.php b/unit_test/path.php new file mode 100644 index 0000000..4ae17f9 --- /dev/null +++ b/unit_test/path.php @@ -0,0 +1,3 @@ + diff --git a/unit_test/run_tests b/unit_test/run_tests new file mode 100755 index 0000000..145239b --- /dev/null +++ b/unit_test/run_tests @@ -0,0 +1 @@ +php -dmagic_quotes_gpc=0 -f run_tests.php diff --git a/unit_test/run_tests.php b/unit_test/run_tests.php new file mode 100644 index 0000000..7b59e8c --- /dev/null +++ b/unit_test/run_tests.php @@ -0,0 +1,180 @@ +IsEqual($oStartingTableCounts)) +{ + $bTestSuccess = false; + echo "\n\nStarting and ending table counts do not match\n"; + + $oStartingTableCounts->OutputSideBySide($oEndingTableCounts, + "Starting", + "Ending"); +} else +{ + echo "\n\nTable counts match from the start and end of the test suite.\n"; +} + +if($bTestSuccess == true) +{ + echo "\nAll tests were successful\n"; +} else +{ + echo "\nSome test(s) failed!\n"; +} + + + +// keep track of the counts of various tables +class table_counts +{ + // the tables we should count, set in the constructor + var $aTablesToCount; + + // the counts of the tables + var $aTableCounts; + + function table_counts() + { + $this->aTablesToCount = array('appBundle', + 'appCategory', + 'appComments', + 'appData', + 'appFamily', + 'appMaintainers', + 'appMonitors', + 'appNotes', + 'appVersion', + 'appVotes', + 'buglinks', + 'distributions', + 'prefs_list', + 'testResults', + 'user_list', + 'user_privs', + 'vendor'); + + $this->update_counts(); + } + + // update the count for each table + function update_counts() + { + $this->aTableCounts = array(); + + foreach($this->aTablesToCount as $sTable) + { + $sQuery = "select count(*) as cnt from ?;"; + $hResult = query_parameters($sQuery, $sTable); + $oRow = query_fetch_object($hResult); + + $this->aTableCounts[] = $oRow->cnt; + } + } + + // returns 'true' if equal, 'false' if not + function IsEqual($oTableCounts) + { + $iIndex = 0; + for($iIndex = 0; $iIndex < count($this->aTableCounts); $iIndex++) + { + if($this->aTableCounts[$iIndex] != $oTableCounts->aTableCounts[$iIndex]) + { + return false; + } + } + + return true; + } + + function OutputSideBySide($oTableCounts, $sFirstTableCountName, + $sSecondTableCountName) + { + $iIndex = 0; + + // output the header + printf("%20s%20s%20s\n", + "Table name", + $sFirstTableCountName, + $sSecondTableCountName); + + for($iIndex = 0; $iIndex < count($this->aTableCounts); $iIndex++) + { + printf("%20s%20s%20s", + $this->aTablesToCount[$iIndex], + $this->aTableCounts[$iIndex], + $oTableCounts->aTableCounts[$iIndex]); + if($this->aTableCounts[$iIndex] != $oTableCounts->aTableCounts[$iIndex]) + { + echo " <-- Mismatch"; + } + echo "\n"; + } + } + + function output() + { + $iIndex = 0; + for($iIndex = 0; $iIndex < count($this->aTableCounts); $iIndex++) + { + $sTableName = $this->aTablesToCount[$iIndex]; + $iTableCount = $this->aTableCounts[$iIndex]; + echo "$sTableName count of $iTableCount\n"; + } + } +} + + +?> diff --git a/unit_test/test_appData.php b/unit_test/test_appData.php new file mode 100644 index 0000000..335a642 --- /dev/null +++ b/unit_test/test_appData.php @@ -0,0 +1,66 @@ +sUrl = "http://www.microsoft.com/windowsmedia"; + $oDownloadUrl->sDescription = "Download Meida Player"; + $oDownloadUrl->iVersionId = 1; + + $oDownloadUrl->create(); + + $shReturn = appData::listSubmittedBy($oUser->iUserId, true); + + /* This is needed for deleting the entry */ + $oUser->addPriv("admin"); + + /* There should be two lines; one header and one for the downloadurl */ + $iExpected = 2; + $iReceived = substr_count($shReturn, ""); + if($iExpected != $iReceived) + { + error("Got $iReceived rows instead of $iExpected."); + $bSuccess = false; + } + + /* Clean up */ + if(!$oDownloadUrl->purge()) + { + $bSuccess = false; + error("Failed to delete oDownloadUrl!"); + } + + $oUser->delete(); + + return $bSuccess; +} + +if(!test_appData_listSubmittedBy()) +{ + echo "test_appData_listSubmittedBy() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_appData_listSubmittedBy() passed\n"; +} + +?> diff --git a/unit_test/test_application.php b/unit_test/test_application.php new file mode 100644 index 0000000..bf5dbe7 --- /dev/null +++ b/unit_test/test_application.php @@ -0,0 +1,248 @@ +iUserId, "admin"); + + $oApp = new Application(); + $oApp->sName = "Some application"; + $oApp->sDescription = "some description"; + $oApp->submitterId = $oUser->iUserId; + if(!$oApp->create()) + { + $oUser->delete(); /* clean up the user we created prior to exiting */ + error("Failed to create application!"); + return false; + } + + $iAppId = $oApp->iAppId; /* use the iAppId of the application we just created */ + + for($iVersionIdIndex = 0; $iVersionIdIndex < 10; $iVersionIdIndex++) + { + $oVersion = new Version(); + $oVersion->versionName = "Some Version".$iVersionIdIndex; + $oVersion->description = "Some Version description".$iVersionIdIndex; + $oVersion->iAppId = $oApp->iAppId; + + if(!$oVersion->create()) + { + delete_app_and_user($oApp, $oUser); + echo "Failed to create version!\n"; + return false; + } + } + + + delete_app_and_user($oApp, $oUser); + + $sQuery = "SELECT appId + FROM appVersion + WHERE appId = '?'"; + + if($hResult = query_parameters($sQuery, $iAppId)) + { + $iRows = query_num_rows($hResult); + if($iRows > 0) + { + echo "Found '".$iRows."' versions for this application left over!"; + return false; + } + } + + return true; + +} + + +function test_application_getWithRating() +{ + test_start(__FUNCTION__); + + $sTestEmail = "test_application_getwithrating@somesite.com"; + $sTestPassword = "password"; + + if(!$oUser = create_and_login_user($sTestEmail, $sTestPassword)) + return false; + + /* make this user an admin so we can create applications without having them queued */ + $hResult = query_parameters("INSERT into user_privs values ('?', '?')", + $oUser->iUserId, "admin"); + + $oApp = new Application(); + $oApp->sName = "Some application"; + $oApp->sDescription = "some description"; + $oApp->submitterId = $oUser->iUserId; + if(!$oApp->create()) + { + $oUser->delete(); + error("Failed to create application!"); + return false; + } + + $iAppId = $oApp->iAppId; /* use the iAppId of the application we just created */ + + + /* Create several versions of the new application to test uniqueness of getWithRating() results */ + + for($iVersionIdIndex = 0; $iVersionIdIndex < 10; $iVersionIdIndex++) + { + $oVersion = new Version(); + $oVersion->versionName = "Some Version".$iVersionIdIndex; + $oVersion->description = "Some Version description".$iVersionIdIndex; + $oVersion->iAppId = $oApp->iAppId; + + + /* Create Several Ratings, some duplicate */ + if ($iVersionIdIndex < 4) + { + $oVersion->sTestedRating = "Platinum"; + } + elseif ($iVersionIdIndex < 8) + { + $oVersion->sTestedRating = "Gold"; + } + else + { + $oVersion->sTestedRating = "Bronze"; + } + + if(!$oVersion->create()) + { + delete_app_and_user($oApp, $oUser); + error("Failed to create version!"); + return false; + } + } + + + $iItemsPerPage = 50; + $iOffset = 0; + $sRating = 'Bronze'; + $aApps = Application::getWithRating($sRating, $iOffset, $iItemsPerPage); + $aTest = array();//array to test the uniqueness our query results + while(list($i, $iId) = each($aApps)) //cycle through results returned by getWithRating + { + if ( in_array($iId, $aTest) ) //if the appId is already in our test results fail unique test + { + delete_app_and_user($oApp, $oUser); + error("getWithRating failed to return a unique result set"); + return false; + } + + array_push($aTest, $iId); //push the appId on to our test array + + } + + + delete_app_and_user($oApp, $oUser); + + + //test to ensure getWithRating doesn't return applications that are queued + + //create user without admin priveliges + if(!$oUser = create_and_login_user($sTestEmail, $sTestPassword)) + return false; + + + $oApp = new Application(); + $oApp->sName = "Some application"; + $oApp->sDescription = "some description"; + $oApp->submitterId = $oUser->iUserId; + if(!$oApp->create()) + { + $oUser->delete(); /* clean up the user we created prior to exiting */ + error("Failed to create application!"); + return false; + } + + $iAppId = $oApp->iAppId; /* use the iAppId of the application we just created */ + + $oVersion = new Version(); + $oVersion->versionName = "Some Version".$iVersionIdIndex; + $oVersion->description = "Some Version description".$iVersionIdIndex; + $oVersion->iAppId = $oApp->iAppId; + $oVersion->sTestedRating = "Bronze"; + $oVersion->objectSetState('queued'); + + if(!$oVersion->create()) + { + delete_app_and_user($oApp, $oUser); + error("Failed to create version!"); + return false; + } + + + $aApps=Application::getWithRating($sRating, $iOffset, $iItemsPerPage); + + if ( in_array($iAppId, $aApps )) //if the appId is in our test results fail queued test + { + delete_app_and_user($oApp, $oUser); + error("getWithRating failed to return a unique result set"); + return false; + } + + delete_app_and_user($oApp, $oUser); + + return true; +} + +function delete_app_and_user($oApp, $oUser) +{ + $bSuccess = true; + if(!$oApp->purge()) + { + echo __FUNCTION__."() oApp->purge() failed\n"; + $bSuccess = false; + } + + if(!$oUser->delete()) + { + echo __FUNCTION__."() oUser->delete() failed\n"; + $bSuccess = false; + } + + return $bSuccess; +} + +if(!test_application_delete()) +{ + echo "test_application_delete() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_application_delete() passed\n"; +} + + +if(!test_application_getWithRating()) +{ + echo "test_application_getWithRating() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_application_getWithRating() passed\n"; +} + +?> + diff --git a/unit_test/test_common.php b/unit_test/test_common.php new file mode 100644 index 0000000..5734687 --- /dev/null +++ b/unit_test/test_common.php @@ -0,0 +1,116 @@ +sName = "OM App ".$sId; + if(!$oApp->create()) + { + error("oApp->create() failed\n"); + } + + $oVersion = new version(); + $oVersion->sName = "OM version ".$sId; + $oVersion->iAppId = $oApp->iAppId; + if(!$oVersion->create()) + { + error("oVersion->create() failed"); + } + return $oVersion->iVersionId; +} + +// delete a version based on the $iVersionId parameter +// and delete its parent application +// NOTE: we enable admin permissions here to ensure that +// the application and version are deleted +function delete_version_and_parent_app($iVersionId) +{ + $bWasAdmin = $_SESSION['current']->hasPriv("admin"); + + $_SESSION['current']->addPriv("admin"); + + $oVersion = new version($iVersionId); + $oApp = new application($oVersion->iAppId); + if(!$oApp->purge()) + { + echo __FUNCTION__."() oApp->purge() failed, returned false!\n"; + } + + // remove the admin privileges only if the user didn't + // have them to begin with + if(!$bWasAdmin) + $_SESSION['current']->delPriv("admin"); +} + +function create_and_login_user($sTestEmail, $sTestPassword) +{ + $oUser = new User(); + + /* delete the user if they already exist */ + if($oUser->login($sTestEmail, $sTestPassword) == SUCCESS) + { + $oUser->delete(); + $oUser = new User(); + } + + // create the user + // NOTE: user::create() will call user::login() to login the user + // if the user creation is successful + $retval = $oUser->create($sTestEmail, $sTestPassword, "Test user", "20051020"); + if($retval != SUCCESS) + { + if($retval == USER_CREATE_EXISTS) + error("The user already exists!"); + else if($retval == USER_LOGIN_FAILED) + error("User login failed!"); + else + error("ERROR: UNKNOWN ERROR!!"); + + return false; + } + + return $oUser; +} + +function error($sMsg) +{ + $aBT = debug_backtrace(); + + // get class, function called by caller of caller of caller + if(isset($aBT[1]['class'])) + $sClass = $aBT[1]['class']; + else + $sClass = ""; + $sFunction = $aBT[1]['function']; + + // get file, line where call to caller of caller was made + $sFile = $aBT[0]['file']; + $sLine = $aBT[0]['line']; + + // build & return the message + echo "$sClass::$sFunction:$sFile:$sLine $sMsg\n"; +} + +function run_test($sTestName) +{ + if(!$sTestName()) + { + global $bTestSuccess; + echo "$sTestName() failed!\n"; + $bTestSuccess = false; + } else + { + echo "$sTestName() passed.\n"; + } +} + +?> diff --git a/unit_test/test_error_log.php b/unit_test/test_error_log.php new file mode 100644 index 0000000..f853e2f --- /dev/null +++ b/unit_test/test_error_log.php @@ -0,0 +1,46 @@ + diff --git a/unit_test/test_filter.php b/unit_test/test_filter.php new file mode 100644 index 0000000..a22d193 --- /dev/null +++ b/unit_test/test_filter.php @@ -0,0 +1,136 @@ +This is some html"; + $_REQUEST['shHtml'] = $shHtml; + + // filter the variables and make sure that we don't have a return value + // ie, that filtering succeeded + $sResult = filter_gpc(); + if($sResult) + { + error("sResult is '$sResult' but we expected success and no return value"); + return false; + } + + // expect that the filtered value will be equal + if($aClean['shHtml'] != $shHtml) + { + error("Expected aClean['shHtml'] to be '".$shHtml."' but instead it was '".$aClean['shHtml']."'"); + return false; + } + + + //***************************************************************************** + // test that filtering strings with html results in the tags being stripped out + $_REQUEST = array(); // clear out the array + $sHtml = "
    This is some html
    "; + $_REQUEST['sHtml'] = $sHtml; + + // filter the variables and make sure that we don't have a return value + // ie, that filtering succeeded + $sResult = filter_gpc(); + if($sResult) + { + error("sResult is '$sResult' but we expected success and no return value"); + return false; + } + + // expect that $aClean value has been modified during filtering so these + // shouldn't be equal unless something has failed + if($aClean['sHtml'] == $sHtml) + { + error("Expected aClean['shHtml'] to be '".$sHtml."' but instead it was '".$aClean['sHtml']."'"); + return false; + } + + // make sure all html has been stripped + if(strip_tags($aClean['sHtml']) != $aClean['sHtml']) + { + error("Expected all html to be stripped already but we were able to strip this '".$aClean['sHtml'] + ."' into '".strip_tags($aClean['sHtml'])."'"); + return false; + } + + return true; +} + + +/*************************/ +/* Main test routines */ + +if(!test_filter()) +{ + echo "test_filter() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_filter() passed\n"; +} + + +?> diff --git a/unit_test/test_image.php b/unit_test/test_image.php new file mode 100644 index 0000000..82c26ad --- /dev/null +++ b/unit_test/test_image.php @@ -0,0 +1,292 @@ +isLoaded()) + { + error("Error, unable to load image filename of ".$sImageFilename); + error("Internal filename is: ".$oImage->sFile); + return false; + } + + /* make sure the image size is correct */ + if($oImage->get_width() != TEST_IMAGE_WIDTH) + { + error("Expected width of ".TEST_IMAGE_WIDTH.", got ".$oImage->get_width()); + return false; + } + + if($oImage->get_height() != TEST_IMAGE_HEIGHT) + { + error("Expected width of ".TEST_IMAGE_HEIGHT.", got ".$oImage->get_height()); + return false; + } + + /* test that isLoaded() returns false if we create an */ + /* image object from a file that doesn't exist */ + $oImage = new Image("somefilethatdoesntexist.png"); + if($oImage->isLoaded()) + { + error("Error, isLoaded() returned true for a image that doesn't exist, expected false!"); + return false; + } + + return true; +} + +function test_image_make_thumbnail() +{ + test_start(__FUNCTION__); + + $sImageFilename = TEST_IMAGE_FILENAME; + + /* create a new image from a known image file */ + $oImage = new Image($sImageFilename); + + if(!$oImage->isLoaded()) + { + error("Error, unable to load image filename of ".$sImageFilename); + error("Internal filename is: ".$oImage->sFile); + return false; + } + + $iWidth = 100; + $iHeight = ($iWidth * TEST_IMAGE_HEIGHT) / TEST_IMAGE_WIDTH; /* compute the expected height + from the ratio of the height + to width of the original image */ + $iBorderWidth = 20; + $oImage->make_thumb($iWidth, $iHeight, $iBorderWidth, "#0000FF"); + + /* did we get the correct size? */ + $iActualWidth = $oImage->get_width(); + if($iActualWidth != $iWidth) + { + error("Expected width of $iWidth, got ".$iActualWidth); + error($oImage->get_debuglog(false)); + return false; + } + + $iActualHeight = $oImage->get_height(); + if($iActualHeight != $iHeight) + { + error("Expected height of $iHeight, got ".$iActualHeight); + error($oImage->get_debuglog(false)); + return false; + } + + return true; +} + +function test_image_make_full() +{ + test_start(__FUNCTION__); + + $sImageFilename = TEST_IMAGE_FILENAME; + + /* create a new image from a known image file */ + $oImage = new Image($sImageFilename); + + if(!$oImage->isLoaded()) + { + error("Error, unable to load image filename of ".$sImageFilename); + error("Internal filename is: ".$oImage->sFile); + return false; + } + + $iWidth = 1000; + $iHeight = ($iWidth * TEST_IMAGE_HEIGHT) / TEST_IMAGE_WIDTH; + $oImage->make_full($iWidth, $iHeight); + + /* we expect the width and height to be limited to the size of the image */ + $iWidth = TEST_IMAGE_WIDTH; + $iHeight = TEST_IMAGE_HEIGHT; + + /* did we get the correct size? */ + $iActualWidth = $oImage->get_width(); + if($iActualWidth != $iWidth) + { + error("Expected width of $iWidth, got ".$iActualWidth); + error($oImage->get_debuglog(false)); + return false; + } + + $iActualHeight = $oImage->get_height(); + if($iActualHeight != $iHeight) + { + error("Expected height of $iHeight, got ".$iActualHeight); + error($oImage->get_debuglog(false)); + return false; + } + + return true; +} + +function test_image_output_to_file() +{ + test_start(__FUNCTION__); + + $sImageFilename = TEST_IMAGE_FILENAME; + + /* create a new image from a known image file */ + $oImage = new Image($sImageFilename); + + if(!$oImage->isLoaded()) + { + error("Error, unable to load image filename of ".$sImageFilename); + error("Internal filename is: ".$oImage->sFile); + return false; + } + + /* write the file to disk */ + if(!$oImage->output_to_file(TEST_IMAGE_OUTPUT_FILENAME)) + { + error("image::output_to_file failed to output to filename of ".TEST_IMAGE_OUTPUT_FILENAME); + return false; + } + + /* check that we can load this file up */ + $oImage2 = new Image(TEST_IMAGE_OUTPUT_FILENAME, true); + if(!$oImage2->isLoaded()) + { + error("Error, unable to load newly output image filename of ".TEST_IMAGE_OUTPUT_FILENAME); + error("Internal filename is: ".$oImage2->sFile); + return false; + } + + /* and make sure we can now remove it */ + $oImage2->delete(); + + /* and check that it is unlinked by trying to open it up again */ + $oImage2 = new Image(TEST_IMAGE_OUTPUT_FILENAME, true); + if($oImage2->isLoaded()) + { + error("Error, unlinking filename of ".TEST_IMAGE_OUTPUT_FILENAME." failed, we are able to"); + error(" open up a file that should have been deleted."); + error("Internal filename is: ".$oImage2->sFile); + return false; + } + + return true; +} + +function test_image_add_watermark() +{ + test_start(__FUNCTION__); + + $sImageFilename = TEST_IMAGE_FILENAME; + + /* create a new image from a known image file */ + $oImage = new Image($sImageFilename); + + if(!$oImage->isLoaded()) + { + error("Error, unable to load image filename of ".$sImageFilename); + error("Internal filename is: ".$oImage->sFile); + return false; + } + + /* load the watermark up */ + $oWatermark = new Image(TEST_IMAGE_WATERMARK); + if(!$oWatermark->isLoaded()) + { + error("Error, unable to load image filename of ".TEST_IMAGE_WATERMARK); + error("Internal filename is: ".$oWatermark->sFile); + return false; + } + + $oImage->add_watermark($oWatermark->get_image_resource(), 50, 50); + + return true; +} + +function test_resize_image_border() +{ + test_start(__FUNCTION__); + $sBorderColor = '#00EEFF'; + $iBorderWidth = 1; + $iNewWidth = 3; + $iNewHeight = 3; + $sImageFilename = TEST_IMAGE_FILENAME; + + /* create a new image from a known image file */ + $oImage = new Image($sImageFilename); + + /* resize the image with a border */ + $oImage->resize_image_border($sBorderColor, $iBorderWidth, $iNewWidth, $iNewHeight); + + return true; +} + + +if(!test_image_constructor()) +{ + echo "test_image_constructor() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_image_constructor() passed\n"; +} + +if(!test_image_make_thumbnail()) +{ + echo "test_image_make_thumbnail() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_image_make_thumbnail() passed\n"; +} + +if(!test_image_make_full()) +{ + echo "test_image_make_full() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_image_make_full() passed\n"; +} + +if(!test_image_output_to_file()) +{ + echo "test_image_output_to_file() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_image_output_to_file() passed\n"; +} + +if(!test_image_add_watermark()) +{ + echo "test_image_add_watermark() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_image_add_watermark() passed\n"; +} + +if(!test_resize_image_border()) +{ + echo "test_resize_image_border() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_resize_image_border() passed\n"; +} +?> diff --git a/unit_test/test_maintainer.php b/unit_test/test_maintainer.php new file mode 100644 index 0000000..87a043d --- /dev/null +++ b/unit_test/test_maintainer.php @@ -0,0 +1,719 @@ +iAppId = $iAppId; + $oMaintainer->iVersionId = $iVersionId; + $oMaintainer->iUserId = $_SESSION['current']->iUserId; + $oMaintainer->sMaintainReason = "Some crazy reason"; + $oMaintainer->bSuperMaintainer = TRUE; + $oMaintainer->create(); + + /* and unqueue it to accept the user as a maintainer */ + $oMaintainer->unQueue("Some reply text"); + + /* see that the user is a super maintainer of the one application we added them to be */ + $iExpected = 1; /* we expect 1 super maintainer for this user */ + $iSuperMaintainerCount = Maintainer::getMaintainerCountForUser($oUser, TRUE); + if($iSuperMaintainerCount != $iExpected) + { + error("Got super maintainer count of '".$iSuperMaintainerCount."' instead of '".$iExpected."'"); + $oUser->delete(); + return false; + } + + /* maintainer count should be zero */ + $iExpected = 0; + $iMaintainerCount = Maintainer::getMaintainerCountForUser($oUser, FALSE); + if($iMaintainerCount != $iExpected) + { + error("Got maintainer count of '".$iMaintainerCount."' instead of '".$iExpected."'"); + $oUser->delete(); + return false; + } + + /* remove maintainership for this user */ + Maintainer::deleteMaintainer($oUser, $iAppId); + + /** + * make the user a maintainer + */ + + /* queue up this maintainer */ + $oMaintainer = new Maintainer(); + $oMaintainer->iAppId = $iAppId; + $oMaintainer->iVersionId = $iVersionId; + $oMaintainer->iUserId = $_SESSION['current']->iUserId; + $oMaintainer->sMaintainReason = "Some crazy reason"; + $oMaintainer->bSuperMaintainer = FALSE; + $oMaintainer->create(); + + /* and unqueue it to accept the user as a maintainer */ + $oMaintainer->unQueue("Some reply text"); + + /* see that the user is a super maintainer of no applications */ + $iExpected = 0; /* we expect 1 super maintainer for this user */ + $iSuperMaintainerCount = Maintainer::getMaintainerCountForUser($oUser, TRUE); + if($iSuperMaintainerCount != $iExpected) + { + error("Got super maintainer count of '".$iSuperMaintainerCount."' instead of '".$iExpected."'"); + $oUser->delete(); + return false; + } + + /* maintainer count should be one */ + $iExpected = 1; + $iMaintainerCount = Maintainer::getMaintainerCountForUser($oUser, FALSE); + if($iMaintainerCount != $iExpected) + { + error("Got maintainer count of '".$iMaintainerCount."' instead of '".$iExpected."'"); + $oUser->delete(); + return false; + } + + /* remove maintainership for this user */ + Maintainer::deleteMaintainer($oUser, $iAppId, $iVersionId); + + $oUser->delete(); + return true; +} + +// test that applications a user maintains are accurately reported by +// maintainer::GetAppsMaintained() +function test_maintainer_getAppsMaintained() +{ + test_start(__FUNCTION__); + + $sTestEmail = __FUNCTION__."@localhost.com"; + $sTestPassword = "password"; + if(!($oUser = create_and_login_user($sTestEmail, $sTestPassword))) + { + error("Failed to create and log in user!"); + return FALSE; + } + + /* make this user an admin so we can create applications without having them queued */ + $hResult = query_parameters("INSERT into user_privs values ('?', '?')", + $oUser->iUserId, "admin"); + + /* create a application so we have a valid appFamily for the call to user::getAppsMaintained() */ + $oApp = new Application(); + $oApp->sName = "Some application"; + $oApp->sDescription = "some description"; + $oApp->submitterId = $oUser->iUserId; + if(!$oApp->create()) + { + error("Failed to create application!"); + $oUser->delete(); + return false; + } + + /** + * make the user a super maintatiner + */ + $iAppId = $oApp->iAppId; /* use the iAppId of the application we just created */ + $iVersionId = 655200; + $bSuperMaintainer = TRUE; + + /* queue up the maintainership */ + // add to queue + $oMaintainer = new Maintainer(); + $oMaintainer->iAppId = $iAppId; + $oMaintainer->iVersionId = $iVersionId; + $oMaintainer->iUserId = $oUser->iUserId; + $oMaintainer->sMaintainReason = "Some crazy reason"; + $oMaintainer->bSuperMaintainer = $bSuperMaintainer; + $oMaintainer->create(); + + $statusMessage = $oMaintainer->unQueue("Some reply text"); /* accept the maintainership */ + + /* get an array of the apps maintained */ + $aAppsMaintained = maintainer::getAppsMaintained($oUser); + + if(!$aAppsMaintained) + { + error("aAppsMaintained is null, we expected a non-null return value!"); + $oUser->delete(); + return false; + } + + /* get only the first entry from the array of applications maintained */ + /* we only added the user as a maintainer of a single application */ + list($iAppId1, $iVersionId1, $bSuperMaintainer1) = $aAppsMaintained[0]; + + /* make sure all parameters match what we added as maintainer information */ + if($iAppId1 != $iAppId) + { + error("Expected iAppid of ".$iAppId." but got ".$iAppId1); + $oUser->delete(); + return false; + } + + if($iVersionId1 != $iVersionId) + { + error("Expected iVersionId of ".$iVersionId." but got ".$iVersionId1); + $oUser->delete(); + return false; + } + + if($bSuperMaintainer1 != $bSuperMaintainer) + { + error("Expected bSuperMaintainer of ".$bSuperMaintainer." but got ".$bSuperMaintainer1); + $oUser->delete(); + return false; + } + + /* remove maintainership for this user */ + Maintainer::deleteMaintainer($oUser, $iAppId); + + /* remove this application */ + $oApp = new Application($iAppId); + $oApp->purge(); + + $oUser->delete(); + + return true; +} + +// test that unQueueing a queued maintainer request twice is ignored +function test_maintainer_unQueue() +{ + test_start(__FUNCTION__); + + $sTestEmail = __FUNCTION__."@localhost.com"; + $sTestPassword = "password"; + if(!($oFirstUser = create_and_login_user($sTestEmail, $sTestPassword))) + { + error("Failed to create and log in first user!"); + return FALSE; + } + + // create a second user + $sTestEmail = __FUNCTION__."2nd@localhost.com"; + $sTestPassword = "password"; + if(!($oSecondUser = create_and_login_user($sTestEmail, $sTestPassword))) + { + error("Failed to create and log in second user!"); + $oFirstUser->delete(); + return FALSE; + } + + // make the first user the current user + // because create_and_login_user() calls user::login() + // and this sets $_SESSION['current'] so we need + // to override the create_and_login_user() for the second user + $_SESSION['current'] = $oFirstUser; + + + $iAppId = 655000; + $iVersionId = 655200; + + $oApp = new Application(); + $oVersion = new Version(); + $oApp->iAppId = $iAppId; + $oVersion->iVersionId = $iVersionId; + + /* Create a non-super maintainer for a different userId; it should not be affected + by the other user first becoming a maintainer and then a super maintainer of + the same application */ + $oSecondUserMaintainer = new Maintainer(); + $oSecondUserMaintainer->iAppId = $iAppId; + $oSecondUserMaintainer->iVersionId = $iVersionId; + $oSecondUserMaintainer->iUserId = $oSecondUser->iUserId; + $oSecondUserMaintainer->sMaintainReason = "I need it"; + $oSecondUserMaintainer->bSuperMaintainer = FALSE; + if(!$oSecondUserMaintainer->create()) + error("oSecondUserMaintainer->create() failed"); + + $oSecondUserMaintainer->unQueue(); + + /* Create a super maintainer for a different userId; it should not be affected + by the other user first becoming a maintainer and then a super maintainer of + the same application */ + $oSecondUserSuperMaintainer = new Maintainer(); + $oSecondUserSuperMaintainer->iAppId = $iAppId; + $oSecondUserSuperMaintainer->iVersionId = $iVersionId; + $oSecondUserSuperMaintainer->iUserId = $oSecondUser->iUserId; + $oSecondUserSuperMaintainer->sMaintainReason = "I need it"; + $oSecondUserSuperMaintainer->bSuperMaintainer = TRUE; + + // disable admin permissions around the creation of the second maintainer + // so the maintainer object remains queued + $oFirstUser->delPriv("admin"); + if(!$oSecondUserSuperMaintainer->create()) + error("oSecondUserSuperMaintainer->create() failed"); + $oFirstUser->addPriv("admin"); + + + /* Create a non-super maintainer + It should be removed later because a super maintainer entry for the same + application is added */ + $oFirstUserMaintainer = new Maintainer(); + $oFirstUserMaintainer->iAppId = $iAppId; + $oFirstUserMaintainer->iVersionId = $iVersionId; + $oFirstUserMaintainer->iUserId = $_SESSION['current']->iUserId; + $oFirstUserMaintainer->sMaintainReason = "The most stupid reason"; + $oFirstUserMaintainer->bSuperMaintainer = FALSE; + if(!$oFirstUserMaintainer->create()) + error("oFirstUserMaintainer->create() failed"); + + $sStatus = $oFirstUserMaintainer->unQueue(""); + + /* There should now be 1 maintainer and 0 super maintainers */ + $iExpected = 1; + $iReceived = maintainer::getMaintainerCountForUser($oFirstUser, FALSE); + if($iExpected != $iReceived) + { + error("Got maintainer count of $iReceived instead of $iExpected"); + error("sStatus is $sStatus"); + maintainer::deleteMaintainersForApplication($oApp); + maintainer::deleteMaintainersForVersion($oVersion); + $oFirstUser->delete(); + $oSecondUser->delete(); + return FALSE; + } + + $iExpected = 0; + $iReceived = maintainer::getMaintainerCountForUser($oFirstUser, TRUE); + if($iExpected != $iReceived) + { + error("Got super maintainer count of $iReceived instead of $iExpected"); + maintainer::deleteMaintainersForApplication($oApp); + maintainer::deleteMaintainersForVersion($oVersion); + $oFirstUser->delete(); + $oSecondUser->delete(); + return FALSE; + } + + /** + * make the user a super maintatiner + */ + /* queue up this maintainer */ + $oFirstUserSuperMaintainer = new Maintainer(); + $oFirstUserSuperMaintainer->iAppId = $iAppId; + $oFirstUserSuperMaintainer->iVersionId = $iVersionId; + $oFirstUserSuperMaintainer->iUserId = $_SESSION['current']->iUserId; + $oFirstUserSuperMaintainer->sMaintainReason = "Some crazy reason"; + $oFirstUserSuperMaintainer->bSuperMaintainer = TRUE; + if(!$oFirstUserSuperMaintainer->create()) + error("oFirstUserSuperMaintainer->create() failed"); + + /* and unqueue it to accept the user as a maintainer */ + $oFirstUserSuperMaintainer->unQueue("Some reply text"); + + /* unqueue it again to ensure that unQueueing a maintainer request twice works properly */ + $oFirstUserSuperMaintainer->unQueue("Some other reply text"); + + + /* see that the user is a super maintainer of the one application we added them to be */ + $iExpected = 1; /* we expect 1 super maintainer for this user */ + $iSuperMaintainerCount = maintainer::getMaintainerCountForUser($oFirstUser, TRUE); + if($iSuperMaintainerCount != $iExpected) + { + error("Got super maintainer count of '".$iSuperMaintainerCount. + "' instead of '".$iExpected."'"); + maintainer::deleteMaintainersForApplication($oApp); + maintainer::deleteMaintainersForVersion($oVersion); + $oFirstUser->delete(); + $oSecondUser->delete(); + return false; + } + + /* maintainer count should be zero, because unQueue should have removed the + previous non-super maintainer entry */ + $iExpected = 0; + $iMaintainerCount = maintainer::getMaintainerCountForUser($oFirstUser, FALSE); + if($iMaintainerCount != $iExpected) + { + error("Got maintainer count of '".$iMaintainerCount. + "' instead of '".$iExpected."'"); + maintainer::deleteMaintainersForApplication($oApp); + maintainer::deleteMaintainersForVersion($oVersion); + $oFirstUser->delete(); + $oSecondUser->delete(); + return false; + } + + /* Now the maintainer entry for the second user should still be present */ + $iExpected = 1; + $iReceived = maintainer::getMaintainerCountForUser($oSecondUser, FALSE); + if($iExpected != $iReceived) + { + error("Got maintainer count of $iReceived instead of $iExpected"); + maintainer::deleteMaintainersForApplication($oApp); + maintainer::deleteMaintainersForVersion($oVersion); + $oFirstUser->delete(); + $oSecondUser->delete(); + return FALSE; + } + + // Now the super maintainer request for the second user should still be present + $oSecondUserSuperMaintainer->unQueue(); + $iExpected = 1; + $iReceived = maintainer::getMaintainerCountForUser($oSecondUser, TRUE); + if($iExpected != $iReceived) + { + error("Got super maintainer count of $iReceived instead of $iExpected"); + maintainer::deleteMaintainersForApplication($oApp); + maintainer::deleteMaintainersForVersion($oVersion); + $oFirstUser->delete(); + $oSecondUser->delete(); + return FALSE; + } + + // Now that the super maintainer entry was unqueued, the maintainer + // entry should have been deleted + $iExpected = 0; + $iReceived = maintainer::getMaintainerCountForUser($oSecondUser, FALSE); + if($iExpected != $iReceived) + { + error("Got maintainer count of $iReceived instead of $iExpected"); + maintainer::deleteMaintainersForApplication($oApp); + maintainer::deleteMaintainersForVersion($oVersion); + $oFirstUser->delete(); + $oSecondUser->delete(); + return FALSE; + } + + /* remove maintainership for this user */ + maintainer::deleteMaintainersForApplication($oApp); + maintainer::deleteMaintainersForVersion($oVersion); + + $oFirstUser->delete(); + $oSecondUser->delete(); + + return true; +} + +/* Test whether a super maintainer request submitted along with an application is also accepted when the application is accepted */ +function test_superMaintainerOnAppSubmit() +{ + test_start(__FUNCTION__); + + $sTestEmail = __FUNCTION__."@localhost.com"; + $sTestPassword = "password"; + if(!($oUser = create_and_login_user($sTestEmail, $sTestPassword))) + { + error("Failed to create and log in user!"); + return FALSE; + } + + $iAppId = 655000; + $iVersionId = 655200; + + $oApp = new Application($iAppId); + + /* The user wants to be a super maintainer */ + $oApp->iMaintainerRequest = SUPERMAINTAINER_REQUEST; + + /* Make sure the user is not an admin, so the app will be queued */ + $oUser->delPriv("admin"); + + $oApp->create(); + + /* Make the user an admin so the app can be unqueued */ + $oUser->addPriv("admin"); + + $oApp->unQueue(); + + /* The user should now be a super maintainer */ + $iExpected = 1; + $iGot = Maintainer::getMaintainerCountForUser($oUser, TRUE); + + if($iGot != $iExpected) + { + error("Got maintainer count of '$iGot' instead of '$iExpected'"); + $oUser->delete(); + return false; + } + + Maintainer::deleteMaintainer($oUser, $iAppId); + + $oApp->purge(); + $oUser->delete(); + + return true; +} + +/* deleteMaintainersForVersion() should fail if versionId = 0 + Otherwise it will delete all super maintainers */ +function test_maintainer_deleteMaintainersForVersion() +{ + test_start(__FUNCTION__); + + $sTestEmail = __FUNCTION__."@localhost.com"; + $sTestPassword = "password"; + if(!($oUser = create_and_login_user($sTestEmail, $sTestPassword))) + { + error("Failed to create and log in user!"); + return FALSE; + } + + $oMaintainer = new maintainer(); + $oMaintainer->iAppId = 655000; + $oMaintainer->iVersionId = 0; + $oMaintainer->iUserId = 655000; + $oMaintainer->sMaintainReason = "Silly reason"; + $oMaintainer->bSuperMaintainer = 1; + + $oMaintainer->create(); + + $oVersion = new version(); + $oVersion->iVersionId = 0; + + if(maintainer::deleteMaintainersForVersion($oVersion) !== FALSE) + { + error("Got success, but this should fail."); + $oUser->delete(); + return FALSE; + } + + $oMaintainer->delete(); + $oUser->delete(); + + return TRUE; +} + +function test_maintainer_getMaintainersForAppIdVersionId() +{ + test_start(__FUNCTION__); + + $sTestEmail = __FUNCTION__."@localhost.com"; + $sTestPassword = "password"; + if(!($oUser = create_and_login_user($sTestEmail, $sTestPassword))) + { + error("Failed to create and log in user!"); + return FALSE; + } + + $oUser->addPriv("admin"); + + // assign the user with admin permissions as the current user + $_SESSION['current'] = $oUser; + + $oSecondUser = new user(); + $oSecondUser->iUserId = $oUser->iUserId + 1; + $oSecondUser->addPriv("admin"); + + $oApp = new application(); + $oApp->create(); + $oFirstVersion = new version(); + $oFirstVersion->sName = __FUNCTION__." first version"; + $oFirstVersion->iAppId = $oApp->iAppId; // $oApp is the parent + $oFirstVersion->create(); + $oSecondVersion = new version(); + $oSecondVersion->sName = __FUNCTION__." first version"; + $oSecondVersion->iAppId = $oApp->iAppId; // $oApp is the parent + $oSecondVersion->create(); + + $oSuperMaintainer = new maintainer(); + $oSuperMaintainer->bSuperMaintainer = TRUE; + $oSuperMaintainer->sMaintainReason = "Because"; + $oSuperMaintainer->iAppId = $oApp->iAppId; + $oSuperMaintainer->iUserId = $oUser->iUserId; + $oSuperMaintainer->create(); + + if(!$hResult = maintainer::getMaintainersForAppIdVersionId($oApp->iAppId)) + { + error("Failed to get list of maintainers!"); + $oUser->delete(); // delete the user + $oApp->purge(); // cleanup the application and its versions we created + return FALSE; + } + + /* The application should have one maintainer */ + $iExpected = 1; + $iReceived = query_num_rows($hResult); + if($iExpected != $iReceived) + { + error("Got super maintainer count of $iReceived instead of $iExpected!"); + $oUser->delete(); // delete the user + $oApp->purge(); // cleanup the application and its versions we created + return FALSE; + } + + if(!$hResult = maintainer::getMaintainersForAppIdVersionId(null, + $oFirstVersion->iVersionId)) + { + error("Failed to get list of maintainers!"); + $oUser->delete(); // delete the user + $oApp->purge(); // cleanup the application and its versions we created + return FALSE; + } + + /* The version should have one maintainer */ + $iExpected = 1; + $iReceived = query_num_rows($hResult); + if($iExpected != $iReceived) + { + error("Got maintainer count of $iReceived instead of $iExpected!"); + $oUser->delete(); // delete the user + return FALSE; + } + + $oSuperMaintainer->delete(); // cleanup the super maintainer we created + + /* Become a maintainer for one of the versions only */ + $oFirstVersionMaintainer = new maintainer(); + $oFirstVersionMaintainer->sMaintainReason = "I need it"; + $oFirstVersionMaintainer->iVersionId = $oFirstVersion->iVersionId; + $oFirstVersionMaintainer->iAppId = $oFirstVersion->iAppId; + $oFisrtVersionMaintainer->bSuperMaintainer = FALSE; + $oFirstVersionMaintainer->iUserId = $oUser->iUserId; + $oFirstVersionMaintainer->create(); + + /* Become a maintainer for the other version */ + $oSecondVersionMaintainer = new maintainer(); + $oSecondVersionMaintainer->sMaintainReason = "I need it"; + $oSecondVersionMaintainer->iVersionId = $oSecondVersion->iVersionId; + $oSecondVersionMaintainer->iAppId = $oFirstVersion->iAppId; + $oSecondVersionMaintainer->bSuperMaintainer = FALSE; + $oSecondVersionMaintainer->iUserId = $oSecondUser->iUserId; + $oSecondVersionMaintainer->create(); + + if(!$hResult = maintainer::getMaintainersForAppIdVersionId(null, + $oFirstVersion->iVersionId)) + { + error("Failed to get list of maintainers!"); + $oUser->delete(); // delete the user + $oApp->purge(); // cleanup the application and its versions we created + return FALSE; + } + + /* The first version should have one maintainer */ + $iExpected = 1; + $iReceived = query_num_rows($hResult); + if($iExpected != $iReceived) + { + error("Got maintainer count of $iReceived instead of $iExpected!"); + $oUser->delete(); // delete the user + $oApp->purge(); // cleanup the application and its versions we created + return FALSE; + } + + if(!$hResult = maintainer::getMaintainersForAppIdVersionId(null, + $oSecondVersion->iVersionId)) + { + error("Failed to get list of maintainers!"); + $oUser->delete(); // delete the user + $oApp->purge(); // cleanup the application and its versions we created + return FALSE; + } + + /* The second version should have 1 maintainer */ + $iExpected = 1; + $iReceived = query_num_rows($hResult); + if($iExpected != $iReceived) + { + error("Got maintainer count of $iReceived instead of $iExpected!"); + $oUser->delete(); // clean up the user + $oApp->purge(); // cleanup the application and its versions we created + return FALSE; + } + + if(!$oApp->purge()) + echo __FUNCTION__." oApp->purge() failed\n"; + + $oUser->delete(); // clean up the user + + return TRUE; +} + +if(!test_maintainer_getMaintainerCountForUser()) +{ + echo "test_maintainer_getMaintainerCountForUser() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_maintainer_getMaintainerCountForUser() passed\n"; +} + + +if(!test_maintainer_getAppsMaintained()) +{ + echo "test_maintainer_getAppsMaintained() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_maintainer_getAppsMaintained() passed\n"; +} + + +if(!test_maintainer_unQueue()) +{ + echo "test_maintainer_unQueue() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_maintainer_unQueue() passed\n"; +} + +if(!test_superMaintainerOnAppSubmit()) +{ + echo "test_superMaintainerOnAppSubmit() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_superMaintainerOnAppSubmit() passed\n"; +} + +if(!test_maintainer_deleteMaintainersForVersion()) +{ + echo "test_maintainer_deleteMaintainersForVersion() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_maintainer_deleteMaintianersForVersion() passed\n"; +} + +if(!test_maintainer_getMaintainersForAppIdVersionId()) +{ + echo "test_maintainer_getMaintainersForAppIdVersionId() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_maintainer_getMaintainersForAppIdVersionId() passed\n"; +} + +if(!test_maintainer_notifyMaintainersOfQueuedData()) +{ + echo "test_maintainer_notifyMaintainersOfQueuedData() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_maintainer_notifyMaintainersOfQueuedData() passed\n"; +} + +?> diff --git a/unit_test/test_maintainer_notify.php b/unit_test/test_maintainer_notify.php new file mode 100644 index 0000000..d7feabc --- /dev/null +++ b/unit_test/test_maintainer_notify.php @@ -0,0 +1,699 @@ +__internal_setupQueuedDataForUser($bTestAsMaintainer); + } + + function cleanup() + { + $this->oTestData->purge(); // deleted the created testData + $this->oMaintainer->delete(); // delete the created maintainer entry + // (Should be deleted when the user is deleted) + + // delete the version and its parent application that we created + delete_version_and_parent_app($this->iVersionId); + + // delete the user we created + $this->oUser->delete(); + } + + //FIXME: this should be private when we get php5 + function __internal_setupQueuedDataForUser($bTestAsMaintainer) + { + $bDebugOutputEnabled = false; + + $this->oUser = new User(); + $sUserEmail = "notifyMaintainerUser@somesite.com"; + $sUserPassword = "password"; + + // if we can login as the user, delete the user + if($this->oUser->login($sUserEmail, $sUserPassword) == SUCCESS) + { + // delete the user and create the new user object + $this->oUser->delete(); + $this->oUser = new User(); + } + + // create the user + $iRetval = $this->oUser->create("notifyMaintainerUser@somesite.com", + "password", "testuser1", "0.1.0"); + if($iRetval != SUCCESS) + { + echo "User creation failed, returned $iRetval\n"; + } + + // flag the testing user as the current user + $_SESSION['current'] = $this->oUser; + + // create a fake version + $this->iVersionId = create_version_and_parent_app("test_maintainer_notify"); + + // create a queued entry for the user we just created + $this->oTestData = new testData(); + $this->oTestData->iVersionId = $this->iVersionId; + $this->oTestData->shWhatWorks = "nothing"; + $this->oTestData->shWhatDoesnt = "nothing"; + $this->oTestData->shWhatNotTested = "nothing"; + $this->oTestData->sTestedDate = "20070404"; + $this->oTestData->sInstalls = "Yes"; + $this->oTestData->sRuns = "Yes"; + $this->oTestData->sTestedRating = "Gold"; + $this->oTestData->sComments = ""; + if(!$this->oTestData->create()) + { + echo "Failed to create testData\n"; + } + + // make this testData queued, we need to manually override this + // because the user created the application and version and + // because of this the user is allowed to submit unqueued test data + // for an unqueued version that they created + $this->oTestData->ReQueue(); + + // refresh the testdata object now that we've modified its queued status + $this->oTestData = new testData($this->oTestData->iTestingId); + + if($bDebugOutputEnabled) + { + echo "testData:\n"; + print_r($this->oTestData); + } + + // NOTE: we don't unqueue $oTestData because maintainer notification + // only applies to queued testData + + + $this->oVersion = new Version($this->iVersionId); + + // make the user a maintainer of the fake version or application + // depending on whether this user is a maintainer or super maintainer + $this->oMaintainer = new maintainer(); + $this->oMaintainer->iUserId = $this->oUser->iUserId; + $this->oMaintainer->iAppId = $this->oVersion->iAppId; + $this->oMaintainer->sMaintainReason = "for testing"; + if($bTestAsMaintainer) // create a version maintainer entry + { + $this->oMaintainer->bSuperMaintainer = false; + $this->oMaintainer->iVersionId = $this->iVersionId; + } else // create an application maintainer entry, a super maintainer entry + { + $this->oMaintainer->bSuperMaintainer = true; + $this->oMaintainer->iVersionId = 0; + } + + if(!$this->oMaintainer->create()) + { + echo "Failed to create maintainer!\n"; + } + + // notification code checks versions of a super maintainers application + // we must unqueue the version. if the version is queued + // we will only process this queued version during notification + // and will skip over queued entries that depend on this version + if(!$bTestAsMaintainer) + { + $sVersionUnqueue = "update appVersion set state='?' where versionId = '?'"; + $hResult = query_parameters($sVersionUnqueue, 'accepted', $this->iVersionId); + } + + // debug printing + if($bDebugOutputEnabled) + { + $sQuery2 = "select * from appMaintainers where maintainerId = '?'"; + $hResult = query_parameters($sQuery2, $this->oMaintainer->iMaintainerId); + $oObject = query_fetch_object($hResult); + print_r($oObject); + } + + // adjust the maintainer submitTime because the oldest entry is + // truncated at the time the user became a maintainer to prevent punishing + // them for signing up for an app that has had queued data for a long time + $iAdjustedTime = strtotime("now") - (100 * 24 * 60 * 60); // 100 days ago + $sQuery = "update appMaintainers set submitTime = '?' where maintainerId = '?'"; + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + query_parameters($sQuery, $sDate, $this->oMaintainer->iMaintainerId); + + if($bDebugOutputEnabled) + { + echo "iAdjustedTime for maintainer ".$iAdjustedTime."\n"; + echo "iMaintainerId: ".$this->oMaintainer->iMaintainerId."\n"; + } + + // update our maintainer object to get the new submit time + $this->oMaintainer = new Maintainer($this->oMaintainer->iMaintainerId); + + // echo "new maintainer class:\n"; + // print_r($this->oMaintainer); + } + + // adjust the submission time of the $oTestData object + // to make it appear as if it is $iAgeInSeconds old + function adjustTestDataSubmitTime($iAgeInSeconds) + { + // now adjust the submission time of this entry + // so it is older than iNotificationIntervalDays + // echo "strtotime('now') is ".strtotime("now")."\n"; + // echo "iAgeInSeconds is ".$iAgeInSeconds."\n"; + $iAdjustedTime = strtotime("now") - $iAgeInSeconds; + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update testResults set submitTime = '?' where testingId = '?'"; + query_parameters($sQuery, $sDate, $this->oTestData->iTestingId); + + // debug printing + // echo "iAdjustedTime is ".$iAdjustedTime."\n"; + // echo "Original date is: ".date('Y-m-d H:i:s', strtotime("now"))."\n"; + // echo "New date is ".$sDate."\n"; + } + + // returns true if the level is correct, false if not + function checkLevel($iExpectedLevel) + { + $bSuccess = true; + + // create a new maintainer so we can check its level, we COULD use + // the level of the existing $oMaintainer object but we want to + // check both to make sure that the $oMaintainer was updated + // AND that the database was updated + $oMaintainer2 = new maintainer($this->oMaintainer->iMaintainerId); + + // print_r($this->oMaintainer); + + if($this->oMaintainer->iNotificationLevel != $iExpectedLevel) + { + echo "oMaintainer expected iNotificationLevel of ".$iExpectedLevel. + ", actual level is ".$this->oMaintainer->iNotificationLevel."\n"; + $bSuccess = false; + } + + // echo "maintainer2\n"; + // print_r($oMaintainer2); + + if($oMaintainer2->iNotificationLevel != $iExpectedLevel) + { + echo "oMaintainer2 expected iNotificationLevel of ".$iExpectedLevel. + ", actual level is ".$oMaintainer2->iNotificationLevel."\n"; + $bSuccess = false; + } + + return $bSuccess; + } +} + + + +// test a user going from nothing(level 0) to level 1 +function test_maintainer_notifyLevel_0_to_1($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back a little bit + // to be in the level 1 range + $iSecondsOlder = ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(1); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test a user going from level 1 to level 2, so the queued time is +// >= (iNotificationIntervalDays * 2) +function test_maintainer_notifyLevel_1_to_2($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back two intervals + 1 day + // this should be in the level 2 range + $iSecondsOlder = (((iNotificationIntervalDays * 2) + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 1; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(2); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test user going from level 2 to 3, where the user will be deleted +function test_maintainer_notifyLevel_2_to_3($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back three intervals + 1 day + // this should be in the level 3 range + $iSecondsOlder = (((iNotificationIntervalDays * 3) + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 2 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', ". + "notificationTime = '?' where maintainerId = '?'"; + $iStartingLevel = 2; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + // check to make sure the maintainer doesn't exist + $sQuery = "select count(*) as cnt from appMaintainers where maintainerId = '?'"; + $hResult = query_parameters($sQuery, $oNotifyContainer->oMaintainer->iMaintainerId); + $oRow = query_fetch_object($hResult); + if($oRow->cnt != 0) + { + $bSuccess = false; + } + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + // test user going from level 2 to level 1 +function test_maintainer_notifyLevel_2_to_1($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back one interval + 1 day + // this should be in the level 1 range + $iSecondsOlder = ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 2 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 2; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(1); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test user going from level 1 to level 0 +function test_maintainer_notifyLevel_1_to_0($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // this is only a few seconds old + $iSecondsOlder = 60; + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 1; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(0); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test user going from level 2 to level 0 +function test_maintainer_notifyLevel_2_to_0($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // this is only a few seconds old + $iSecondsOlder = 60; + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 2; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(0); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test that a user that should go from level 1 to level 2 will not do so +// because the last update time is too soon +function test_maintainer_notifyLevel_1_to_2_delay($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back two intervals + 1 day + // this should be in the level 2 range + $iSecondsOlder = (((iNotificationIntervalDays * 2) + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // set the notification time as if we just notified this particular + // maintainer a few seconds ago + $iAdjustedTime = strtotime("now") - 60; + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 1; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(1); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test that a user with queued items not old enough to cause a transition +// from level 0 to 1 will remain at level 0 +function test_maintainer_notifyLevel_0_to_0($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back two intervals + 1 day + // this should be in the level 2 range + $iSecondsOlder = 60; + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // flag this maintainer as being notified at least a iNotificationIntervalDays + // ago so they should certainly be notified again + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 1; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(0); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test that a user with queued data that is really really old will +// only go from level 0 to level 1 +function test_maintainer_notifyLevel_0_to_1_with_old_queued_data($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back a little bit + // to be in the level 1 range + $iSecondsOlder = (((iNotificationIntervalDays * 5) + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(1); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +function test_maintainer_notifyLevel_starts_at_zero($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // see if our notification level is zero + if($oNotifyContainer->oMaintainer->iNotificationLevel != 0) + { + $bSuccess = false; + } + + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test maintainer::notifyMaintainerOfQueuedData() in various +// potential situations +// $bTestAsMaintainer == true - the user being tested is a normal maintainer +// $bTestAsMaintainer == false - the user being tested is a super maintainer +function _test_maintainer_notifyMaintainersOfQueuedData($bTestAsMaintainer) +{ + $bSuccess = true; // default to success + + test_start(__FUNCTION__); + + $sFunction = "test_maintainer_notifyLevel_0_to_1"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_1_to_2"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_2_to_3"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_2_to_1"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_1_to_0"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_2_to_0"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_1_to_2_delay"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_0_to_0"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_0_to_1_with_old_queued_data"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_starts_at_zero"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + return $bSuccess; +} + + +// test maintainer::notifyMaintainerOfQueuedData() in various +// potential situations +// NOTE: we test one as a normal maintainer and once as a super maintainer +function test_maintainer_notifyMaintainersOfQueuedData() +{ + $bSuccess = true; + + test_start(__FUNCTION__); + + echo "\nTesting as maintainer\n"; + if(!_test_maintainer_notifyMaintainersOfQueuedData(true)) + { + echo "Maintainer test failed!\n"; + $bSuccess = false; + } + + echo "\n\nTesting as super maintainer\n"; + if(!_test_maintainer_notifyMaintainersOfQueuedData(false)) + { + echo "Super maintainer test failed!\n"; + $bSuccess = false; + } + + return $bSuccess; +} +?> diff --git a/unit_test/test_om_objects.php b/unit_test/test_om_objects.php new file mode 100644 index 0000000..a1d7c23 --- /dev/null +++ b/unit_test/test_om_objects.php @@ -0,0 +1,399 @@ +checkMethods($aTestMethods, false)) + { + echo "FAILED\t\t".$oObject->getClass()." does not have valid methods for use with". + " the object manager\n"; + return false; + } + + /* Set up test user */ + $sTestEmail = __FUNCTION__."@localhost.com"; + $sTestPassword = "password"; + if(!$oUser = create_and_login_user($sTestEmail, $sTestPassword)) + { + error("Failed to create and log in user."); + return FALSE; + } else + { + // assign the session variable that makes this user the current user + $_SESSION['current'] = $oUser; + } + + /* Test the class constructor */ + if(!$oTestObject = create_object($sClassName, $oUser)) + return FALSE; + + /* Should return 1 or more, since there may be entries present already */ + $hResult = $oTestObject->objectGetEntries('accepted'); + + if(!$hResult) + { + error("Got '$hResult' instead of a valid query handle"); + error("FAILED\t\t$sClassName::$sClassName"); + $oTestObject->purge(); + return FALSE; + } + + if(!($oRow = query_fetch_object($hResult))) + { + error("Failed to fetch query object"); + error("FAILED\t\t$sClassName::$sClassName"); + $oTestObject->purge(); + return FALSE; + } + + $oNewTestObject = new $sClassName(null, $oRow); + $iReceived = $oNewTestObject->objectGetId(); + + if(!$iReceived || !is_numeric($iReceived)) + { + error("Got '$iReceived' instead of a valid id"); + error("FAILED\t\t$sClassName::$sClassName()"); + $oTestObject->purge(); + return FALSE; + } + + echo "PASSED\t\t$sClassName::$sClassName\n"; + + ////////////////////////// + // cleanup after the test + cleanup($oTestObject); + + if(!$oUser->addPriv("admin")) + error("oUser->addPriv('admin') failed"); + + if(!$oTestObject->purge()) + { + error("sClassName of '".$sClassName."' oTestObject->purge() failed!"); + $oUser->delete(); + return false; + } + + //////////////////////////////// + + /* Test the methods' functionality */ + foreach($aTestMethods as $sMethod) + { + switch($sMethod) + { + case 'objectGetEntries': + if(!$oTestObject = create_object($sClassName, $oUser)) + return FALSE; + + /* Should return 1 or more, since there may be entries present already */ + $iExpected = 1; + $hResult = $oTestObject->objectGetEntries('accepted'); + $iReceived = query_num_rows($hResult); + if($iExpected > $iReceived) + { + error("Got $iReceived instead of >= $iExpected"); + error("FAILED\t\t$sClassName::$sMethod"); + cleanup_and_purge($oTestObject, $oUser); + return FALSE; + } + + /* Create an object as a regular user */ + $oTestObject2 = create_object($sClassName, $oUser, false); + + /* objectGetEntries() and objectGetEntriesCount() should return matching results */ + $iExpected = mysql_num_rows($oTestObject2->objectGetEntries('accepted')); + $iReceived = $oTestObject2->objectGetEntriesCount('accepted'); + if($iExpected != $iReceived) + { + error("ObjectGetEntriesCount returned $iReceived, objectGetEntries fetched $iExpected rows\n"); + error("FAILED\t\t$sClassName::$sMethod"); + cleanup_and_purge($oTestObject, $oUser); + cleanup_and_purge($oTestObject2, $oUser); + return false; + } + + /* Now test for queued objects, as admin */ + $oUser->addPriv('admin'); + $iExpected = mysql_num_rows($oTestObject2->objectGetEntries('queued')); + $iReceived = $oTestObject2->objectGetEntriesCount('queued'); + $oUser->delPriv('admin'); + if($iExpected != $iReceived) + { + error("ObjectGetEntriesCount returned $iReceived, objectGetEntries fetched $iExpected rows\n"); + error("FAILED\t\t$sClassName::$sMethod"); + cleanup_and_purge($oTestObject, $oUser); + cleanup_and_purge($oTestObject2, $oUser); + return false; + } + + /* Class specific clean-up */ + cleanup_and_purge($oTestObject, $oUser); + cleanup_and_purge($oTestObject2, $oUser); + + echo "PASSED\t\t$sClassName::$sMethod\n"; + break; + case 'unQueue': + $bSuccess = true; + $oTestObject = create_object($sClassName, $oUser, false); + + $oUser->addPriv('admin'); + $oTestObject->unQueue(); + + $iReceived = $oTestObject->objectGetState(); + $iExpected = 'accepted'; + if($iReceived != $iExpected) + { + error("Got queue state of $iReceived instead of $iExpected\n"); + error("FAILED\t\t$sClassName::$sMethod"); + $bSuccess = false; + } + cleanup($oTestObject); + $oTestObject->purge(); + $oUser->delPriv('admin'); + + if(!$bSuccess) + return $bSuccess; + + echo "PASSED\t\t$sClassName::$sMethod\n"; + break; + } + } + + $oUser->delete(); + + echo "PASSED\t\t".$oObject->getClass()."\n"; + return TRUE; +} + +function cleanup($oObject) +{ + switch(get_class($oObject)) + { + case "bug": + // remove the bug row we created for the bug in create_object() + $sQuery = "delete from bugs where bug_id = '?'"; + $hResult = query_bugzilladb($sQuery, $oObject->iBug_id); + break; + case "downloadurl": + case "maintainer": + case "screenshot": + case "testData": + delete_version_and_parent_app($oObject->iVersionId); + break; + case "testData_queue": + delete_version_and_parent_app($oObject->oTestData->iVersionId); + break; + case "version": + $oApp = new application($oObject->iAppId); + $oApp->purge(); + break; + case "version_queue": + $oApp = new application($oObject->oVersion->iAppId); + $oApp->purge(); + break; + } +} + +function cleanup_and_purge($oObject, $oUser) +{ + $bWasAdmin = $oUser->hasPriv('admin'); + + $oUser->addPriv('admin'); + cleanup($oObject); + $oObject->purge(); + + switch(get_class($oObject)) + { + case 'application': + $oVendor = new vendor($oObject->iVendorId); + $oVendor->purge(); + break; + } + + if(!$bWasAdmin) + $oUser->delPriv('admin'); +} + +function create_object($sClassName, $oUser, $bAsAdmin = true) +{ + if($bAsAdmin) + $oUser->addPriv("admin"); + + $oTestObject = new $sClassName(); + /* Set up one test entry, depending on class */ + switch($sClassName) + { + // Some application functions require a vendor to be set + case 'application': + $oVendor = new vendor(); + $oVendor->create(); + $oTestObject->iVendorId = $oVendor->objectGetId(); + break; + + case "bug": + // create a bug in the bugzilla database, we need a valid + // bug id to create a bug entry + $sQuery = "insert into bugs (short_desc, bug_status, resolution)". + " values ('?', '?', '?')"; + $hResult = query_bugzilladb($sQuery, "test_om_objects", "VERIFIED", + ''); + + // retrieve the bug id and assign that to our + // bug class + $oTestObject->iBug_id = query_bugzilla_insert_id(); + break; + case "distribution": + $oTestObject->sName = "Silly test distribution"; + $oTestObject->sUrl = "http://appdb.winehq.org/"; + break; + case "downloadurl": + $oTestObject->sUrl = "http://appdb.winehq.org/"; + $oTestObject->sDescription = "DANGER"; + $oTestObject->iVersionId = create_version_and_parent_app("create_object_downloadurl"); + break; + case "maintainer": + /* We create the version as admin anyway to avoid the maintainer entry getting a state of 'pending' */ + if(!$bAsAdmin) + $oUser->addPriv('admin'); + + $iVersionId = create_version_and_parent_app("create_object_maintainer"); + + if(!$bAsAdmin) + $oUser->delPriv('admin'); + + $oVersion = new version($iVersionId); + $oTestObject->iUserId = $oUser->iUserId; + $oTestObject->iAppId = $oVersion->iAppId; + $oTestObject->iVersionId = $oVersion->iVersionId; + $oTestObject->sMaintainReason = "I need it"; + break; + case "screenshot": + case "testData": + $oTestObject->iVersionId = create_version_and_parent_app("create_object_testData"); + break; + case "testData_queue": + $oTestObject->oTestData->iVersionId = create_version_and_parent_app("create_object_testData_queue"); + break; + case "version": + $oApp = new application(); + $oApp->create(); + $oTestObject->iAppId = $oApp->iAppId; + $oTestObject->sName = "OM Version"; + break; + case "version_queue": + $oApp = new application(); + $oApp->create(); + $oTestObject->oVersion->iAppId = $oApp->iAppId; + $oTestObject->oVersion->sName = "OM Version"; + break; + case "vendor": + $oTestObject->sName = "OM vendor"; + break; + } + + /* We cannot use screenshot::create() because it requires an image */ + if($sClassName != "screenshot") + { + if(!$oTestObject->create()) + { + error("FAILED\t\t$sClassName::create()"); + return FALSE; + } + } else + { + $sQuery = "INSERT INTO appData + (versionId, type, description, state, submitterId) + VALUES('?','?','?','?','?')"; + $hResult = query_parameters($sQuery, $oTestObject->iVersionId, 'screenshot', '', 'accepted', + $oUser->iUserId); + if(!$hResult) + { + error("FAILED\t\t$sClassName to create screenshot entry"); + return FALSE; + } + $oTestObject->iScreenshotId = query_appdb_insert_id(); + } + + if($bAsAdmin) + $oUser->delPriv('admin'); + + return $oTestObject; +} + +function test_object_methods() +{ + test_start(__FUNCTION__); + + $aTestMethods = array("allowAnonymousSubmissions", + "canEdit", + "display", + "getOutputEditorValues", + "mustBeQueued", + "objectGetChildren", + "objectGetEntries", + 'objectGetEntriesCount', + "objectGetHeader", + "objectGetId", + "objectGetMail", + "objectGetMailOptions", + 'objectGetState', + "objectGetSubmitterId", + "objectGetTableRow", + "objectMakeLink", + "objectMakeUrl", + "outputEditor", + 'purge', + 'unQueue' + ); + + $aTestClasses = array("application", + "application_queue", + "bug", + "distribution", + "downloadurl", + "maintainer", + "monitor", + "note", + "screenshot", + "testData", + "testData_queue", + "vendor", + "version", + "version_queue" + ); + + foreach($aTestClasses as $sTestClass) + { + if(!test_class($sTestClass, $aTestMethods)) + return FALSE; + } + + return true; +} + +if(!test_object_methods()) +{ + echo "test_object_methods() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_object_methods() passed\n"; +} + +?> diff --git a/unit_test/test_query.php b/unit_test/test_query.php new file mode 100644 index 0000000..4ff08af --- /dev/null +++ b/unit_test/test_query.php @@ -0,0 +1,131 @@ +count; + + /* see that '~' strings are replaced with parameters */ + /* NOTE: if the second parameter is quoted this query will produce */ + /* a different number of results than if it was */ + /* NOTE: The second parameter is an example of a SQL injection attack */ + $sQuery = "SELECT count(*) as count from ~ where userid='~'"; + $hResult = query_parameters($sQuery, "user_list", "1' OR 1='1"); + if($hResult) + { + $oRow = query_fetch_object($hResult); + if($iUserCount != $oRow->count) + { + echo "sQuery of '".$sQuery."' returned ".$oRow->count." entries instead of the expected ".$iUserCount."\n"; + return false; + } + + if($iUserCount == 0) + { + echo "Because iUserCount is zero we can't know if this test passed or failed\n"; + } + } else + { + echo "sQuery of '".$sQuery."' failed but should have succeeded\n"; + return false; + } + + /** + * test that '&' in a query is properly replaced by the contents from a file + */ + /* write to a file that we will use for the test of '&' */ + $sFilename = "/tmp/test_query.txt"; + $hFile = fopen($sFilename, "wb"); + if($hFile) + { + fwrite($hFile, "user_list"); + fclose($hFile); + + $sQuery = "SELECT count(*) as count from &"; + $hResult = query_parameters($sQuery, $sFilename); + unlink($sFilename); /* delete the temporary file we've created */ + if(!$hResult) + { + echo "sQuery of '".$sQuery."' failed but should have succeeded\n"; + return false; + } + } else + { + echo "Could not open '".$sFilename."' for writing to complete the '&' test\n"; + } + + /** + * test that queries with slashes in them are parameterized properly + * NOTE: this test exists because query_parameters() at one point did not work + * properly with slashes in the query, they were incorrectly being recognized + * as tokens that should be replaced with parameters + */ + $sQuery = "SELECT count(*) as count, '".query_escape_string("\r\n")."' as x from ?"; + $hResult = query_parameters($sQuery, "user_list"); + if(!$hResult) + { + echo "sQuery of '".$sQuery."' failed but should have succeeded\n"; + return false; + } + + /* test that queries with too many parameters are rejected */ + $sQuery = "SELECT count(*) as count from ?"; + $hResult = query_parameters($sQuery, "user_list", "12"); + if($hResult) + { + echo "sQuery of '".$sQuery."' succeeded but should have failed for too many parameters\n"; + return false; + } + + /* test that queries with too few parameters are rejected */ + $sQuery = "SELECT count(*) as count from ?"; + $hResult = query_parameters($sQuery); + if($hResult) + { + echo "sQuery of '".$sQuery."' succeeded but should have failed for too few parameters\n"; + return false; + } + + return true; +} + + +if(!test_query_parameters()) +{ + echo "test_query_parameters() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_query_parameters() passed\n"; +} + + +?> diff --git a/unit_test/test_testData.php b/unit_test/test_testData.php new file mode 100644 index 0000000..f79f23a --- /dev/null +++ b/unit_test/test_testData.php @@ -0,0 +1,59 @@ +iVersionId = $iVersionId; + $oOldTestData->sTestedRelease = '0.9.50.'; + if(!$oOldTestData->create()) + error("oOldTestData->create() failed"); + + $oNewTestData = new testData(); + $oNewTestData->iVersionId = $iVersionId; + $oNewTestData->sTestedRelease = '0.9.51.'; + if(!$oNewTestData->create()) + error("oNewTestData->create() failed"); + + $oUser->addPriv("admin"); + $oOldTestData->unQueue(); + + /* Now the oldTestData should be listed as current, because the new one is queued */ + $iExpected = $oOldTestData->iTestingId; + $iReceived = testData::getNewestTestidFromVersionId($iVersionId); + if($iExpected != $iReceived) + { + error("Got testData id of $iReceived instead of $iExpected!"); + $oOldTestData->purge(); + $oNewTestData->purge(); + $oUser->delete(); + return FALSE; + } + + $oOldTestData->purge(); + $oNewTestData->purge(); + $oUser->delete(); + + return TRUE; +} + +if(!test_testData_getNewestTestidFromVersionId()) +{ + echo "test_testData_getNewestTestidFromVersionId() failed!\n"; + $bTestSuccess = false; +} else + echo "test_testData_getNewestTestidFromVersionId() passed\n"; +?> diff --git a/unit_test/test_url.php b/unit_test/test_url.php new file mode 100644 index 0000000..16b954f --- /dev/null +++ b/unit_test/test_url.php @@ -0,0 +1,77 @@ +addPriv("admin"); + + $oUrl = new Url(); + $oUrl->create("Bad description", "http://www.badurl.com/", $iVersionId, $iAppId, TRUE); + + $sDescriptionNew = "Good description"; + $sUrlNew = "http://www.goodurl.com/"; + $iAppIdNew = $iAppId + 1; + $iVersionIdNew = $iVersionId + 1; + + $oUrl->update($sDescriptionNew, $sUrlNew, $iVersionIdNew, $iAppIdNew, TRUE); + + if($oUrl->sDescription != $sDescriptionNew) + { + error("Description is '$oUrl->sDescription' instead of '$sDescriptionNew'"); + $bSuccess = false; + } + + if($oUrl->sUrl != $sUrlNew) + { + error("Url is '$oUrl->sUrl' instead of '$sUrlNew'"); + $bSuccess = false; + } + + if($oUrl->iVersionId != $iVersionIdNew) + { + error("VersionId is '$oUrl->iVersionId' instead of '$iVersionIdNew'"); + $bSuccess = false; + } + + if($oUrl->iAppId != $iAppIdNew) + { + error("AppId is '$oUrl->iAppId' instead of '$iAppIdNew'"); + $bSuccess = false; + } + + $oUrl->delete(TRUE); + $oUser->delete(); + + return $bSuccess; +} + +if(!test_url_update()) +{ + echo "test_url_update() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_url_update() passed\n"; +} + +?> diff --git a/unit_test/test_user.php b/unit_test/test_user.php new file mode 100644 index 0000000..5758b4c --- /dev/null +++ b/unit_test/test_user.php @@ -0,0 +1,343 @@ +create($test_email, $test_password, "Test user", "20051020"); + if($retval != USER_CREATE_EXISTS) + { + echo "Got '".$retval."' instead of USER_CREATE_EXISTS(".USER_CREATE_EXISTS.")\n"; + return false; + } + + return true; +} + +/* NOTE: relies on test_create_user() being run first and leaving a user */ +/* created in the db */ +function test_user_login() +{ + test_start(__FUNCTION__); + + global $test_email, $test_password; + + /* test that correct information results in a correct login */ + $oUser = new User(); + $retval = $oUser->login($test_email, $test_password); + if($retval != SUCCESS) + { + echo "Test that correct information results in a correct login FAILED\n"; + echo "Got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + /* test that incorrect user results in a login failed */ + $oUser = new User(); + $retval = $oUser->login("some nutty username", $test_password); + if($retval != USER_LOGIN_FAILED) + { + echo "Test that incorrect user results in a failed login FAILED\n"; + echo "Got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + /* test that incorrect password results in a login failed */ + $oUser = new User(); + $retval = $oUser->login($test_email, "some password"); + if($retval != USER_LOGIN_FAILED) + { + echo "Test that incorrect passowrd results in a login failed FAILED\n"; + echo "Got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + return true; +} + + +function test_user_update_set_test($realname, $winerelease) +{ + global $test_email, $test_password; + + /* log the user in */ + $oUser = new User(); + $retval = $oUser->login($test_email, $test_password); + if($retval != SUCCESS) + { + echo "Got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + /* modify the users realname and wine release */ + $oUser->sRealname = $realname; + $oUser->sWineRelease = $winerelease; + $oUser->update(); /* save the changes */ + + /* log the user in again */ + $oUser = new User(); + $retval = $oUser->login($test_email, $test_password); + if($retval != SUCCESS) + { + echo "Got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + /* make sure the realname and wine release match */ + if($oUser->sRealname != $realname) + { + echo "Realname of '".$oUser->sRealname."' doesn't match expected realname of '".$realname."'\n"; + return false; + } + + if($oUser->sWineRelease != $winerelease) + { + echo "Wine release of '".$oUser->sWineRelease."' doesn't match expected wine release of '".$winerelease."'\n"; + return false; + } + + return true; +} + +/* test that we can set values and call user::update() and have the values be saved */ +function test_user_update() +{ + test_start(__FUNCTION__); + + global $test_email, $test_password; + + if(!test_user_update_set_test("some bogus realname", "some crazy wine release")) + { + return false; + } + + if(!test_user_update_set_test("some new bogus realname", "some new crazy wine release")) + { + return false; + } + + return true; +} + +function test_user_delete() +{ + test_start(__FUNCTION__); + + global $test_email, $test_password; + + /* login the user */ + $oUser = new User(); + $retval = $oUser->login($test_email, $test_password); + if($retval != SUCCESS) + { + echo "Got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + /* delete the user */ + $oUser->delete(); + + /* try to log in again */ + $oUser = new User(); + $retval = $oUser->login($test_email, $test_password); + if($retval != USER_LOGIN_FAILED) + { + echo "Got '".$retval."' instead of USER_LOGIN_FAILED(".USER_LOGIN_FAILED.")\n"; + return false; + } + + + /* now create the user again and see that it is created successfully */ + + /* create the user */ + $oUser = new User(); + $retval = $oUser->create($test_email, $test_password, "Test user", "20051020"); + if($retval != SUCCESS) + { + if($retval == USER_CREATE_EXISTS) + echo "The user already exists!\n"; + else if($retval == USER_LOGIN_FAILED) + echo "User login failed!\n"; + else + echo "ERROR: UNKNOWN ERROR!!\n"; + + return false; + } + + return true; +} + +function test_user_getpref_setpref() +{ + test_start(__FUNCTION__); + + global $test_email, $test_password; + + /* login the user */ + $oUser = new User(); + $retval = $oUser->login($test_email, $test_password); + if($retval != SUCCESS) + { + echo "Got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + /* set a preference and retrieve it */ + $pref_key = "testpreference"; + $pref_value = "test value"; + $oUser->setPref($pref_key, $pref_value); + + $got_pref = $oUser->getPref($pref_key); + if($got_pref != $pref_value) + { + echo "Expected preference value of '".$pref_value."' got preference value of '".$got_pref."'\n"; + return false; + } + + return true; +} + +function test_user_update_password() +{ + test_start(__FUNCTION__); + + global $test_email, $test_password; + + /* login the user */ + $oUser = new User(); + $retval = $oUser->login($test_email, $test_password); + if($retval != SUCCESS) + { + echo "Got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + /* change the users password to something new */ + $sNewPassword = $test_password.$test_password; + if(!$oUser->update_password($sNewPassword)) + { + echo "user::update_password() failed to update password to '".$sNewPassword."'\n"; + return false; + } + + /* log the user in again, using the new password this time */ + $oUser = new User(); + $retval = $oUser->login($test_email, $sNewPassword); + if($retval != SUCCESS) + { + echo "Failed to login with new password, got '".$retval."' instead of SUCCESS(".SUCCESS.")\n"; + return false; + } + + /* change the password back to the original one */ + if(!$oUser->update_password($test_password)) + { + echo "user::update_password() failed, unable to restore password to .".$test_password."'\n"; + return false; + } + + return true; +} + +/*************************/ +/* Main test routines */ + +if(!test_user_create()) +{ + echo "test_user_create() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_user_create() passed\n"; +} + +if(!test_user_login()) +{ + echo "test_user_login() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_user_login() passed\n"; +} + +if(!test_user_update()) +{ + echo "test_user_update() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_user_update() passed\n"; +} + +if(!test_user_delete()) +{ + echo "test_user_delete() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_user_delete() passed\n"; +} + +if(!test_user_getpref_setpref()) +{ + echo "test_user_getpref_setpref() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_user_getpref_setpref() passed\n"; +} + +if(!test_user_update_password()) +{ + echo "test_user_update_password() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_user_update_password() passed\n"; +} + +// perform tests related to user password migration +include_once("test_user_password_migration.php"); + +/* Perform the maintainer tests here because they require that a user we can log into */ +/* and we want to save on having to clean up the user by duplicating the cleanup code below */ +include_once("test_maintainer.php"); + + +/* TODO: the rest of the user member functions we don't currently test */ + +/* clean up the user we created during the tests */ +/* so the unit test leaves no trace that it ran */ +$oUser = new User(); + +/* delete the user if they already exist */ +if($oUser->login($test_email, $test_password) == SUCCESS) +{ + $oUser->delete(); + $oUser = new User(); +} + +?> \ No newline at end of file diff --git a/unit_test/test_user_password_migration.php b/unit_test/test_user_password_migration.php new file mode 100644 index 0000000..78c1c3c --- /dev/null +++ b/unit_test/test_user_password_migration.php @@ -0,0 +1,85 @@ +password; + + // test that the user was created with the sha1 hash of their password + $sQuery = "select password from user_list where userid = '?';"; + $hResult = query_parameters($sQuery, $oUser->iUserId); + $oRow = query_fetch_object($hResult); + if($sTestUserPasswordSHA1 != $oRow->password) + { + error("sTestUserPasswordSHA1 $sTestUserPasswordSHA1 doesn't match oRow->password of $oRow->password after user::create()"); + $bSuccess = false; + } + + // build an array of the different types of password hashing + $aPasswordForm = array(); + $aPasswordForm[] = "old_password('?')"; + $aPasswordForm[] = "password('?')"; + $aPasswordForm[] = "sha1('?')"; + + foreach($aPasswordForm as $sPasswordForm) + { + // manually set the users password + $sQuery = "update user_list set password = ".$sPasswordForm." where userid = '?';"; + query_parameters($sQuery, $sTestPassword, $oUser->iUserId); + + // attempt to login + $retval = $oUser->login($sTestEmail, $sTestPassword); + if($retval != SUCCESS) + { + error("Failed to login when the user has an $sPasswordForm generated hash!"); + $bSuccess = false; + } + + // test that the users password has been updated to the SHA1 hash + // after the user was logged in + $sQuery = "select password from user_list where userid = '?';"; + $hResult = query_parameters($sQuery, $oUser->iUserId); + $oRow = query_fetch_object($hResult); + if($sTestUserPasswordSHA1 != $oRow->password) + { + error("sTestUserPasswordSHA1 $sTestUserPasswordSHA1 doesn't match oRow->password of $oRow->password"); + $bSuccess = false; + } + } + + // delete the user we created, we want the database to be left + // as it was before we ran our tests on it + $oUser->delete(); + + return $bSuccess; +} + + + +if(!test_user_password_migration()) +{ + echo "test_user_password_migration() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_user_password_migration() passed\n"; +} + +?> diff --git a/unit_test/test_voting.php b/unit_test/test_voting.php new file mode 100644 index 0000000..efbc64e --- /dev/null +++ b/unit_test/test_voting.php @@ -0,0 +1,85 @@ +getVotes()); + + if($iExpected != $iReceived) + { + echo "Expected voteManager::getVotes() to return $iExpected vote objects, got $iReceived.\n"; + return FALSE; + } + + return TRUE; +} + +/* Tests that the votes are saved to the database and that we cannot create more than MAX_VOTES. + Note that a user always has MAX_VOTES even though they're not in the DB, so we use update instead of create */ +function test_vote_update_delete() +{ + $iUserId = 655000; + + for($i = 0; $i < MAX_VOTES+1; $i++) + { + $oVote = new vote(); + $oVote->iUserId = $iUserId; + $oVote->iSlotIndex = $i+1; + + $oVote->update(); + } + + $oVoteManager = new voteManager($iUserId); + $aVotes = $oVoteManager->getVotes(); + + /* First test to see that the legit votes are saved */ + for($i = 0; $i < MAX_VOTES; $i++) + { + $iExpected = $i+1; + $iReceived = $aVotes[$i]->iSlotIndex; + if($iExpected != $iReceived) + { + echo "Expected slot index of $iExpected, got $iReceived instead.\n"; + return FALSE; + } + } + + /* There should only be MAX_VOTES number of votes */ + $iExpected = MAX_VOTES; + $iReceived = sizeof($aVotes); + if($iExpected != $iReceived) + { + echo "Expected $iExpected number of votes, got $iReceived.\n"; + return FALSE; + } + + /* Now the entries should be gone again */ + $oVoteManager->delete(); + $iExpected = 0; + $iReceived = 0; /* Incremented below */ + foreach($oVoteManager->getVotes() as $oVote) + { + if($oVote->iVoteId) + $iReceived++; + } + + if($iExpected != $iReceived) + { + echo "Expected $iExpected votes after deletion, got $iReceived\n"; + return FALSE; + } + + return TRUE; +} + +run_test("test_voteManager_getVotes"); +run_test("test_vote_update_delete"); + +?> \ No newline at end of file diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..8d95972 --- /dev/null +++ b/utils.js @@ -0,0 +1,23 @@ +/* + Misc JavaScipt for WineHQ +*/ + +// include a file from js scripts dir +function include_dom (script_filename) { + var html_doc = document.getElementsByTagName('head').item(0); + var js = document.createElement('script'); + js.setAttribute('language', 'javascript'); + js.setAttribute('type', 'text/javascript'); + js.setAttribute('src', script_filename); + html_doc.appendChild(js); + return false; +} + +// load and execute jquery IE6 PNG fix +include_dom("jquery.pngfix.js"); +jQuery(function($) { + $("img[@src$=png]").pngfix(); /* all img tags with .png extension */ + $("#tabs li").pngfix(); /* top tabs li backgrounds */ +}); + +// done diff --git a/viewbugs.php b/viewbugs.php new file mode 100644 index 0000000..517dd35 --- /dev/null +++ b/viewbugs.php @@ -0,0 +1,90 @@ +',"\n"; + + echo '',"\n"; + echo '',"\n"; + echo ' ',"\n"; + echo ' ',"\n"; + echo ' ',"\n"; + echo ' ',"\n"; + echo '',"\n"; + + + $hResult = query_parameters("SELECT appFamily.description as appDescription, + appFamily.appName as appName, + appVersion.*, buglinks.versionId as versionId + FROM appFamily, appVersion, buglinks + WHERE appFamily.appId = appVersion.appId + and buglinks.versionId = appVersion.versionId + AND buglinks.bug_id = '?' + ORDER BY versionName", $aClean['iBugId']); + $c = 0; + + if($hResult) + { + while($oRow = query_fetch_object($hResult)) + { + $oApp = new application($oRow->appId); + $oVersion = new version($oRow->versionId); + $sDownloadUrls = ""; + if($hDownloadUrls = appData::getData($oRow->versionId, "downloadurl")) + { + while($oDownloadUrl = query_fetch_object($hDownloadUrls)) + $sDownloadUrls .= "url\">". + "$oDownloadUrl->description
    "; + } + + // set row color + $bgcolor = ($c % 2 == 0) ? "color0" : "color1"; + echo '',"\n"; + echo ' ',"\n"; + echo ' ',"\n"; + echo ' ',"\n"; + echo " \n"; + echo '',"\n"; + } + } + + // allow users to search for other apps + echo '',"\n"; + echo ' ',"\n"; + echo '',"\n"; + + echo '',"\n"; + echo ' ',"\n"; + echo '',"\n"; + + echo '',"\n"; + echo ' ',"\n"; + echo ' ',"\n"; + echo '',"\n"; + + echo '
    Application NameDescriptionversionDownloads
    ',"\n"; + echo " ".$oApp->objectMakeLink()."\n"; + echo ' '.$oRow->appDescription.'',"\n"; + echo " ".$oVersion->objectMakeLink()."\n"; + echo ' $sDownloadUrls
     
      Bug #
    ',"\n"; + echo '
    ',"\n"; + apidb_footer(); + +?> diff --git a/votestats.php b/votestats.php new file mode 100644 index 0000000..58cb715 --- /dev/null +++ b/votestats.php @@ -0,0 +1,223 @@ + 200 || $aClean['iTopNumber'] < 0) + $aClean['iTopNumber'] = 25; +if(empty($aClean['iCategoryId'])) + $aClean['iCategoryId'] = 0; + +apidb_header("Vote Stats - Top ".$aClean['iTopNumber']." Applications"); + +echo "
    \n"; + +/* display the selection for the top number of apps to view */ +echo "
    "; +echo "Number of top apps to display:"; +echo ""; + +/** + * build an array of categories from the current category back up + * the tree to the main category + */ +$cat_array = Array(); +$cat_name_array = Array(); + +if(!empty($aClean['iCategoryId'])) +{ + $currentCatId = $aClean['iCategoryId']; + + do + { + $sCatQuery = "SELECT appCategory.catName, appCategory.catParent ". + "FROM appCategory WHERE appCategory.catId = '?'"; + $hResult = query_parameters($sCatQuery, $currentCatId); + + if($hResult) + { + $oRow = query_fetch_object($hResult); + $catParent = $oRow->catParent; + + array_push($cat_array, "$currentCatId"); + array_push($cat_name_array, "$oRow->catName"); + } + + $currentCatId = $catParent; + } while($currentCatId != 0); +} + +/*******************************************************************/ +/* add options for all of the categories that we are recursed into */ +echo "Section:"; +echo ''; +echo ''; +echo '
    '; +echo '
    '; +echo '
    '; + +/***************************************************/ +/* build a list of the apps in the chosen category */ +if(empty($aClean['iCategoryId'])) +{ + /* leave out the appFamily.catId = '$aClean['iCategoryId']' */ + $hResult = query_parameters("SELECT appVotes.versionId, versionName, appName, + count(userId) as count + FROM appVotes, appFamily, appVersion + WHERE appVotes.versionId = appVersion.versionId AND + appFamily.appId = appVersion.appId AND + appVersion.state = 'accepted' + GROUP BY appVotes.versionId ORDER BY count DESC LIMIT ?", + $aClean['iTopNumber']); +} else +{ + /* Display all application for a given category (including sub categories) + SELECT f.appId, f.appName + FROM appFamily AS f, appCategory AS c + WHERE f.catId = c.catId + AND ( + c.catId =29 + OR c.catParent =29)*/ + + $hResult = query_parameters("SELECT v.versionId, appVersion.versionName, + f.appName, count( v.versionId ) AS count + FROM appFamily AS f, appCategory AS c, appVotes AS v, appVersion + WHERE appVersion.appId = f.appId + AND appVersion.versionId = v.versionId + AND appVersion.state = 'accepted' + AND f.catId = c.catId + AND ( + c.catId = '?' + OR c.catParent = '?' + ) + GROUP BY v.versionId + ORDER BY count DESC LIMIT ?", + $aClean['iCategoryId'], $aClean['iCategoryId'], $aClean['iTopNumber']); +} + +if($hResult) +{ + echo html_frame_start("", "90%", '', 0); + + $oTable = new Table(); + $oTable->SetWidth("100%"); + $oTable->SetAlign("center"); + + $oTableRow = new TableRow(); + $oTableRow->SetClass("color4"); + $oTableRow->AddTextCell("Application Name"); + $oTableRow->AddTextCell("Votes"); + $oTable->AddRow($oTableRow); + + $c = 1; + while($oRow = query_fetch_object($hResult)) + { + $sColor = ($c % 2) ? "color0" : "color1"; + + $oTableRowHighlight = GetStandardRowHighlight($c); + + $shLink = version::fullNameLink($oRow->versionId); + + $oVersion = new Version($oRow->versionId); + + $oTableRowClick = new TableRowClick($oVersion->objectMakeUrl()); + $oTableRowClick->SetHighlight($oTableRowHighlight); + + $oTableRow = new TableRow(); + $oTableRow->SetRowClick($oTableRowClick); + $oTableRow->SetClass($sColor); + $oTableCell = new TableCell("$c.".$shLink); + $oTableCell->SetWidth("90%"); + $oTableRow->AddCell($oTableCell); + $oTableRow->AddTextCell($oRow->count); + + $oTable->AddRow($oTableRow); + + $c++; + } + + // output the table + echo $oTable->GetString(); + + echo html_frame_end(); + + /* Make sure we tell the user here are no apps, otherwise they might */ + /* think that something went wrong with the server */ + if($c == 1) + { + echo '

    No apps found in this category, please vote for your favorite apps!

    '; + } + + echo '

    What does this screen mean?

    '; +} + +echo "
    \n"; + +apidb_footer(); +?> diff --git a/xinha/Xinha.css b/xinha/Xinha.css new file mode 100644 index 0000000..d15a73f --- /dev/null +++ b/xinha/Xinha.css @@ -0,0 +1,263 @@ +.htmlarea { background: #fff; } +.htmlarea td { margin:0;padding:0; } + +.htmlarea .toolbar { + cursor: default; + background: ButtonFace; + padding: 3px; + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} +.htmlarea .toolbar table { margin: 0; font-family: tahoma,verdana,sans-serif; font-size: 11px; } +.htmlarea .toolbar img { border: none; vertical-align: top; } +.htmlarea .toolbar .label { padding: 0px 3px; } + +.htmlarea .toolbar .button { + background: ButtonFace; + color: ButtonText; + border: 1px solid ButtonFace; + padding: 1px; + margin: 0px; + width: 18px; + height: 18px; +} +.htmlarea .toolbar a.button:hover { + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} +.htmlarea .toolbar a.buttonDisabled:hover { + border-color: ButtonFace; +} +.htmlarea .toolbar .buttonActive, +.htmlarea .toolbar .buttonPressed +{ + padding: 2px 0px 0px 2px; + border: 1px solid; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; +} +.htmlarea .toolbar .buttonPressed { + background: ButtonHighlight; +} +.htmlarea .toolbar .indicator { + padding: 0px 3px; + overflow: hidden; + width: 20px; + text-align: center; + cursor: default; + border: 1px solid ButtonShadow; +} + +.htmlarea .toolbar .buttonDisabled img { + filter: gray() alpha(opacity = 25); + -moz-opacity: 0.25; + opacity: 0.25; +} + +.htmlarea .toolbar .separator { + /*position: relative;*/ + margin:0 3px; + border-left: 1px solid ButtonShadow; + border-right: 1px solid ButtonHighlight; + width: 0px; + height: 18px; + padding: 0px; +} + +.htmlarea .toolbar .space { width: 5px; } + +.htmlarea .toolbar select, .htmlarea .toolbar option { font: 11px Tahoma,Verdana,sans-serif;} + +.htmlarea .toolbar select, +.htmlarea .toolbar select:hover, +.htmlarea .toolbar select:active { + margin-top: 2px; + margin-bottom: 1px; + color: ButtonText; + height: 17px; +} + +.htmlarea iframe.xinha_iframe, .htmlarea textarea.xinha_textarea +{ + border: none; /*1px solid;*/ +} + +.htmlarea .statusBar { + border: 1px solid; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; + padding: 2px 4px; + background-color: ButtonFace; + color: ButtonText; + font: 11px Tahoma,Verdana,sans-serif; + height:16px; +} + +.htmlarea .statusBar .statusBarTree a { + padding: 2px 5px; + color: #00f; +} + +.htmlarea .statusBar .statusBarTree a:visited { color: #00f; } +.htmlarea .statusBar .statusBarTree a:hover { + background-color: Highlight; + color: HighlightText; + padding: 1px 4px; + border: 1px solid HighlightText; +} + + +/* popup dialogs */ + +.dialog { + color: ButtonText; + background: ButtonFace; +} + +.dialog .content { padding: 2px; } + +.dialog, .dialog button, .dialog input, .dialog select, .dialog textarea, .dialog table { + font: 11px Tahoma,Verdana,sans-serif; +} + +.dialog table { border-collapse: collapse; } + +.dialog .title, .dialog h1 +{ + background: #008; + color: #ff8; + border-bottom: 1px solid #000; + padding: 1px 0px 2px 5px; + font-size: 12px; + font-weight: bold; + cursor: default; +} +.dialog h1 { margin:0px;} +.dialog .title .button { + float: right; + border: 1px solid #66a; + padding: 0px 1px 0px 2px; + margin-right: 1px; + color: #fff; + text-align: center; +} + +.dialog .title .button-hilite { border-color: #88f; background: #44c; } + +.dialog button { + width: 5em; + padding: 0px; +} + +.dialog .buttonColor { + width :1em; + padding: 1px; + cursor: default; + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} + +.dialog .buttonColor .chooser, .dialog .buttonColor .nocolor { + height: 0.6em; + border: 1px solid; + padding: 0px 1em; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; +} + +.dialog .buttonClick { + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; +} +.dialog .buttonColor-hilite { + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; +} + +.dialog .buttonColor .nocolor { padding: 0px; } +.dialog .buttonColor .nocolor-hilite { background-color: #fff; color: #f00; } + +.dialog .label { text-align: right; width: 6em; } +.dialog .value input { width: 100%; } +.dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; } + +.dialog legend { font-weight: bold; } +.dialog fieldset table { margin: 2px 0px; } + +.popupwin { + padding: 0px; + margin: 0px; +} + +.popupwin .title { + background: #fff; + color: #000; + font-weight: bold; + font-size: 120%; + padding: 3px 10px; + margin-bottom: 10px; + border-bottom: 1px solid black; + letter-spacing: 2px; +} + +form { margin: 0px; border: none; } + + +/** Panels **/ +.htmlarea .panels.top +{ + border-bottom : 1px solid; + border-color: ButtonShadow; +} + +.htmlarea .panels.right +{ + border-left : 1px solid; + border-color: ButtonShadow; +} + +.htmlarea .panels.left +{ + border-right : 1px solid; + border-color: ButtonShadow; +} + +.htmlarea .panels.bottom +{ + border-top : 1px solid; + border-color: ButtonShadow; +} + +.htmlarea .panel h1 { + background: ButtonFace; + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; + margin: 0px; + padding: 0px; + font-size:100%; + font-weight:bold; + padding: 2px; + clear:left; + +} + +.htmlarea .panel { overflow:hidden; } +.htmlarea .panels.left .panel { border-right:none; border-left:none; } +.htmlarea .panels.left h1 { border-right:none; } +.htmlarea .panels.right .panel { border-right:none; border-left:none; } +.htmlarea .panels.left h1 { border-left:none; } +.htmlarea { border: 1px solid black; } + +.loading +{ + background-color:#666; + position:absolute; + z-index:998; +} +.loading_main +{ + font-size:1.6em; + color:#ff6; + text-align:center; +} +.loading_sub +{ + font-size:1.0em; + color:#fff; + text-align:center; +} diff --git a/xinha/XinhaCore.js b/xinha/XinhaCore.js new file mode 100644 index 0000000..85f179a --- /dev/null +++ b/xinha/XinhaCore.js @@ -0,0 +1,3668 @@ +Xinha.version={"Release":"0.931","Head":"http://svn.xinha.python-hosting.com/trunk/XinhaCore.js","Date":"2007-05-16","Revision":"819","RevisionBy":"ray"}; +Xinha._resolveRelativeUrl=function(_1,_2){ +if(_2.match(/^([^:]+\:)?\//)){ +return _2; +}else{ +var b=_1.split("/"); +if(b[b.length-1]==""){ +b.pop(); +} +var p=_2.split("/"); +if(p[0]=="."){ +p.shift(); +} +while(p[0]==".."){ +b.pop(); +p.shift(); +} +return b.join("/")+"/"+p.join("/"); +} +}; +if(typeof _editor_url=="string"){ +_editor_url=_editor_url.replace(/\x2f*$/,"/"); +if(!_editor_url.match(/^([^:]+\:)?\//)){ +var path=window.location.toString().split("/"); +path.pop(); +_editor_url=Xinha._resolveRelativeUrl(path.join("/"),_editor_url); +} +}else{ +alert("WARNING: _editor_url is not set! You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea/', but it can be relative if you prefer. Further we will try to load the editor files correctly but we'll probably fail."); +_editor_url=""; +} +if(typeof _editor_lang=="string"){ +_editor_lang=_editor_lang.toLowerCase(); +}else{ +_editor_lang="en"; +} +if(typeof _editor_skin!=="string"){ +_editor_skin=""; +} +var __xinhas=[]; +Xinha.agt=navigator.userAgent.toLowerCase(); +Xinha.is_ie=((Xinha.agt.indexOf("msie")!=-1)&&(Xinha.agt.indexOf("opera")==-1)); +Xinha.ie_version=parseFloat(Xinha.agt.substring(Xinha.agt.indexOf("msie")+5)); +Xinha.is_opera=(Xinha.agt.indexOf("opera")!=-1); +Xinha.opera_version=navigator.appVersion.substring(0,navigator.appVersion.indexOf(" "))*1; +Xinha.is_khtml=(Xinha.agt.indexOf("khtml")!=-1); +Xinha.is_safari=(Xinha.agt.indexOf("safari")!=-1); +Xinha.is_mac=(Xinha.agt.indexOf("mac")!=-1); +Xinha.is_mac_ie=(Xinha.is_ie&&Xinha.is_mac); +Xinha.is_win_ie=(Xinha.is_ie&&!Xinha.is_mac); +Xinha.is_gecko=(navigator.product=="Gecko"&&!Xinha.is_safari); +Xinha.isRunLocally=document.URL.toLowerCase().search(/^file:/)!=-1; +Xinha.is_designMode=(typeof document.designMode!="undefined"&&!Xinha.is_ie); +Xinha.checkSupportedBrowser=function(){ +if(Xinha.is_gecko){ +if(navigator.productSub<20021201){ +alert("You need at least Mozilla-1.3 Alpha.\nSorry, your Gecko is not supported."); +return false; +} +if(navigator.productSub<20030210){ +alert("Mozilla < 1.3 Beta is not supported!\nI'll try, though, but it might not work."); +} +} +if(Xinha.is_opera){ +alert("Sorry, Opera is not yet supported by Xinha."); +} +return Xinha.is_gecko||(Xinha.is_opera&&Xinha.opera_version>=9.1)||Xinha.ie_version>=5.5; +}; +Xinha.isSupportedBrowser=Xinha.checkSupportedBrowser(); +if(Xinha.isRunLocally&&Xinha.isSupportedBrowser){ +alert("Xinha *must* be installed on a web server. Locally opened files (those that use the \"file://\" protocol) cannot properly function. Xinha will try to initialize but may not be correctly loaded."); +} +function Xinha(_5,_6){ +if(!Xinha.isSupportedBrowser){ +return; +} +if(!_5){ +throw ("Tried to create Xinha without textarea specified."); +} +if(typeof _6=="undefined"){ +this.config=new Xinha.Config(); +}else{ +this.config=_6; +} +if(typeof _5!="object"){ +_5=Xinha.getElementById("textarea",_5); +} +this._textArea=_5; +this._textArea.spellcheck=false; +Xinha.freeLater(this,"_textArea"); +this._initial_ta_size={w:_5.style.width?_5.style.width:(_5.offsetWidth?(_5.offsetWidth+"px"):(_5.cols+"em")),h:_5.style.height?_5.style.height:(_5.offsetHeight?(_5.offsetHeight+"px"):(_5.rows+"em"))}; +if(document.getElementById("loading_"+_5.id)||this.config.showLoading){ +if(!document.getElementById("loading_"+_5.id)){ +Xinha.createLoadingMessage(_5); +} +this.setLoadingMessage(Xinha._lc("Constructing object")); +} +this._editMode="wysiwyg"; +this.plugins={}; +this._timerToolbar=null; +this._timerUndo=null; +this._undoQueue=[this.config.undoSteps]; +this._undoPos=-1; +this._customUndo=true; +this._mdoc=document; +this.doctype=""; +this.__htmlarea_id_num=__xinhas.length; +__xinhas[this.__htmlarea_id_num]=this; +this._notifyListeners={}; +var _7={right:{on:true,container:document.createElement("td"),panels:[]},left:{on:true,container:document.createElement("td"),panels:[]},top:{on:true,container:document.createElement("td"),panels:[]},bottom:{on:true,container:document.createElement("td"),panels:[]}}; +for(var i in _7){ +if(!_7[i].container){ +continue; +} +_7[i].div=_7[i].container; +_7[i].container.className="panels "+i; +Xinha.freeLater(_7[i],"container"); +Xinha.freeLater(_7[i],"div"); +} +this._panels=_7; +this._statusBar=null; +this._statusBarTree=null; +this._statusBarTextMode=null; +this._statusBarItems=[]; +this._framework={}; +this._htmlArea=null; +this._iframe=null; +this._doc=null; +this._toolBar=this._toolbar=null; +this._toolbarObjects={}; +} +Xinha.onload=function(){ +}; +Xinha.init=function(){ +Xinha.onload(); +}; +Xinha.RE_tagName=/(<\/|<)\s*([^ \t\n>]+)/ig; +Xinha.RE_doctype=/()\n?/i; +Xinha.RE_head=/((.|\n)*?)<\/head>/i; +Xinha.RE_body=/]*>((.|\n|\r|\t)*?)<\/body>/i; +Xinha.RE_Specials=/([\/\^$*+?.()|{}[\]])/g; +Xinha.escapeStringForRegExp=function(_9){ +return _9.replace(Xinha.RE_Specials,"\\$1"); +}; +Xinha.RE_email=/[_a-z\d\-\.]{3,}@[_a-z\d\-]{2,}(\.[_a-z\d\-]{2,})+/i; +Xinha.RE_url=/(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,}){2,}(:[0-9]+)?(\/\S+)*)/i; +Xinha.Config=function(){ +var _a=this; +this.version=Xinha.version.Revision; +this.width="auto"; +this.height="auto"; +this.sizeIncludesBars=true; +this.sizeIncludesPanels=true; +this.panel_dimensions={left:"200px",right:"200px",top:"100px",bottom:"100px"}; +this.iframeWidth=null; +this.statusBar=true; +this.htmlareaPaste=false; +this.mozParaHandler="best"; +this.getHtmlMethod="DOMwalk"; +this.undoSteps=20; +this.undoTimeout=500; +this.changeJustifyWithDirection=false; +this.fullPage=false; +this.pageStyle=""; +this.pageStyleSheets=[]; +this.baseHref=null; +this.expandRelativeUrl=true; +this.stripBaseHref=true; +this.stripSelfNamedAnchors=true; +this.only7BitPrintablesInURLs=true; +this.sevenBitClean=false; +this.specialReplacements={}; +this.killWordOnPaste=true; +this.makeLinkShowsTarget=true; +this.charSet=(typeof document.characterSet!="undefined")?document.characterSet:document.charset; +this.browserQuirksMode=null; +this.imgURL="images/"; +this.popupURL="popups/"; +this.htmlRemoveTags=null; +this.flowToolbars=true; +this.toolbarAlign="left"; +this.showLoading=false; +this.stripScripts=true; +this.convertUrlsToLinks=true; +this.colorPickerCellSize="6px"; +this.colorPickerGranularity=18; +this.colorPickerPosition="bottom,right"; +this.colorPickerWebSafe=false; +this.colorPickerSaveColors=20; +this.fullScreen=false; +this.fullScreenMargins=[0,0,0,0]; +this.toolbar=[["popupeditor"],["separator","formatblock","fontname","fontsize","bold","italic","underline","strikethrough"],["separator","forecolor","hilitecolor","textindicator"],["separator","subscript","superscript"],["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"],["separator","insertorderedlist","insertunorderedlist","outdent","indent"],["separator","inserthorizontalrule","createlink","insertimage","inserttable"],["linebreak","separator","undo","redo","selectall","print"],(Xinha.is_gecko?[]:["cut","copy","paste","overwrite","saveas"]),["separator","killword","clearfonts","removeformat","toggleborders","splitblock","lefttoright","righttoleft"],["separator","htmlmode","showhelp","about"]]; +this.fontname={"— font —":"","Arial":"arial,helvetica,sans-serif","Courier New":"courier new,courier,monospace","Georgia":"georgia,times new roman,times,serif","Tahoma":"tahoma,arial,helvetica,sans-serif","Times New Roman":"times new roman,times,serif","Verdana":"verdana,arial,helvetica,sans-serif","impact":"impact","WingDings":"wingdings"}; +this.fontsize={"— size —":"","1 (8 pt)":"1","2 (10 pt)":"2","3 (12 pt)":"3","4 (14 pt)":"4","5 (18 pt)":"5","6 (24 pt)":"6","7 (36 pt)":"7"}; +this.formatblock={"— format —":"","Heading 1":"h1","Heading 2":"h2","Heading 3":"h3","Heading 4":"h4","Heading 5":"h5","Heading 6":"h6","Normal":"p","Address":"address","Formatted":"pre"}; +this.customSelects={}; +this.debug=true; +this.URIs={"blank":"popups/blank.html","link":_editor_url+"modules/CreateLink/link.html","insert_image":_editor_url+"modules/InsertImage/insert_image.html","insert_table":_editor_url+"modules/InsertTable/insert_table.html","select_color":"select_color.html","about":"about.html","help":"editor_help.html"}; +this.btnList={bold:["Bold",Xinha._lc({key:"button_bold",string:["ed_buttons_main.gif",3,2]},"Xinha"),false,function(e){ +e.execCommand("bold"); +}],italic:["Italic",Xinha._lc({key:"button_italic",string:["ed_buttons_main.gif",2,2]},"Xinha"),false,function(e){ +e.execCommand("italic"); +}],underline:["Underline",Xinha._lc({key:"button_underline",string:["ed_buttons_main.gif",2,0]},"Xinha"),false,function(e){ +e.execCommand("underline"); +}],strikethrough:["Strikethrough",Xinha._lc({key:"button_strikethrough",string:["ed_buttons_main.gif",3,0]},"Xinha"),false,function(e){ +e.execCommand("strikethrough"); +}],subscript:["Subscript",Xinha._lc({key:"button_subscript",string:["ed_buttons_main.gif",3,1]},"Xinha"),false,function(e){ +e.execCommand("subscript"); +}],superscript:["Superscript",Xinha._lc({key:"button_superscript",string:["ed_buttons_main.gif",2,1]},"Xinha"),false,function(e){ +e.execCommand("superscript"); +}],justifyleft:["Justify Left",["ed_buttons_main.gif",0,0],false,function(e){ +e.execCommand("justifyleft"); +}],justifycenter:["Justify Center",["ed_buttons_main.gif",1,1],false,function(e){ +e.execCommand("justifycenter"); +}],justifyright:["Justify Right",["ed_buttons_main.gif",1,0],false,function(e){ +e.execCommand("justifyright"); +}],justifyfull:["Justify Full",["ed_buttons_main.gif",0,1],false,function(e){ +e.execCommand("justifyfull"); +}],orderedlist:["Ordered List",["ed_buttons_main.gif",0,3],false,function(e){ +e.execCommand("insertorderedlist"); +}],unorderedlist:["Bulleted List",["ed_buttons_main.gif",1,3],false,function(e){ +e.execCommand("insertunorderedlist"); +}],insertorderedlist:["Ordered List",["ed_buttons_main.gif",0,3],false,function(e){ +e.execCommand("insertorderedlist"); +}],insertunorderedlist:["Bulleted List",["ed_buttons_main.gif",1,3],false,function(e){ +e.execCommand("insertunorderedlist"); +}],outdent:["Decrease Indent",["ed_buttons_main.gif",1,2],false,function(e){ +e.execCommand("outdent"); +}],indent:["Increase Indent",["ed_buttons_main.gif",0,2],false,function(e){ +e.execCommand("indent"); +}],forecolor:["Font Color",["ed_buttons_main.gif",3,3],false,function(e){ +e.execCommand("forecolor"); +}],hilitecolor:["Background Color",["ed_buttons_main.gif",2,3],false,function(e){ +e.execCommand("hilitecolor"); +}],undo:["Undoes your last action",["ed_buttons_main.gif",4,2],false,function(e){ +e.execCommand("undo"); +}],redo:["Redoes your last action",["ed_buttons_main.gif",5,2],false,function(e){ +e.execCommand("redo"); +}],cut:["Cut selection",["ed_buttons_main.gif",5,0],false,function(e,cmd){ +e.execCommand(cmd); +}],copy:["Copy selection",["ed_buttons_main.gif",4,0],false,function(e,cmd){ +e.execCommand(cmd); +}],paste:["Paste from clipboard",["ed_buttons_main.gif",4,1],false,function(e,cmd){ +e.execCommand(cmd); +}],selectall:["Select all","ed_selectall.gif",false,function(e){ +e.execCommand("selectall"); +}],inserthorizontalrule:["Horizontal Rule",["ed_buttons_main.gif",6,0],false,function(e){ +e.execCommand("inserthorizontalrule"); +}],createlink:["Insert Web Link",["ed_buttons_main.gif",6,1],false,function(e){ +e._createLink(); +}],insertimage:["Insert/Modify Image",["ed_buttons_main.gif",6,3],false,function(e){ +e.execCommand("insertimage"); +}],inserttable:["Insert Table",["ed_buttons_main.gif",6,2],false,function(e){ +e.execCommand("inserttable"); +}],htmlmode:["Toggle HTML Source",["ed_buttons_main.gif",7,0],true,function(e){ +e.execCommand("htmlmode"); +}],toggleborders:["Toggle Borders",["ed_buttons_main.gif",7,2],false,function(e){ +e._toggleBorders(); +}],print:["Print document",["ed_buttons_main.gif",8,1],false,function(e){ +if(Xinha.is_gecko){ +e._iframe.contentWindow.print(); +}else{ +e.focusEditor(); +print(); +} +}],saveas:["Save as","ed_saveas.gif",false,function(e){ +e.execCommand("saveas",false,"noname.htm"); +}],about:["About this editor",["ed_buttons_main.gif",8,2],true,function(e){ +e.execCommand("about"); +}],showhelp:["Help using editor",["ed_buttons_main.gif",9,2],true,function(e){ +e.execCommand("showhelp"); +}],splitblock:["Split Block","ed_splitblock.gif",false,function(e){ +e._splitBlock(); +}],lefttoright:["Direction left to right",["ed_buttons_main.gif",0,4],false,function(e){ +e.execCommand("lefttoright"); +}],righttoleft:["Direction right to left",["ed_buttons_main.gif",1,4],false,function(e){ +e.execCommand("righttoleft"); +}],overwrite:["Insert/Overwrite","ed_overwrite.gif",false,function(e){ +e.execCommand("overwrite"); +}],wordclean:["MS Word Cleaner",["ed_buttons_main.gif",5,3],false,function(e){ +e._wordClean(); +}],clearfonts:["Clear Inline Font Specifications",["ed_buttons_main.gif",5,4],true,function(e){ +e._clearFonts(); +}],removeformat:["Remove formatting",["ed_buttons_main.gif",4,4],false,function(e){ +e.execCommand("removeformat"); +}],killword:["Clear MSOffice tags",["ed_buttons_main.gif",4,3],false,function(e){ +e.execCommand("killword"); +}]}; +for(var i in this.btnList){ +var btn=this.btnList[i]; +if(typeof btn!="object"){ +continue; +} +if(typeof btn[1]!="string"){ +btn[1][0]=_editor_url+this.imgURL+btn[1][0]; +}else{ +btn[1]=_editor_url+this.imgURL+btn[1]; +} +btn[0]=Xinha._lc(btn[0]); +} +}; +Xinha.Config.prototype.registerButton=function(id,_3b,_3c,_3d,_3e,_3f){ +var _40; +if(typeof id=="string"){ +_40=id; +}else{ +if(typeof id=="object"){ +_40=id.id; +}else{ +alert("ERROR [Xinha.Config::registerButton]:\ninvalid arguments"); +return false; +} +} +switch(typeof id){ +case "string": +this.btnList[id]=[_3b,_3c,_3d,_3e,_3f]; +break; +case "object": +this.btnList[id.id]=[id.tooltip,id.image,id.textMode,id.action,id.context]; +break; +} +}; +Xinha.prototype.registerPanel=function(_41,_42){ +if(!_41){ +_41="right"; +} +this.setLoadingMessage("Register "+_41+" panel "); +var _43=this.addPanel(_41); +if(_42){ +_42.drawPanelIn(_43); +} +}; +Xinha.Config.prototype.registerDropdown=function(_44){ +this.customSelects[_44.id]=_44; +}; +Xinha.Config.prototype.hideSomeButtons=function(_45){ +var _46=this.toolbar; +for(var i=_46.length;--i>=0;){ +var _48=_46[i]; +for(var j=_48.length;--j>=0;){ +if(_45.indexOf(" "+_48[j]+" ")>=0){ +var len=1; +if(/separator|space/.test(_48[j+1])){ +len=2; +} +_48.splice(j,len); +} +} +} +}; +Xinha.Config.prototype.addToolbarElement=function(id,_4c,_4d){ +var _4e=this.toolbar; +var a,i,j,o,sid; +var _50=false; +var _51=false; +var _52=0; +var _53=0; +var _54=0; +var _55=false; +var _56=false; +if((id&&typeof id=="object")&&(id.constructor==Array)){ +_50=true; +} +if((_4c&&typeof _4c=="object")&&(_4c.constructor==Array)){ +_51=true; +_52=_4c.length; +} +if(_50){ +for(i=0;i=0;){ +a.splice(j,0,id[i]); +} +}else{ +a[j]=id; +} +}else{ +if(_4d<0){ +j=j+_4d+1; +}else{ +if(_4d>0){ +j=j+_4d; +} +} +if(_50){ +for(i=id.length;--i>=0;){ +a.splice(j,0,id[i]); +} +}else{ +a.splice(j,0,id); +} +} +}else{ +_4e[0].splice(0,0,"separator"); +if(_50){ +for(i=id.length;--i>=0;){ +_4e[0].splice(0,0,id[i]); +} +}else{ +_4e[0].splice(0,0,id); +} +} +}; +Xinha.Config.prototype.removeToolbarElement=Xinha.Config.prototype.hideSomeButtons; +Xinha.replaceAll=function(_57){ +var tas=document.getElementsByTagName("textarea"); +for(var i=tas.length;i>0;(new Xinha(tas[--i],_57)).generate()){ +} +}; +Xinha.replace=function(id,_5b){ +var ta=Xinha.getElementById("textarea",id); +return ta?(new Xinha(ta,_5b)).generate():null; +}; +Xinha.prototype._createToolbar=function(){ +this.setLoadingMessage(Xinha._lc("Create Toolbar")); +var _5d=this; +var _5e=document.createElement("div"); +this._toolBar=this._toolbar=_5e; +_5e.className="toolbar"; +_5e.unselectable="1"; +Xinha.freeLater(this,"_toolBar"); +Xinha.freeLater(this,"_toolbar"); +var _5f=null; +var _60={}; +this._toolbarObjects=_60; +this._createToolbar1(_5d,_5e,_60); +this._htmlArea.appendChild(_5e); +return _5e; +}; +Xinha.prototype._setConfig=function(_61){ +this.config=_61; +}; +Xinha.prototype._addToolbar=function(){ +this._createToolbar1(this,this._toolbar,this._toolbarObjects); +}; +Xinha._createToolbarBreakingElement=function(){ +var brk=document.createElement("div"); +brk.style.height="1px"; +brk.style.width="1px"; +brk.style.lineHeight="1px"; +brk.style.fontSize="1px"; +brk.style.clear="both"; +return brk; +}; +Xinha.prototype._createToolbar1=function(_63,_64,_65){ +var _66; +if(_63.config.flowToolbars){ +_64.appendChild(Xinha._createToolbarBreakingElement()); +} +function newLine(){ +if(typeof _66!="undefined"&&_66.childNodes.length===0){ +return; +} +var _67=document.createElement("table"); +_67.border="0px"; +_67.cellSpacing="0px"; +_67.cellPadding="0px"; +if(_63.config.flowToolbars){ +if(Xinha.is_ie){ +_67.style.styleFloat="left"; +}else{ +_67.style.cssFloat="left"; +} +} +_64.appendChild(_67); +var _68=document.createElement("tbody"); +_67.appendChild(_68); +_66=document.createElement("tr"); +_68.appendChild(_66); +_67.className="toolbarRow"; +} +newLine(); +function setButtonStatus(id,_6a){ +var _6b=this[id]; +var el=this.element; +if(_6b!=_6a){ +switch(id){ +case "enabled": +if(_6a){ +Xinha._removeClass(el,"buttonDisabled"); +el.disabled=false; +}else{ +Xinha._addClass(el,"buttonDisabled"); +el.disabled=true; +} +break; +case "active": +if(_6a){ +Xinha._addClass(el,"buttonPressed"); +}else{ +Xinha._removeClass(el,"buttonPressed"); +} +break; +} +this[id]=_6a; +} +} +function createSelect(txt){ +var _6e=null; +var el=null; +var cmd=null; +var _71=_63.config.customSelects; +var _72=null; +var _73=""; +switch(txt){ +case "fontsize": +case "fontname": +case "formatblock": +_6e=_63.config[txt]; +cmd=txt; +break; +default: +cmd=txt; +var _74=_71[cmd]; +if(typeof _74!="undefined"){ +_6e=_74.options; +_72=_74.context; +if(typeof _74.tooltip!="undefined"){ +_73=_74.tooltip; +} +}else{ +alert("ERROR [createSelect]:\nCan't find the requested dropdown definition"); +} +break; +} +if(_6e){ +el=document.createElement("select"); +el.title=_73; +var obj={name:txt,element:el,enabled:true,text:false,cmd:cmd,state:setButtonStatus,context:_72}; +Xinha.freeLater(obj); +_65[txt]=obj; +for(var i in _6e){ +if(typeof (_6e[i])!="string"){ +continue; +} +var op=document.createElement("option"); +op.innerHTML=Xinha._lc(i); +op.value=_6e[i]; +el.appendChild(op); +} +Xinha._addEvent(el,"change",function(){ +_63._comboSelected(el,txt); +}); +} +return el; +} +function createButton(txt){ +var el,btn,obj=null; +switch(txt){ +case "separator": +if(_63.config.flowToolbars){ +newLine(); +} +el=document.createElement("div"); +el.className="separator"; +break; +case "space": +el=document.createElement("div"); +el.className="space"; +break; +case "linebreak": +newLine(); +return false; +case "textindicator": +el=document.createElement("div"); +el.appendChild(document.createTextNode("A")); +el.className="indicator"; +el.title=Xinha._lc("Current style"); +obj={name:txt,element:el,enabled:true,active:false,text:false,cmd:"textindicator",state:setButtonStatus}; +Xinha.freeLater(obj); +_65[txt]=obj; +break; +default: +btn=_63.config.btnList[txt]; +} +if(!el&&btn){ +el=document.createElement("a"); +el.style.display="block"; +el.href="javascript:void(0)"; +el.style.textDecoration="none"; +el.title=btn[0]; +el.className="button"; +el.style.direction="ltr"; +obj={name:txt,element:el,enabled:true,active:false,text:btn[2],cmd:btn[3],state:setButtonStatus,context:btn[4]||null}; +Xinha.freeLater(el); +Xinha.freeLater(obj); +_65[txt]=obj; +el.ondrag=function(){ +return false; +}; +Xinha._addEvent(el,"mouseout",function(ev){ +if(obj.enabled){ +Xinha._removeClass(el,"buttonActive"); +if(obj.active){ +Xinha._addClass(el,"buttonPressed"); +} +} +}); +Xinha._addEvent(el,"mousedown",function(ev){ +if(obj.enabled){ +Xinha._addClass(el,"buttonActive"); +Xinha._removeClass(el,"buttonPressed"); +Xinha._stopEvent(Xinha.is_ie?window.event:ev); +} +}); +Xinha._addEvent(el,"click",function(ev){ +ev=Xinha.is_ie?window.event:ev; +_63.btnClickEvent=ev; +if(obj.enabled){ +Xinha._removeClass(el,"buttonActive"); +if(Xinha.is_gecko){ +_63.activateEditor(); +} +obj.cmd(_63,obj.name,obj); +Xinha._stopEvent(ev); +} +}); +var _7d=Xinha.makeBtnImg(btn[1]); +var img=_7d.firstChild; +Xinha.freeLater(_7d); +Xinha.freeLater(img); +el.appendChild(_7d); +obj.imgel=img; +obj.swapImage=function(_7f){ +if(typeof _7f!="string"){ +img.src=_7f[0]; +img.style.position="relative"; +img.style.top=_7f[2]?("-"+(18*(_7f[2]+1))+"px"):"-18px"; +img.style.left=_7f[1]?("-"+(18*(_7f[1]+1))+"px"):"-18px"; +}else{ +obj.imgel.src=_7f; +img.style.top="0px"; +img.style.left="0px"; +} +}; +}else{ +if(!el){ +el=createSelect(txt); +} +} +return el; +} +var _80=true; +for(var i=0;i] button to switch back to WYSIWYG."); +div.style.display="none"; +this._statusBarTextMode=div; +Xinha.freeLater(this,"_statusBarTextMode"); +this._statusBar.appendChild(div); +if(!this.config.statusBar){ +_8d.style.display="none"; +} +return _8d; +}; +Xinha.prototype.generate=function(){ +if(!Xinha.isSupportedBrowser){ +return; +} +var i; +var _90=this; +var url; +if(!document.getElementById("XinhaCoreDesign")){ +Xinha.loadStyle(typeof _editor_css=="string"?_editor_css:"Xinha.css",null,"XinhaCoreDesign"); +} +if(Xinha.is_ie){ +url=_editor_url+"modules/InternetExplorer/InternetExplorer.js"; +if(typeof InternetExplorer=="undefined"&&!document.getElementById(url)){ +Xinha.loadPlugin("InternetExplorer",function(){ +_90.generate(); +},url); +return false; +} +_90._browserSpecificPlugin=_90.registerPlugin("InternetExplorer"); +}else{ +url=_editor_url+"modules/Gecko/Gecko.js"; +if(typeof Gecko=="undefined"&&!document.getElementById(url)){ +Xinha.loadPlugin("Gecko",function(){ +_90.generate(); +},url); +return false; +} +_90._browserSpecificPlugin=_90.registerPlugin("Gecko"); +} +if(typeof Dialog=="undefined"&&!Xinha._loadback(_editor_url+"modules/Dialogs/dialog.js",this.generate,this)){ +return false; +} +if(typeof Xinha.Dialog=="undefined"&&!Xinha._loadback(_editor_url+"modules/Dialogs/inline-dialog.js",this.generate,this)){ +return false; +} +url=_editor_url+"modules/FullScreen/full-screen.js"; +if(typeof FullScreen=="undefined"&&!document.getElementById(url)){ +Xinha.loadPlugin("FullScreen",function(){ +_90.generate(); +},url); +return false; +} +url=_editor_url+"modules/ColorPicker/ColorPicker.js"; +if(typeof ColorPicker=="undefined"&&!document.getElementById(url)){ +Xinha.loadPlugin("ColorPicker",function(){ +_90.generate(); +},url); +return false; +}else{ +if(typeof ColorPicker!="undefined"){ +_90.registerPlugin("ColorPicker"); +} +} +var _92=_90.config.toolbar; +for(i=_92.length;--i>=0;){ +for(var j=_92[i].length;--j>=0;){ +switch(_92[i][j]){ +case "popupeditor": +_90.registerPlugin("FullScreen"); +break; +case "insertimage": +url=_editor_url+"modules/InsertImage/insert_image.js"; +if(typeof InsertImage=="undefined"&&typeof Xinha.prototype._insertImage=="undefined"&&!document.getElementById(url)){ +Xinha.loadPlugin("InsertImage",function(){ +_90.generate(); +},url); +return false; +}else{ +if(typeof InsertImage!="undefined"){ +_90.registerPlugin("InsertImage"); +} +} +break; +case "createlink": +url=_editor_url+"modules/CreateLink/link.js"; +if(typeof CreateLink=="undefined"&&typeof Xinha.prototype._createLink=="undefined"&&typeof Linker=="undefined"&&!document.getElementById(url)){ +Xinha.loadPlugin("CreateLink",function(){ +_90.generate(); +},url); +return false; +}else{ +if(typeof CreateLink!="undefined"){ +_90.registerPlugin("CreateLink"); +} +} +break; +case "inserttable": +url=_editor_url+"modules/InsertTable/insert_table.js"; +if(typeof InsertTable=="undefined"&&typeof Xinha.prototype._insertTable=="undefined"&&!document.getElementById(url)){ +Xinha.loadPlugin("InsertTable",function(){ +_90.generate(); +},url); +return false; +}else{ +if(typeof InsertTable!="undefined"){ +_90.registerPlugin("InsertTable"); +} +} +break; +} +} +} +if(Xinha.is_gecko&&(_90.config.mozParaHandler=="best"||_90.config.mozParaHandler=="dirty")){ +switch(this.config.mozParaHandler){ +case "dirty": +var _94=_editor_url+"modules/Gecko/paraHandlerDirty.js"; +break; +default: +var _94=_editor_url+"modules/Gecko/paraHandlerBest.js"; +break; +} +if(typeof EnterParagraphs=="undefined"&&!document.getElementById(_94)){ +Xinha.loadPlugin("EnterParagraphs",function(){ +_90.generate(); +},_94); +return false; +} +_90.registerPlugin("EnterParagraphs"); +} +switch(this.config.getHtmlMethod){ +case "TransformInnerHTML": +var _95=_editor_url+"modules/GetHtml/TransformInnerHTML.js"; +break; +default: +var _95=_editor_url+"modules/GetHtml/DOMwalk.js"; +break; +} +if(typeof GetHtmlImplementation=="undefined"&&!document.getElementById(_95)){ +Xinha.loadPlugin("GetHtmlImplementation",function(){ +_90.generate(); +},_95); +return false; +}else{ +_90.registerPlugin("GetHtmlImplementation"); +} +if(_editor_skin!==""){ +var _96=false; +var _97=document.getElementsByTagName("head")[0]; +var _98=document.getElementsByTagName("link"); +for(i=0;i<_98.length;i++){ +if((_98[i].rel=="stylesheet")&&(_98[i].href==_editor_url+"skins/"+_editor_skin+"/skin.css")){ +_96=true; +} +} +if(!_96){ +var _99=document.createElement("link"); +_99.type="text/css"; +_99.href=_editor_url+"skins/"+_editor_skin+"/skin.css"; +_99.rel="stylesheet"; +_97.appendChild(_99); +} +} +this.setLoadingMessage(Xinha._lc("Generate Xinha framework")); +this._framework={"table":document.createElement("table"),"tbody":document.createElement("tbody"),"tb_row":document.createElement("tr"),"tb_cell":document.createElement("td"),"tp_row":document.createElement("tr"),"tp_cell":this._panels.top.container,"ler_row":document.createElement("tr"),"lp_cell":this._panels.left.container,"ed_cell":document.createElement("td"),"rp_cell":this._panels.right.container,"bp_row":document.createElement("tr"),"bp_cell":this._panels.bottom.container,"sb_row":document.createElement("tr"),"sb_cell":document.createElement("td")}; +Xinha.freeLater(this._framework); +var fw=this._framework; +fw.table.border="0"; +fw.table.cellPadding="0"; +fw.table.cellSpacing="0"; +fw.tb_row.style.verticalAlign="top"; +fw.tp_row.style.verticalAlign="top"; +fw.ler_row.style.verticalAlign="top"; +fw.bp_row.style.verticalAlign="top"; +fw.sb_row.style.verticalAlign="top"; +fw.ed_cell.style.position="relative"; +fw.tb_row.appendChild(fw.tb_cell); +fw.tb_cell.colSpan=3; +fw.tp_row.appendChild(fw.tp_cell); +fw.tp_cell.colSpan=3; +fw.ler_row.appendChild(fw.lp_cell); +fw.ler_row.appendChild(fw.ed_cell); +fw.ler_row.appendChild(fw.rp_cell); +fw.bp_row.appendChild(fw.bp_cell); +fw.bp_cell.colSpan=3; +fw.sb_row.appendChild(fw.sb_cell); +fw.sb_cell.colSpan=3; +fw.tbody.appendChild(fw.tb_row); +fw.tbody.appendChild(fw.tp_row); +fw.tbody.appendChild(fw.ler_row); +fw.tbody.appendChild(fw.bp_row); +fw.tbody.appendChild(fw.sb_row); +fw.table.appendChild(fw.tbody); +var _9b=this._framework.table; +this._htmlArea=_9b; +Xinha.freeLater(this,"_htmlArea"); +_9b.className="htmlarea"; +this._framework.tb_cell.appendChild(this._createToolbar()); +var _9c=document.createElement("iframe"); +_9c.src=_editor_url+_90.config.URIs.blank; +_9c.id="XinhaIFrame_"+this._textArea.id; +this._framework.ed_cell.appendChild(_9c); +this._iframe=_9c; +this._iframe.className="xinha_iframe"; +Xinha.freeLater(this,"_iframe"); +var _9d=this._createStatusBar(); +this._framework.sb_cell.appendChild(_9d); +var _9e=this._textArea; +_9e.parentNode.insertBefore(_9b,_9e); +_9e.className="xinha_textarea"; +Xinha.removeFromParent(_9e); +this._framework.ed_cell.appendChild(_9e); +Xinha.addDom0Event(this._textArea,"click",function(){ +if(Xinha._currentlyActiveEditor!=this){ +_90.updateToolbar(); +} +return true; +}); +if(_9e.form){ +Xinha.prependDom0Event(this._textArea.form,"submit",function(){ +_90._textArea.value=_90.outwardHtml(_90.getHTML()); +return true; +}); +var _9f=_9e.value; +Xinha.prependDom0Event(this._textArea.form,"reset",function(){ +_90.setHTML(_90.inwardHtml(_9f)); +_90.updateToolbar(); +return true; +}); +if(!_9e.form.xinha_submit){ +try{ +_9e.form.xinha_submit=_9e.form.submit; +_9e.form.submit=function(){ +this.onsubmit(); +this.xinha_submit(); +}; +} +catch(ex){ +} +} +} +Xinha.prependDom0Event(window,"unload",function(){ +_9e.value=_90.outwardHtml(_90.getHTML()); +if(!Xinha.is_ie){ +_9b.parentNode.replaceChild(_9e,_9b); +} +return true; +}); +_9e.style.display="none"; +_90.initSize(); +this.setLoadingMessage(Xinha._lc("Finishing")); +_90._iframeLoadDone=false; +if(Xinha.is_opera){ +Xinha._addEvent(this._iframe.contentWindow,"load",function(e){ +if(!_90._iframeLoadDone){ +_90._iframeLoadDone=true; +_90.initIframe(); +} +return true; +}); +}else{ +Xinha._addEvent(this._iframe,"load",function(e){ +if(!_90._iframeLoadDone){ +_90._iframeLoadDone=true; +_90.initIframe(); +} +return true; +}); +} +}; +Xinha.prototype.initSize=function(){ +this.setLoadingMessage(Xinha._lc("Init editor size")); +var _a2=this; +var _a3=null; +var _a4=null; +switch(this.config.width){ +case "auto": +_a3=this._initial_ta_size.w; +break; +case "toolbar": +_a3=this._toolBar.offsetWidth+"px"; +break; +default: +_a3=/[^0-9]/.test(this.config.width)?this.config.width:this.config.width+"px"; +break; +} +switch(this.config.height){ +case "auto": +_a4=this._initial_ta_size.h; +break; +default: +_a4=/[^0-9]/.test(this.config.height)?this.config.height:this.config.height+"px"; +break; +} +this.sizeEditor(_a3,_a4,this.config.sizeIncludesBars,this.config.sizeIncludesPanels); +this.notifyOn("panel_change",function(){ +_a2.sizeEditor(); +}); +}; +Xinha.prototype.sizeEditor=function(_a5,_a6,_a7,_a8){ +if(this._risizing){ +return; +} +this._risizing=true; +this.notifyOf("before_resize",{width:_a5,height:_a6}); +this._iframe.style.height="100%"; +this._textArea.style.height="100%"; +this._iframe.style.width=""; +this._textArea.style.width=""; +if(_a7!==null){ +this._htmlArea.sizeIncludesToolbars=_a7; +} +if(_a8!==null){ +this._htmlArea.sizeIncludesPanels=_a8; +} +if(_a5){ +this._htmlArea.style.width=_a5; +if(!this._htmlArea.sizeIncludesPanels){ +var _a9=this._panels.right; +if(_a9.on&&_a9.panels.length&&Xinha.hasDisplayedChildren(_a9.div)){ +this._htmlArea.style.width=(this._htmlArea.offsetWidth+parseInt(this.config.panel_dimensions.right,10))+"px"; +} +var _aa=this._panels.left; +if(_aa.on&&_aa.panels.length&&Xinha.hasDisplayedChildren(_aa.div)){ +this._htmlArea.style.width=(this._htmlArea.offsetWidth+parseInt(this.config.panel_dimensions.left,10))+"px"; +} +} +} +if(_a6){ +this._htmlArea.style.height=_a6; +if(!this._htmlArea.sizeIncludesToolbars){ +this._htmlArea.style.height=(this._htmlArea.offsetHeight+this._toolbar.offsetHeight+this._statusBar.offsetHeight)+"px"; +} +if(!this._htmlArea.sizeIncludesPanels){ +var _ab=this._panels.top; +if(_ab.on&&_ab.panels.length&&Xinha.hasDisplayedChildren(_ab.div)){ +this._htmlArea.style.height=(this._htmlArea.offsetHeight+parseInt(this.config.panel_dimensions.top,10))+"px"; +} +var _ac=this._panels.bottom; +if(_ac.on&&_ac.panels.length&&Xinha.hasDisplayedChildren(_ac.div)){ +this._htmlArea.style.height=(this._htmlArea.offsetHeight+parseInt(this.config.panel_dimensions.bottom,10))+"px"; +} +} +} +_a5=this._htmlArea.offsetWidth; +_a6=this._htmlArea.offsetHeight; +var _ad=this._panels; +var _ae=this; +var _af=1; +function panel_is_alive(pan){ +if(_ad[pan].on&&_ad[pan].panels.length&&Xinha.hasDisplayedChildren(_ad[pan].container)){ +_ad[pan].container.style.display=""; +return true; +}else{ +_ad[pan].container.style.display="none"; +return false; +} +} +if(panel_is_alive("left")){ +_af+=1; +} +if(panel_is_alive("right")){ +_af+=1; +} +this._framework.tb_cell.colSpan=_af; +this._framework.tp_cell.colSpan=_af; +this._framework.bp_cell.colSpan=_af; +this._framework.sb_cell.colSpan=_af; +if(!this._framework.tp_row.childNodes.length){ +Xinha.removeFromParent(this._framework.tp_row); +}else{ +if(!Xinha.hasParentNode(this._framework.tp_row)){ +this._framework.tbody.insertBefore(this._framework.tp_row,this._framework.ler_row); +} +} +if(!this._framework.bp_row.childNodes.length){ +Xinha.removeFromParent(this._framework.bp_row); +}else{ +if(!Xinha.hasParentNode(this._framework.bp_row)){ +this._framework.tbody.insertBefore(this._framework.bp_row,this._framework.ler_row.nextSibling); +} +} +if(!this.config.statusBar){ +Xinha.removeFromParent(this._framework.sb_row); +}else{ +if(!Xinha.hasParentNode(this._framework.sb_row)){ +this._framework.table.appendChild(this._framework.sb_row); +} +} +this._framework.lp_cell.style.width=this.config.panel_dimensions.left; +this._framework.rp_cell.style.width=this.config.panel_dimensions.right; +this._framework.tp_cell.style.height=this.config.panel_dimensions.top; +this._framework.bp_cell.style.height=this.config.panel_dimensions.bottom; +this._framework.tb_cell.style.height=this._toolBar.offsetHeight+"px"; +this._framework.sb_cell.style.height=this._statusBar.offsetHeight+"px"; +var _b1=_a6-this._toolBar.offsetHeight-this._statusBar.offsetHeight; +if(panel_is_alive("top")){ +_b1-=parseInt(this.config.panel_dimensions.top,10); +} +if(panel_is_alive("bottom")){ +_b1-=parseInt(this.config.panel_dimensions.bottom,10); +} +this._iframe.style.height=_b1+"px"; +var _b2=_a5; +if(panel_is_alive("left")){ +_b2-=parseInt(this.config.panel_dimensions.left,10); +} +if(panel_is_alive("right")){ +_b2-=parseInt(this.config.panel_dimensions.right,10); +} +this._iframe.style.width=_b2+"px"; +this._textArea.style.height=this._iframe.style.height; +this._textArea.style.width=this._iframe.style.width; +this.notifyOf("resize",{width:this._htmlArea.offsetWidth,height:this._htmlArea.offsetHeight}); +this._risizing=false; +}; +Xinha.prototype.registerPanel=function(_b3,_b4){ +if(!_b3){ +_b3="right"; +} +this.setLoadingMessage("Register "+_b3+" panel "); +var _b5=this.addPanel(_b3); +if(_b4){ +_b4.drawPanelIn(_b5); +} +}; +Xinha.prototype.addPanel=function(_b6){ +var div=document.createElement("div"); +div.side=_b6; +if(_b6=="left"||_b6=="right"){ +div.style.width=this.config.panel_dimensions[_b6]; +if(this._iframe){ +div.style.height=this._iframe.style.height; +} +} +Xinha.addClasses(div,"panel"); +this._panels[_b6].panels.push(div); +this._panels[_b6].div.appendChild(div); +this.notifyOf("panel_change",{"action":"add","panel":div}); +return div; +}; +Xinha.prototype.removePanel=function(_b8){ +this._panels[_b8.side].div.removeChild(_b8); +var _b9=[]; +for(var i=0;i"; +}else{ +if(_ca.config.browserQuirksMode===true){ +var _cc=""; +}else{ +var _cc=Xinha.getDoctype(document); +} +} +if(!_ca.config.fullPage){ +_cb+=_cc+"\n"; +_cb+="\n"; +_cb+="\n"; +_cb+="\n"; +if(typeof _ca.config.baseHref!="undefined"&&_ca.config.baseHref!==null){ +_cb+="\n"; +} +_cb+=Xinha.addCoreCSS(); +if(_ca.config.pageStyle){ +_cb+=""; +} +if(typeof _ca.config.pageStyleSheets!=="undefined"){ +for(var i=0;i<_ca.config.pageStyleSheets.length;i++){ +if(_ca.config.pageStyleSheets[i].length>0){ +_cb+=""; +} +} +} +_cb+="\n"; +_cb+="\n"; +_cb+=_ca.inwardHtml(_ca._textArea.value); +_cb+="\n"; +_cb+=""; +}else{ +_cb=_ca.inwardHtml(_ca._textArea.value); +if(_cb.match(Xinha.RE_doctype)){ +_ca.setDoctype(RegExp.$1); +} +var _ce=_cb.match(//gi); +_cb=_cb.replace(/\s*/gi,""); +_ce?_cb=_cb.replace(/<\/head>/i,_ce.join("\n")+"\n"):null; +} +doc.write(_cb); +doc.close(); +if(this.config.fullScreen){ +this._fullScreen(); +} +this.setEditorEvents(); +}; +Xinha.prototype.whenDocReady=function(f){ +var e=this; +if(this._doc&&this._doc.body){ +f(); +}else{ +setTimeout(function(){ +e.whenDocReady(f); +},50); +} +}; +Xinha.prototype.setMode=function(_d1){ +var _d2; +if(typeof _d1=="undefined"){ +_d1=this._editMode=="textmode"?"wysiwyg":"textmode"; +} +switch(_d1){ +case "textmode": +this.setCC("iframe"); +_d2=this.outwardHtml(this.getHTML()); +this.setHTML(_d2); +this.deactivateEditor(); +this._iframe.style.display="none"; +this._textArea.style.display=""; +if(this.config.statusBar){ +this._statusBarTree.style.display="none"; +this._statusBarTextMode.style.display=""; +} +this.notifyOf("modechange",{"mode":"text"}); +this.findCC("textarea"); +break; +case "wysiwyg": +this.setCC("textarea"); +_d2=this.inwardHtml(this.getHTML()); +this.deactivateEditor(); +this.setHTML(_d2); +this._iframe.style.display=""; +this._textArea.style.display="none"; +this.activateEditor(); +if(this.config.statusBar){ +this._statusBarTree.style.display=""; +this._statusBarTextMode.style.display="none"; +} +this.notifyOf("modechange",{"mode":"wysiwyg"}); +this.findCC("iframe"); +break; +default: +alert("Mode <"+_d1+"> not defined!"); +return false; +} +this._editMode=_d1; +for(var i in this.plugins){ +var _d4=this.plugins[i].instance; +if(_d4&&typeof _d4.onMode=="function"){ +_d4.onMode(_d1); +} +} +}; +Xinha.prototype.setFullHTML=function(_d5){ +var _d6=RegExp.multiline; +RegExp.multiline=true; +if(_d5.match(Xinha.RE_doctype)){ +this.setDoctype(RegExp.$1); +} +RegExp.multiline=_d6; +if(0){ +if(_d5.match(Xinha.RE_head)){ +this._doc.getElementsByTagName("head")[0].innerHTML=RegExp.$1; +} +if(_d5.match(Xinha.RE_body)){ +this._doc.getElementsByTagName("body")[0].innerHTML=RegExp.$1; +} +}else{ +var _d7=this.editorIsActivated(); +if(_d7){ +this.deactivateEditor(); +} +var _d8=/((.|\n)*?)<\/html>/i; +_d5=_d5.replace(_d8,"$1"); +this._doc.open("text/html","replace"); +this._doc.write(_d5); +this._doc.close(); +if(_d7){ +this.activateEditor(); +} +this.setEditorEvents(); +return true; +} +}; +Xinha.prototype.setEditorEvents=function(){ +var _d9=this; +var doc=this._doc; +_d9.whenDocReady(function(){ +Xinha._addEvents(doc,["mousedown"],function(){ +_d9.activateEditor(); +return true; +}); +Xinha._addEvents(doc,["keydown","keypress","mousedown","mouseup","drag"],function(_db){ +return _d9._editorEvent(Xinha.is_ie?_d9._iframe.contentWindow.event:_db); +}); +for(var i in _d9.plugins){ +var _dd=_d9.plugins[i].instance; +Xinha.refreshPlugin(_dd); +} +if(typeof _d9._onGenerate=="function"){ +_d9._onGenerate(); +} +Xinha.addDom0Event(window,"resize",function(e){ +_d9.sizeEditor(); +}); +_d9.removeLoadingMessage(); +}); +}; +Xinha.prototype.registerPlugin=function(){ +if(!Xinha.isSupportedBrowser){ +return; +} +var _df=arguments[0]; +if(_df===null||typeof _df=="undefined"||(typeof _df=="string"&&eval("typeof "+_df)=="undefined")){ +return false; +} +var _e0=[]; +for(var i=1;i=0;){ +ta.value+=" "; +} +ta.value+=str+"\n"; +} +function _dt(root,_107){ +var tag=root.tagName.toLowerCase(),i; +var ns=Xinha.is_ie?root.scopeName:root.prefix; +debug(_107,"- "+tag+" ["+ns+"]"); +for(i=root.firstChild;i;i=i.nextSibling){ +if(i.nodeType==1){ +_dt(i,_107+2); +} +} +} +_dt(this._doc.body,0); +document.body.appendChild(ta); +}; +Xinha.getInnerText=function(el){ +var txt="",i; +for(i=el.firstChild;i;i=i.nextSibling){ +if(i.nodeType==3){ +txt+=i.data; +}else{ +if(i.nodeType==1){ +txt+=Xinha.getInnerText(i); +} +} +} +return txt; +}; +Xinha.prototype._wordClean=function(){ +var _10c=this; +var _10d={empty_tags:0,mso_class:0,mso_style:0,mso_xmlel:0,orig_len:this._doc.body.innerHTML.length,T:(new Date()).getTime()}; +var _10e={empty_tags:"Empty tags removed: ",mso_class:"MSO class names removed: ",mso_style:"MSO inline style removed: ",mso_xmlel:"MSO XML elements stripped: "}; +function showStats(){ +var txt="Xinha word cleaner stats: \n\n"; +for(var i in _10d){ +if(_10e[i]){ +txt+=_10e[i]+_10d[i]+"\n"; +} +} +txt+="\nInitial document length: "+_10d.orig_len+"\n"; +txt+="Final document length: "+_10c._doc.body.innerHTML.length+"\n"; +txt+="Clean-up took "+(((new Date()).getTime()-_10d.T)/1000)+" seconds"; +alert(txt); +} +function clearClass(node){ +var newc=node.className.replace(/(^|\s)mso.*?(\s|$)/ig," "); +if(newc!=node.className){ +node.className=newc; +if(!(/\S/.test(node.className))){ +node.removeAttribute("className"); +++_10d.mso_class; +} +} +} +function clearStyle(node){ +var _114=node.style.cssText.split(/\s*;\s*/); +for(var i=_114.length;--i>=0;){ +if((/^mso|^tab-stops/i.test(_114[i]))||(/^margin\s*:\s*0..\s+0..\s+0../i.test(_114[i]))){ +++_10d.mso_style; +_114.splice(i,1); +} +} +node.style.cssText=_114.join("; "); +} +var _116=null; +if(Xinha.is_ie){ +_116=function(el){ +el.outerHTML=Xinha.htmlEncode(el.innerText); +++_10d.mso_xmlel; +}; +}else{ +_116=function(el){ +var txt=document.createTextNode(Xinha.getInnerText(el)); +el.parentNode.insertBefore(txt,el); +Xinha.removeFromParent(el); +++_10d.mso_xmlel; +}; +} +function checkEmpty(el){ +if(/^(span|b|strong|i|em|font|div|p)$/i.test(el.tagName)&&!el.firstChild){ +Xinha.removeFromParent(el); +++_10d.empty_tags; +} +} +function parseTree(root){ +var tag=root.tagName.toLowerCase(),i,next; +if((Xinha.is_ie&&root.scopeName!="HTML")||(!Xinha.is_ie&&(/:/.test(tag)))){ +_116(root); +return false; +}else{ +clearClass(root); +clearStyle(root); +for(i=root.firstChild;i;i=next){ +next=i.nextSibling; +if(i.nodeType==1&&parseTree(i)){ +checkEmpty(i); +} +} +} +return true; +} +parseTree(this._doc.body); +this.updateToolbar(); +}; +Xinha.prototype._clearFonts=function(){ +var D=this.getInnerHTML(); +if(confirm(Xinha._lc("Would you like to clear font typefaces?"))){ +D=D.replace(/face="[^"]*"/gi,""); +D=D.replace(/font-family:[^;}"']+;?/gi,""); +} +if(confirm(Xinha._lc("Would you like to clear font sizes?"))){ +D=D.replace(/size="[^"]*"/gi,""); +D=D.replace(/font-size:[^;}"']+;?/gi,""); +} +if(confirm(Xinha._lc("Would you like to clear font colours?"))){ +D=D.replace(/color="[^"]*"/gi,""); +D=D.replace(/([^-])color:[^;}"']+;?/gi,"$1"); +} +D=D.replace(/(style|class)="\s*"/gi,""); +D=D.replace(/<(font|span)\s*>/gi,""); +this.setHTML(D); +this.updateToolbar(); +}; +Xinha.prototype._splitBlock=function(){ +this._doc.execCommand("formatblock",false,"div"); +}; +Xinha.prototype.forceRedraw=function(){ +this._doc.body.style.visibility="hidden"; +this._doc.body.style.visibility=""; +}; +Xinha.prototype.focusEditor=function(){ +switch(this._editMode){ +case "wysiwyg": +try{ +if(Xinha._someEditorHasBeenActivated){ +this.activateEditor(); +this._iframe.contentWindow.focus(); +} +} +catch(ex){ +} +break; +case "textmode": +try{ +this._textArea.focus(); +} +catch(e){ +} +break; +default: +alert("ERROR: mode "+this._editMode+" is not defined"); +} +return this._doc; +}; +Xinha.prototype._undoTakeSnapshot=function(){ +++this._undoPos; +if(this._undoPos>=this.config.undoSteps){ +this._undoQueue.shift(); +--this._undoPos; +} +var take=true; +var txt=this.getInnerHTML(); +if(this._undoPos>0){ +take=(this._undoQueue[this._undoPos-1]!=txt); +} +if(take){ +this._undoQueue[this._undoPos]=txt; +}else{ +this._undoPos--; +} +}; +Xinha.prototype.undo=function(){ +if(this._undoPos>0){ +var txt=this._undoQueue[--this._undoPos]; +if(txt){ +this.setHTML(txt); +}else{ +++this._undoPos; +} +} +}; +Xinha.prototype.redo=function(){ +if(this._undoPos=0;){ +var el=_128[i]; +if(!el){ +continue; +} +var a=document.createElement("a"); +a.href="javascript:void(0)"; +a.el=el; +a.editor=this; +this._statusBarItems.push(a); +Xinha.addDom0Event(a,"click",function(){ +this.blur(); +this.editor.selectNodeContents(this.el); +this.editor.updateToolbar(true); +return false; +}); +Xinha.addDom0Event(a,"contextmenu",function(){ +this.blur(); +var info="Inline style:\n\n"; +info+=this.el.style.cssText.split(/;\s*/).join(";\n"); +alert(info); +return false; +}); +var txt=el.tagName.toLowerCase(); +if(typeof el.style!="undefined"){ +a.title=el.style.cssText; +} +if(el.id){ +txt+="#"+el.id; +} +if(el.className){ +txt+="."+el.className; +} +a.appendChild(document.createTextNode(txt)); +this._statusBarTree.appendChild(a); +if(i!==0){ +this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(187))); +} +Xinha.freeLater(a); +} +} +} +for(var cmd in this._toolbarObjects){ +var btn=this._toolbarObjects[cmd]; +var _131=true; +if(typeof (btn.state)!="function"){ +continue; +} +if(btn.context&&!text){ +_131=false; +var _132=btn.context; +var _133=[]; +if(/(.*)\[(.*?)\]/.test(_132)){ +_132=RegExp.$1; +_133=RegExp.$2.split(","); +} +_132=_132.toLowerCase(); +var _134=(_132=="*"); +for(var k=0;k<_128.length;++k){ +if(!_128[k]){ +continue; +} +if(_134||(_128[k].tagName.toLowerCase()==_132)){ +_131=true; +var _136=null; +var att=null; +var comp=null; +var _139=null; +for(var ka=0;ka<_133.length;++ka){ +_136=_133[ka].match(/(.*)(==|!=|===|!==|>|>=|<|<=)(.*)/); +att=_136[1]; +comp=_136[2]; +_139=_136[3]; +if(!eval(_128[k][att]+comp+_139)){ +_131=false; +break; +} +} +if(_131){ +break; +} +} +} +} +btn.state("enabled",(!text||btn.text)&&_131); +if(typeof cmd=="function"){ +continue; +} +var _13b=this.config.customSelects[cmd]; +if((!text||btn.text)&&(typeof _13b!="undefined")){ +_13b.refresh(this); +continue; +} +switch(cmd){ +case "fontname": +case "fontsize": +if(!text){ +try{ +var _13c=(""+doc.queryCommandValue(cmd)).toLowerCase(); +if(!_13c){ +btn.element.selectedIndex=0; +break; +} +var _13d=this.config[cmd]; +var _13e=0; +for(var j in _13d){ +if((j.toLowerCase()==_13c)||(_13d[j].substr(0,_13c.length).toLowerCase()==_13c)){ +btn.element.selectedIndex=_13e; +throw "ok"; +} +++_13e; +} +btn.element.selectedIndex=0; +} +catch(ex){ +} +} +break; +case "formatblock": +var _140=[]; +for(var _141 in this.config.formatblock){ +if(typeof this.config.formatblock[_141]=="string"){ +_140[_140.length]=this.config.formatblock[_141]; +} +} +var _142=this._getFirstAncestor(this.getSelection(),_140); +if(_142){ +for(var x=0;x<_140.length;x++){ +if(_140[x].toLowerCase()==_142.tagName.toLowerCase()){ +btn.element.selectedIndex=x; +} +} +}else{ +btn.element.selectedIndex=0; +} +break; +case "textindicator": +if(!text){ +try{ +var _144=btn.element.style; +_144.backgroundColor=Xinha._makeColor(doc.queryCommandValue(Xinha.is_ie?"backcolor":"hilitecolor")); +if(/transparent/i.test(_144.backgroundColor)){ +_144.backgroundColor=Xinha._makeColor(doc.queryCommandValue("backcolor")); +} +_144.color=Xinha._makeColor(doc.queryCommandValue("forecolor")); +_144.fontFamily=doc.queryCommandValue("fontname"); +_144.fontWeight=doc.queryCommandState("bold")?"bold":"normal"; +_144.fontStyle=doc.queryCommandState("italic")?"italic":"normal"; +} +catch(ex){ +} +} +break; +case "htmlmode": +btn.state("active",text); +break; +case "lefttoright": +case "righttoleft": +var _145=this.getParentElement(); +while(_145&&!Xinha.isBlockElement(_145)){ +_145=_145.parentNode; +} +if(_145){ +btn.state("active",(_145.style.direction==((cmd=="righttoleft")?"rtl":"ltr"))); +} +break; +default: +cmd=cmd.replace(/(un)?orderedlist/i,"insert$1orderedlist"); +try{ +btn.state("active",(!text&&doc.queryCommandState(cmd))); +} +catch(ex){ +} +break; +} +} +if(this._customUndo&&!this._timerUndo){ +this._undoTakeSnapshot(); +var _146=this; +this._timerUndo=setTimeout(function(){ +_146._timerUndo=null; +},this.config.undoTimeout); +} +if(0&&Xinha.is_gecko){ +var s=this.getSelection(); +if(s&&s.isCollapsed&&s.anchorNode&&s.anchorNode.parentNode.tagName.toLowerCase()!="body"&&s.anchorNode.nodeType==3&&s.anchorOffset==s.anchorNode.length&&!(s.anchorNode.parentNode.nextSibling&&s.anchorNode.parentNode.nextSibling.nodeType==3)&&!Xinha.isBlockElement(s.anchorNode.parentNode)){ +try{ +s.anchorNode.parentNode.parentNode.insertBefore(this._doc.createTextNode("\t"),s.anchorNode.parentNode.nextSibling); +} +catch(ex){ +} +} +} +for(var _148 in this.plugins){ +var _149=this.plugins[_148].instance; +if(_149&&typeof _149.onUpdateToolbar=="function"){ +_149.onUpdateToolbar(); +} +} +}; +Xinha.prototype.getAllAncestors=function(){ +var p=this.getParentElement(); +var a=[]; +while(p&&(p.nodeType==1)&&(p.tagName.toLowerCase()!="body")){ +a.push(p); +p=p.parentNode; +} +a.push(this._doc.body); +return a; +}; +Xinha.prototype._getFirstAncestor=function(sel,_14d){ +var prnt=this.activeElement(sel); +if(prnt===null){ +try{ +prnt=(Xinha.is_ie?this.createRange(sel).parentElement():this.createRange(sel).commonAncestorContainer); +} +catch(ex){ +return null; +} +} +if(typeof _14d=="string"){ +_14d=[_14d]; +} +while(prnt){ +if(prnt.nodeType==1){ +if(_14d===null){ +return prnt; +} +if(_14d.contains(prnt.tagName.toLowerCase())){ +return prnt; +} +if(prnt.tagName.toLowerCase()=="body"){ +break; +} +if(prnt.tagName.toLowerCase()=="table"){ +break; +} +} +prnt=prnt.parentNode; +} +return null; +}; +Xinha.prototype._getAncestorBlock=function(sel){ +var prnt=(Xinha.is_ie?this.createRange(sel).parentElement:this.createRange(sel).commonAncestorContainer); +while(prnt&&(prnt.nodeType==1)){ +switch(prnt.tagName.toLowerCase()){ +case "div": +case "p": +case "address": +case "blockquote": +case "center": +case "del": +case "ins": +case "pre": +case "h1": +case "h2": +case "h3": +case "h4": +case "h5": +case "h6": +case "h7": +return prnt; +case "body": +case "noframes": +case "dd": +case "li": +case "th": +case "td": +case "noscript": +return null; +default: +break; +} +} +return null; +}; +Xinha.prototype._createImplicitBlock=function(type){ +var sel=this.getSelection(); +if(Xinha.is_ie){ +sel.empty(); +}else{ +sel.collapseToStart(); +} +var rng=this.createRange(sel); +}; +Xinha.prototype.surroundHTML=function(_154,_155){ +var html=this.getSelectedHTML(); +this.insertHTML(_154+html+_155); +}; +Xinha.prototype.hasSelectedText=function(){ +return this.getSelectedHTML()!==""; +}; +Xinha.prototype._comboSelected=function(el,txt){ +this.focusEditor(); +var _159=el.options[el.selectedIndex].value; +switch(txt){ +case "fontname": +case "fontsize": +this.execCommand(txt,false,_159); +break; +case "formatblock": +if(!_159){ +this.updateToolbar(); +break; +} +if(!Xinha.is_gecko||_159!=="blockquote"){ +_159="<"+_159+">"; +} +this.execCommand(txt,false,_159); +break; +default: +var _15a=this.config.customSelects[txt]; +if(typeof _15a!="undefined"){ +_15a.action(this); +}else{ +alert("FIXME: combo box "+txt+" not implemented"); +} +break; +} +}; +Xinha.prototype._colorSelector=function(_15b){ +var _15c=this; +if(Xinha.is_gecko){ +try{ +_15c._doc.execCommand("useCSS",false,false); +_15c._doc.execCommand("styleWithCSS",false,true); +} +catch(ex){ +} +} +var btn=_15c._toolbarObjects[_15b].element; +var _15e; +if(_15b=="hilitecolor"){ +if(Xinha.is_ie){ +_15b="backcolor"; +_15e=Xinha._colorToRgb(_15c._doc.queryCommandValue("backcolor")); +}else{ +_15e=Xinha._colorToRgb(_15c._doc.queryCommandValue("hilitecolor")); +} +}else{ +_15e=Xinha._colorToRgb(_15c._doc.queryCommandValue("forecolor")); +} +var _15f=function(_160){ +_15c._doc.execCommand(_15b,false,_160); +}; +if(Xinha.is_ie){ +var _161=_15c.createRange(_15c.getSelection()); +_15f=function(_162){ +_161.select(); +_15c._doc.execCommand(_15b,false,_162); +}; +} +var _163=new Xinha.colorPicker({cellsize:_15c.config.colorPickerCellSize,callback:_15f,granularity:_15c.config.colorPickerGranularity,websafe:_15c.config.colorPickerWebSafe,savecolors:_15c.config.colorPickerSaveColors}); +_163.open(_15c.config.colorPickerPosition,btn,_15e); +}; +Xinha.prototype.execCommand=function(_164,UI,_166){ +var _167=this; +this.focusEditor(); +_164=_164.toLowerCase(); +if(this.firePluginEvent("onExecCommand",_164,UI,_166)){ +this.updateToolbar(); +return false; +} +switch(_164){ +case "htmlmode": +this.setMode(); +break; +case "hilitecolor": +case "forecolor": +this._colorSelector(_164); +break; +case "createlink": +this._createLink(); +break; +case "undo": +case "redo": +if(this._customUndo){ +this[_164](); +}else{ +this._doc.execCommand(_164,UI,_166); +} +break; +case "inserttable": +this._insertTable(); +break; +case "insertimage": +this._insertImage(); +break; +case "about": +this._popupDialog(_167.config.URIs.about,null,this); +break; +case "showhelp": +this._popupDialog(_167.config.URIs.help,null,this); +break; +case "killword": +this._wordClean(); +break; +case "cut": +case "copy": +case "paste": +this._doc.execCommand(_164,UI,_166); +if(this.config.killWordOnPaste){ +this._wordClean(); +} +break; +case "lefttoright": +case "righttoleft": +if(this.config.changeJustifyWithDirection){ +this._doc.execCommand((_164=="righttoleft")?"justifyright":"justifyleft",UI,_166); +} +var dir=(_164=="righttoleft")?"rtl":"ltr"; +var el=this.getParentElement(); +while(el&&!Xinha.isBlockElement(el)){ +el=el.parentNode; +} +if(el){ +if(el.style.direction==dir){ +el.style.direction=""; +}else{ +el.style.direction=dir; +} +} +break; +case "justifyleft": +case "justifyright": +_164.match(/^justify(.*)$/); +var ae=this.activeElement(this.getSelection()); +if(ae&&ae.tagName.toLowerCase()=="img"){ +ae.align=ae.align==RegExp.$1?"":RegExp.$1; +}else{ +this._doc.execCommand(_164,UI,_166); +} +break; +default: +try{ +this._doc.execCommand(_164,UI,_166); +} +catch(ex){ +if(this.config.debug){ +alert(ex+"\n\nby execCommand("+_164+");"); +} +} +break; +} +this.updateToolbar(); +return false; +}; +Xinha.prototype._editorEvent=function(ev){ +var _16c=this; +if(typeof _16c._textArea["on"+ev.type]=="function"){ +_16c._textArea["on"+ev.type](); +} +if(this.isKeyEvent(ev)){ +if(_16c.firePluginEvent("onKeyPress",ev)){ +return false; +} +if(this.isShortCut(ev)){ +this._shortCuts(ev); +} +} +if(ev.type=="mousedown"){ +if(_16c.firePluginEvent("onMouseDown",ev)){ +return false; +} +} +if(_16c._timerToolbar){ +clearTimeout(_16c._timerToolbar); +} +_16c._timerToolbar=setTimeout(function(){ +_16c.updateToolbar(); +_16c._timerToolbar=null; +},250); +}; +Xinha.prototype._shortCuts=function(ev){ +var key=this.getKey(ev).toLowerCase(); +var cmd=null; +var _170=null; +switch(key){ +case "b": +cmd="bold"; +break; +case "i": +cmd="italic"; +break; +case "u": +cmd="underline"; +break; +case "s": +cmd="strikethrough"; +break; +case "l": +cmd="justifyleft"; +break; +case "e": +cmd="justifycenter"; +break; +case "r": +cmd="justifyright"; +break; +case "j": +cmd="justifyfull"; +break; +case "z": +cmd="undo"; +break; +case "y": +cmd="redo"; +break; +case "v": +cmd="paste"; +break; +case "n": +cmd="formatblock"; +_170="p"; +break; +case "0": +cmd="killword"; +break; +case "1": +case "2": +case "3": +case "4": +case "5": +case "6": +cmd="formatblock"; +_170="h"+key; +break; +} +if(cmd){ +this.execCommand(cmd,false,_170); +Xinha._stopEvent(ev); +} +}; +Xinha.prototype.convertNode=function(el,_172){ +var _173=this._doc.createElement(_172); +while(el.firstChild){ +_173.appendChild(el.firstChild); +} +return _173; +}; +Xinha.prototype.scrollToElement=function(e){ +if(!e){ +e=this.getParentElement(); +if(!e){ +return; +} +} +var _175=Xinha.getElementTopLeft(e); +this._iframe.contentWindow.scrollTo(_175.left,_175.top); +}; +Xinha.prototype.getEditorContent=function(){ +return this.outwardHtml(this.getHTML()); +}; +Xinha.prototype.setEditorContent=function(html){ +this.setHTML(this.inwardHtml(html)); +}; +Xinha.prototype.getHTML=function(){ +var html=""; +switch(this._editMode){ +case "wysiwyg": +if(!this.config.fullPage){ +html=Xinha.getHTML(this._doc.body,false,this).trim(); +}else{ +html=this.doctype+"\n"+Xinha.getHTML(this._doc.documentElement,true,this); +} +break; +case "textmode": +html=this._textArea.value; +break; +default: +alert("Mode <"+this._editMode+"> not defined!"); +return false; +} +return html; +}; +Xinha.prototype.outwardHtml=function(html){ +for(var i in this.plugins){ +var _17a=this.plugins[i].instance; +if(_17a&&typeof _17a.outwardHtml=="function"){ +html=_17a.outwardHtml(html); +} +} +html=html.replace(/<(\/?)b(\s|>|\/)/ig,"<$1strong$2"); +html=html.replace(/<(\/?)i(\s|>|\/)/ig,"<$1em$2"); +html=html.replace(/<(\/?)strike(\s|>|\/)/ig,"<$1del$2"); +html=html.replace(/(<[^>]*onclick=['"])if\(window\.top && window\.top\.Xinha\)\{return false\}/gi,"$1"); +html=html.replace(/(<[^>]*onmouseover=['"])if\(window\.top && window\.top\.Xinha\)\{return false\}/gi,"$1"); +html=html.replace(/(<[^>]*onmouseout=['"])if\(window\.top && window\.top\.Xinha\)\{return false\}/gi,"$1"); +html=html.replace(/(<[^>]*onmousedown=['"])if\(window\.top && window\.top\.Xinha\)\{return false\}/gi,"$1"); +html=html.replace(/(<[^>]*onmouseup=['"])if\(window\.top && window\.top\.Xinha\)\{return false\}/gi,"$1"); +var _17b=location.href.replace(/(https?:\/\/[^\/]*)\/.*/,"$1")+"/"; +html=html.replace(/https?:\/\/null\//g,_17b); +html=html.replace(/((href|src|background)=[\'\"])\/+/ig,"$1"+_17b); +html=this.outwardSpecialReplacements(html); +html=this.fixRelativeLinks(html); +if(this.config.sevenBitClean){ +html=html.replace(/[^ -~\r\n\t]/g,function(c){ +return "&#"+c.charCodeAt(0)+";"; +}); +} +html=html.replace(/(]*)(freezescript)/gi,"$1javascript"); +if(this.config.fullPage){ +html=Xinha.stripCoreCSS(html); +} +return html; +}; +Xinha.prototype.inwardHtml=function(html){ +for(var i in this.plugins){ +var _17f=this.plugins[i].instance; +if(_17f&&typeof _17f.inwardHtml=="function"){ +html=_17f.inwardHtml(html); +} +} +html=html.replace(/<(\/?)del(\s|>|\/)/ig,"<$1strike$2"); +html=html.replace(/(<[^>]*onclick=["'])/gi,"$1if(window.top && window.top.Xinha){return false}"); +html=html.replace(/(<[^>]*onmouseover=["'])/gi,"$1if(window.top && window.top.Xinha){return false}"); +html=html.replace(/(<[^>]*onmouseout=["'])/gi,"$1if(window.top && window.top.Xinha){return false}"); +html=html.replace(/(<[^>]*onmouseodown=["'])/gi,"$1if(window.top && window.top.Xinha){return false}"); +html=html.replace(/(<[^>]*onmouseup=["'])/gi,"$1if(window.top && window.top.Xinha){return false}"); +html=this.inwardSpecialReplacements(html); +html=html.replace(/(]*)(javascript)/gi,"$1freezescript"); +var _180=new RegExp("((href|src|background)=['\"])/+","gi"); +html=html.replace(_180,"$1"+location.href.replace(/(https?:\/\/[^\/]*)\/.*/,"$1")+"/"); +html=this.fixRelativeLinks(html); +if(this.config.fullPage){ +html=Xinha.addCoreCSS(html); +} +return html; +}; +Xinha.prototype.outwardSpecialReplacements=function(html){ +for(var i in this.config.specialReplacements){ +var from=this.config.specialReplacements[i]; +var to=i; +if(typeof from.replace!="function"||typeof to.replace!="function"){ +continue; +} +var reg=new RegExp(Xinha.escapeStringForRegExp(from),"g"); +html=html.replace(reg,to.replace(/\$/g,"$$$$")); +} +return html; +}; +Xinha.prototype.inwardSpecialReplacements=function(html){ +for(var i in this.config.specialReplacements){ +var from=i; +var to=this.config.specialReplacements[i]; +if(typeof from.replace!="function"||typeof to.replace!="function"){ +continue; +} +var reg=new RegExp(Xinha.escapeStringForRegExp(from),"g"); +html=html.replace(reg,to.replace(/\$/g,"$$$$")); +} +return html; +}; +Xinha.prototype.fixRelativeLinks=function(html){ +if(typeof this.config.expandRelativeUrl!="undefined"&&this.config.expandRelativeUrl){ +var src=html.match(/(src|href)="([^"]*)"/gi); +} +var b=document.location.href; +if(src){ +var url,url_m,relPath,base_m,absPath; +for(var i=0;i not defined!"); +return false; +} +return html; +}; +Xinha.prototype.setHTML=function(html){ +if(!this.config.fullPage){ +this._doc.body.innerHTML=html; +}else{ +this.setFullHTML(html); +} +this._textArea.value=html; +}; +Xinha.prototype.setDoctype=function(_194){ +this.doctype=_194; +}; +Xinha._object=null; +Xinha.cloneObject=function(obj){ +if(!obj){ +return null; +} +var _196={}; +if(obj.constructor.toString().match(/\s*function Array\(/)){ +_196=obj.constructor(); +} +if(obj.constructor.toString().match(/\s*function Function\(/)){ +_196=obj; +}else{ +for(var n in obj){ +var node=obj[n]; +if(typeof node=="object"){ +_196[n]=Xinha.cloneObject(node); +}else{ +_196[n]=node; +} +} +} +return _196; +}; +Xinha.flushEvents=function(){ +var x=0; +var e=Xinha._eventFlushers.pop(); +while(e){ +try{ +if(e.length==3){ +Xinha._removeEvent(e[0],e[1],e[2]); +x++; +}else{ +if(e.length==2){ +e[0]["on"+e[1]]=null; +e[0]._xinha_dom0Events[e[1]]=null; +x++; +} +} +} +catch(ex){ +} +e=Xinha._eventFlushers.pop(); +} +}; +Xinha._eventFlushers=[]; +if(document.addEventListener){ +Xinha._addEvent=function(el,_19c,func){ +el.addEventListener(_19c,func,true); +Xinha._eventFlushers.push([el,_19c,func]); +}; +Xinha._removeEvent=function(el,_19f,func){ +el.removeEventListener(_19f,func,true); +}; +Xinha._stopEvent=function(ev){ +ev.preventDefault(); +ev.stopPropagation(); +}; +}else{ +if(document.attachEvent){ +Xinha._addEvent=function(el,_1a3,func){ +el.attachEvent("on"+_1a3,func); +Xinha._eventFlushers.push([el,_1a3,func]); +}; +Xinha._removeEvent=function(el,_1a6,func){ +el.detachEvent("on"+_1a6,func); +}; +Xinha._stopEvent=function(ev){ +try{ +ev.cancelBubble=true; +ev.returnValue=false; +} +catch(ex){ +} +}; +}else{ +Xinha._addEvent=function(el,_1aa,func){ +alert("_addEvent is not supported"); +}; +Xinha._removeEvent=function(el,_1ad,func){ +alert("_removeEvent is not supported"); +}; +Xinha._stopEvent=function(ev){ +alert("_stopEvent is not supported"); +}; +} +} +Xinha._addEvents=function(el,evs,func){ +for(var i=evs.length;--i>=0;){ +Xinha._addEvent(el,evs[i],func); +} +}; +Xinha._removeEvents=function(el,evs,func){ +for(var i=evs.length;--i>=0;){ +Xinha._removeEvent(el,evs[i],func); +} +}; +Xinha.addDom0Event=function(el,ev,fn){ +Xinha._prepareForDom0Events(el,ev); +el._xinha_dom0Events[ev].unshift(fn); +}; +Xinha.prependDom0Event=function(el,ev,fn){ +Xinha._prepareForDom0Events(el,ev); +el._xinha_dom0Events[ev].push(fn); +}; +Xinha._prepareForDom0Events=function(el,ev){ +if(typeof el._xinha_dom0Events=="undefined"){ +el._xinha_dom0Events={}; +Xinha.freeLater(el,"_xinha_dom0Events"); +} +if(typeof el._xinha_dom0Events[ev]=="undefined"){ +el._xinha_dom0Events[ev]=[]; +if(typeof el["on"+ev]=="function"){ +el._xinha_dom0Events[ev].push(el["on"+ev]); +} +el["on"+ev]=function(_1c0){ +var a=el._xinha_dom0Events[ev]; +var _1c2=true; +for(var i=a.length;--i>=0;){ +el._xinha_tempEventHandler=a[i]; +if(el._xinha_tempEventHandler(_1c0)===false){ +el._xinha_tempEventHandler=null; +_1c2=false; +break; +} +el._xinha_tempEventHandler=null; +} +return _1c2; +}; +Xinha._eventFlushers.push([el,ev]); +} +}; +Xinha.prototype.notifyOn=function(ev,fn){ +if(typeof this._notifyListeners[ev]=="undefined"){ +this._notifyListeners[ev]=[]; +Xinha.freeLater(this,"_notifyListeners"); +} +this._notifyListeners[ev].push(fn); +}; +Xinha.prototype.notifyOf=function(ev,args){ +if(this._notifyListeners[ev]){ +for(var i=0;i/ig,">"); +str=str.replace(/\xA0/g," "); +str=str.replace(/\x22/g,"""); +return str; +}; +Xinha.prototype.stripBaseURL=function(_1cd){ +if(this.config.baseHref===null||!this.config.stripBaseHref){ +return _1cd; +} +var _1ce=this.config.baseHref.replace(/^(https?:\/\/[^\/]+)(.*)$/,"$1"); +var _1cf=new RegExp(_1ce); +return _1cd.replace(_1cf,""); +}; +String.prototype.trim=function(){ +return this.replace(/^\s+/,"").replace(/\s+$/,""); +}; +Xinha._makeColor=function(v){ +if(typeof v!="number"){ +return v; +} +var r=v&255; +var g=(v>>8)&255; +var b=(v>>16)&255; +return "rgb("+r+","+g+","+b+")"; +}; +Xinha._colorToRgb=function(v){ +if(!v){ +return ""; +} +var r,g,b; +function hex(d){ +return (d<16)?("0"+d.toString(16)):d.toString(16); +} +if(typeof v=="number"){ +r=v&255; +g=(v>>8)&255; +b=(v>>16)&255; +return "#"+hex(r)+hex(g)+hex(b); +} +if(v.substr(0,3)=="rgb"){ +var re=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/; +if(v.match(re)){ +r=parseInt(RegExp.$1,10); +g=parseInt(RegExp.$2,10); +b=parseInt(RegExp.$3,10); +return "#"+hex(r)+hex(g)+hex(b); +} +return null; +} +if(v.substr(0,1)=="#"){ +return v; +} +return null; +}; +Xinha.prototype._popupDialog=function(url,_1d9,init){ +Dialog(this.popupURL(url),_1d9,init); +}; +Xinha.prototype.imgURL=function(file,_1dc){ +if(typeof _1dc=="undefined"){ +return _editor_url+file; +}else{ +return _editor_url+"plugins/"+_1dc+"/img/"+file; +} +}; +Xinha.prototype.popupURL=function(file){ +var url=""; +if(file.match(/^plugin:\/\/(.*?)\/(.*)/)){ +var _1df=RegExp.$1; +var _1e0=RegExp.$2; +if(!(/\.html$/.test(_1e0))){ +_1e0+=".html"; +} +url=_editor_url+"plugins/"+_1df+"/popups/"+_1e0; +}else{ +if(file.match(/^\/.*?/)){ +url=file; +}else{ +url=_editor_url+this.config.popupURL+file; +} +} +return url; +}; +Xinha.getElementById=function(tag,id){ +var el,i,objs=document.getElementsByTagName(tag); +for(i=objs.length;--i>=0&&(el=objs[i]);){ +if(el.id==id){ +return el; +} +} +return null; +}; +Xinha.prototype._toggleBorders=function(){ +var _1e4=this._doc.getElementsByTagName("TABLE"); +if(_1e4.length!==0){ +if(!this.borders){ +this.borders=true; +}else{ +this.borders=false; +} +for(var i=0;i<_1e4.length;i++){ +if(this.borders){ +Xinha._addClass(_1e4[i],"htmtableborders"); +}else{ +Xinha._removeClass(_1e4[i],"htmtableborders"); +} +} +} +return true; +}; +Xinha.addCoreCSS=function(html){ +var _1e7="\n"; +if(html&&//i.test(html)){ +return html.replace(//i,""+_1e7); +}else{ +if(html){ +return _1e7+html; +}else{ +return _1e7; +} +} +}; +Xinha.stripCoreCSS=function(html){ +return html.replace(/]+title="Xinha Internal CSS"(.|\n)*?<\/style>/i,""); +}; +Xinha._removeClass=function(el,_1ea){ +if(!(el&&el.className)){ +return; +} +var cls=el.className.split(" "); +var ar=[]; +for(var i=cls.length;i>0;){ +if(cls[--i]!=_1ea){ +ar[ar.length]=cls[i]; +} +} +el.className=ar.join(" "); +}; +Xinha._addClass=function(el,_1ef){ +Xinha._removeClass(el,_1ef); +el.className+=" "+_1ef; +}; +Xinha.addClasses=function(el,_1f1){ +if(el!==null){ +var _1f2=el.className.trim().split(" "); +var ours=_1f1.split(" "); +for(var x=0;x0;){ +if(cls[--i]==_200){ +return true; +} +} +return false; +}; +Xinha._postback=function(url,data,_205){ +var req=null; +req=Xinha.getXMLHTTPRequestObject(); +var _207=""; +if(typeof data=="string"){ +_207=data; +}else{ +if(typeof data=="object"){ +for(var i in data){ +_207+=(_207.length?"&":"")+i+"="+encodeURIComponent(data[i]); +} +} +} +function callBack(){ +if(req.readyState==4){ +if(req.status==200||Xinha.isRunLocally&&req.status==0){ +if(typeof _205=="function"){ +_205(req.responseText,req); +} +}else{ +alert("An error has occurred: "+req.statusText+"\nURL: "+url); +} +} +} +req.onreadystatechange=callBack; +req.open("POST",url,true); +req.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"); +req.send(_207); +}; +Xinha._getback=function(url,_20a){ +var req=null; +req=Xinha.getXMLHTTPRequestObject(); +function callBack(){ +if(req.readyState==4){ +if(req.status==200||Xinha.isRunLocally&&req.status==0){ +_20a(req.responseText,req); +}else{ +alert("An error has occurred: "+req.statusText+"\nURL: "+url); +} +} +} +req.onreadystatechange=callBack; +req.open("GET",url,true); +req.send(null); +}; +Xinha._geturlcontent=function(url){ +var req=null; +req=Xinha.getXMLHTTPRequestObject(); +req.open("GET",url,false); +req.send(null); +if(req.status==200||Xinha.isRunLocally&&req.status==0){ +return req.responseText; +}else{ +return ""; +} +}; +if(typeof dump=="undefined"){ +function dump(o){ +var s=""; +for(var prop in o){ +s+=prop+" = "+o[prop]+"\n"; +} +var x=window.open("","debugger"); +x.document.write("
    "+s+"
    "); +} +} +if(!Array.prototype.contains){ +Array.prototype.contains=function(_212){ +var _213=this; +for(var i=0;i<_213.length;i++){ +if(_212==_213[i]){ +return true; +} +} +return false; +}; +} +if(!Array.prototype.indexOf){ +Array.prototype.indexOf=function(_215){ +var _216=this; +for(var i=0;i<_216.length;i++){ +if(_215==_216[i]){ +return i; +} +} +return null; +}; +} +if(!Array.prototype.append){ +Array.prototype.append=function(a){ +for(var i=0;i>2; +enc2=((chr1&3)<<4)|(chr2>>4); +enc3=((chr2&15)<<2)|(chr3>>6); +enc4=chr3&63; +if(isNaN(chr2)){ +enc3=enc4=64; +}else{ +if(isNaN(chr3)){ +enc4=64; +} +} +_24a=_24a+_249.charAt(enc1)+_249.charAt(enc2)+_249.charAt(enc3)+_249.charAt(enc4); +}while(i<_248.length); +return _24a; +}; +Xinha.base64_decode=function(_24e){ +var _24f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; +var _250=""; +var chr1,chr2,chr3; +var enc1,enc2,enc3,enc4; +var i=0; +_24e=_24e.replace(/[^A-Za-z0-9\+\/\=]/g,""); +do{ +enc1=_24f.indexOf(_24e.charAt(i++)); +enc2=_24f.indexOf(_24e.charAt(i++)); +enc3=_24f.indexOf(_24e.charAt(i++)); +enc4=_24f.indexOf(_24e.charAt(i++)); +chr1=(enc1<<2)|(enc2>>4); +chr2=((enc2&15)<<4)|(enc3>>2); +chr3=((enc3&3)<<6)|enc4; +_250=_250+String.fromCharCode(chr1); +if(enc3!=64){ +_250=_250+String.fromCharCode(chr2); +} +if(enc4!=64){ +_250=_250+String.fromCharCode(chr3); +} +}while(i<_24e.length); +return _250; +}; +Xinha.removeFromParent=function(el){ +if(!el.parentNode){ +return; +} +var pN=el.parentNode; +pN.removeChild(el); +return el; +}; +Xinha.hasParentNode=function(el){ +if(el.parentNode){ +if(el.parentNode.nodeType==11){ +return false; +} +return true; +} +return false; +}; +Xinha.viewportSize=function(_257){ +_257=(_257)?_257:window; +var x,y; +if(_257.innerHeight){ +x=_257.innerWidth; +y=_257.innerHeight; +}else{ +if(_257.document.documentElement&&_257.document.documentElement.clientHeight){ +x=_257.document.documentElement.clientWidth; +y=_257.document.documentElement.clientHeight; +}else{ +if(_257.document.body){ +x=_257.document.body.clientWidth; +y=_257.document.body.clientHeight; +} +} +} +return {"x":x,"y":y}; +}; +Xinha.pageSize=function(_259){ +_259=(_259)?_259:window; +var x,y; +var _25b=_259.document.body.scrollHeight; +var _25c=_259.document.documentElement.scrollHeight; +if(_25b>_25c){ +x=_259.document.body.scrollWidth; +y=_259.document.body.scrollHeight; +}else{ +x=_259.document.documentElement.scrollWidth; +y=_259.document.documentElement.scrollHeight; +} +return {"x":x,"y":y}; +}; +Xinha.prototype.scrollPos=function(_25d){ +_25d=(_25d)?_25d:window; +var x,y; +if(_25d.pageYOffset){ +x=_25d.pageXOffset; +y=_25d.pageYOffset; +}else{ +if(_25d.document.documentElement&&document.documentElement.scrollTop){ +x=_25d.document.documentElement.scrollLeft; +y=_25d.document.documentElement.scrollTop; +}else{ +if(_25d.document.body){ +x=_25d.document.body.scrollLeft; +y=_25d.document.body.scrollTop; +} +} +} +return {"x":x,"y":y}; +}; +Xinha.getElementTopLeft=function(_25f){ +var _260=curtop=0; +if(_25f.offsetParent){ +_260=_25f.offsetLeft; +curtop=_25f.offsetTop; +while(_25f=_25f.offsetParent){ +_260+=_25f.offsetLeft; +curtop+=_25f.offsetTop; +} +} +return {top:curtop,left:_260}; +}; +Xinha.findPosX=function(obj){ +var _262=0; +if(obj.offsetParent){ +return Xinha.getElementTopLeft(obj).left; +}else{ +if(obj.x){ +_262+=obj.x; +} +} +return _262; +}; +Xinha.findPosY=function(obj){ +var _264=0; +if(obj.offsetParent){ +return Xinha.getElementTopLeft(obj).top; +}else{ +if(obj.y){ +_264+=obj.y; +} +} +return _264; +}; +Xinha.createLoadingMessages=function(_265){ +if(Xinha.loadingMessages||!Xinha.isSupportedBrowser){ +return; +} +Xinha.loadingMessages=[]; +for(var i=0;i<_265.length;i++){ +Xinha.loadingMessages.push(Xinha.createLoadingMessage(Xinha.getElementById("textarea",_265[i]))); +} +}; +Xinha.createLoadingMessage=function(_267,text){ +if(document.getElementById("loading_"+_267.id)||!Xinha.isSupportedBrowser){ +return; +} +var _269=document.createElement("div"); +_269.id="loading_"+_267.id; +_269.className="loading"; +_269.style.left=Xinha.findPosX(_267)+"px"; +_269.style.top=(Xinha.findPosY(_267)+_267.offsetHeight/2)-50+"px"; +_269.style.width=_267.offsetWidth+"px"; +var _26a=document.createElement("div"); +_26a.className="loading_main"; +_26a.id="loading_main_"+_267.id; +_26a.appendChild(document.createTextNode(Xinha._lc("Loading in progress. Please wait!"))); +var _26b=document.createElement("div"); +_26b.className="loading_sub"; +_26b.id="loading_sub_"+_267.id; +text=text?text:Xinha._lc("Constructing object"); +_26b.appendChild(document.createTextNode(text)); +_269.appendChild(_26a); +_269.appendChild(_26b); +document.body.appendChild(_269); +Xinha.freeLater(_269); +Xinha.freeLater(_26a); +Xinha.freeLater(_26b); +return _26b; +}; +Xinha.prototype.setLoadingMessage=function(_26c,_26d){ +if(!document.getElementById("loading_sub_"+this._textArea.id)){ +return; +} +document.getElementById("loading_main_"+this._textArea.id).innerHTML=_26d?_26d:Xinha._lc("Loading in progress. Please wait!"); +document.getElementById("loading_sub_"+this._textArea.id).innerHTML=_26c; +}; +Xinha.setLoadingMessage=function(_26e){ +if(!Xinha.loadingMessages){ +return; +} +for(var i=0;i + * with (xinha_config.ImageManager) + * { + * '/home/your/directory', + * 'images_url' => '/directory' + * ) + * ) + * ?> + * } + * + * + */ + + function xinha_pass_to_php_backend($Data, $KeyLocation = 'Xinha:BackendKey') + { + + $bk = array(); + $bk['data'] = serialize($Data); + + @session_start(); + if(!isset($_SESSION[$KeyLocation])) + { + $_SESSION[$KeyLocation] = uniqid('Key_'); + } + + $bk['session_name'] = session_name(); + $bk['key_location'] = $KeyLocation; + $bk['hash'] = + function_exists('sha1') ? + sha1($_SESSION[$KeyLocation] . $bk['data']) + : md5($_SESSION[$KeyLocation] . $bk['data']); + + + // The data will be passed via a postback to the + // backend, we want to make sure these are going to come + // out from the PHP as an array like $bk above, so + // we need to adjust the keys. + $backend_data = array(); + foreach($bk as $k => $v) + { + $backend_data["backend_data[$k]"] = $v; + } + + // The session_start() above may have been after data was sent, so cookies + // wouldn't have worked. + $backend_data[session_name()] = session_id(); + + echo 'backend_data = ' . xinha_to_js($backend_data) . "; \n"; + + } + + /** Convert PHP data structure to Javascript */ + + function xinha_to_js($var, $tabs = 0) + { + if(is_numeric($var)) + { + return $var; + } + + if(is_string($var)) + { + return "'" . xinha_js_encode($var) . "'"; + } + + if(is_array($var)) + { + $useObject = false; + foreach(array_keys($var) as $k) { + if(!is_numeric($k)) $useObject = true; + } + $js = array(); + foreach($var as $k => $v) + { + $i = ""; + if($useObject) { + if(preg_match('#^[a-zA-Z]+[a-zA-Z0-9]*$#', $k)) { + $i .= "$k: "; + } else { + $i .= "'$k': "; + } + } + $i .= xinha_to_js($v, $tabs + 1); + $js[] = $i; + } + if($useObject) { + $ret = "{\n" . xinha_tabify(implode(",\n", $js), $tabs) . "\n}"; + } else { + $ret = "[\n" . xinha_tabify(implode(",\n", $js), $tabs) . "\n]"; + } + return $ret; + } + + return 'null'; + } + + /** Like htmlspecialchars() except for javascript strings. */ + + function xinha_js_encode($string) + { + static $strings = "\\,\",',%,&,<,>,{,},@,\n,\r"; + + if(!is_array($strings)) + { + $tr = array(); + foreach(explode(',', $strings) as $chr) + { + $tr[$chr] = sprintf('\x%02X', ord($chr)); + } + $strings = $tr; + } + + return strtr($string, $strings); + } + + + /** Used by plugins to get the config passed via + * xinha_pass_to_backend() + * returns either the structure given, or NULL + * if none was passed or a security error was encountered. + */ + + function xinha_read_passed_data() + { + if(isset($_REQUEST['backend_data']) && is_array($_REQUEST['backend_data'])) + { + $bk = $_REQUEST['backend_data']; + session_name($bk['session_name']); + @session_start(); + if(!isset($_SESSION[$bk['key_location']])) return NULL; + + if($bk['hash'] === + function_exists('sha1') ? + sha1($_SESSION[$bk['key_location']] . $bk['data']) + : md5($_SESSION[$bk['key_location']] . $bk['data'])) + { + return unserialize(ini_get('magic_quotes_gpc') ? stripslashes($bk['data']) : $bk['data']); + } + } + + return NULL; + } + + /** Used by plugins to get a query string that can be sent to the backend + * (or another part of the backend) to send the same data. + */ + + function xinha_passed_data_querystring() + { + $qs = array(); + if(isset($_REQUEST['backend_data']) && is_array($_REQUEST['backend_data'])) + { + foreach($_REQUEST['backend_data'] as $k => $v) + { + $v = ini_get('magic_quotes_gpc') ? stripslashes($v) : $v; + $qs[] = "backend_data[" . rawurlencode($k) . "]=" . rawurlencode($v); + } + } + + $qs[] = session_name() . '=' . session_id(); + return implode('&', $qs); + } + + + /** Just space-tab indent some text */ + function xinha_tabify($text, $tabs) + { + if($text) + { + return str_repeat(" ", $tabs) . preg_replace('/\n(.)/', "\n" . str_repeat(" ", $tabs) . "\$1", $text); + } + } + + /** Return upload_max_filesize value from php.ini in kilobytes (function adapted from php.net)**/ + function upload_max_filesize_kb() + { + $val = ini_get('upload_max_filesize'); + $val = trim($val); + $last = strtolower($val{strlen($val)-1}); + switch($last) + { + // The 'G' modifier is available since PHP 5.1.0 + case 'g': + $val *= 1024; + case 'm': + $val *= 1024; + } + return $val; +} +?> \ No newline at end of file diff --git a/xinha/examples/Extended.html b/xinha/examples/Extended.html new file mode 100644 index 0000000..69aedda --- /dev/null +++ b/xinha/examples/Extended.html @@ -0,0 +1,299 @@ + + + + Settings + + + + + + + + +
    Settings
    +
    +
    Editor width:
    + +

    +

    Editor height:
    + +

    +

    Size includes bars
    + +

    +

    Status Bar
    + +

    +

    Mozilla Parameter Handler:
    + +
    +
    Undo steps:
    + +

    +

    Base href:
    + +

    +

    Strip base href
    + +

    +

    Strip self named anchors
    + +

    +

    only 7bit printables in URLs
    + +

    +

    7bit Clean
    + +

    +

    kill Word on paste
    + +

    +

    flow toolbars
    + +

    +

    show loading
    + +

    + +

    +
    +
    CharacterMap mode :
    + +
    +

    + +

    +
    +
    ListType mode :
    + +
    +

    + +

    +
    +
    CharCounter (showChar) :

    +
    CharCounter (showWord) :

    +
    CharCounter (showHtml) :
    +
    +

    + +

    + + +
    +
    + + diff --git a/xinha/examples/Newbie.html b/xinha/examples/Newbie.html new file mode 100644 index 0000000..e46f7ff --- /dev/null +++ b/xinha/examples/Newbie.html @@ -0,0 +1,22 @@ + + + + Xinha Newbie Guide + + + + + + + + +
    + +
    + + \ No newline at end of file diff --git a/xinha/examples/XinhaConfig.js b/xinha/examples/XinhaConfig.js new file mode 100644 index 0000000..0fcf8fa --- /dev/null +++ b/xinha/examples/XinhaConfig.js @@ -0,0 +1,17 @@ +xinha_editors=null; +xinha_init=null; +xinha_config=null; +xinha_plugins=null; +xinha_init=xinha_init?xinha_init:function(){ +xinha_editors=xinha_editors?xinha_editors:["myTextArea","anotherOne"]; +xinha_plugins=xinha_plugins?xinha_plugins:["CharacterMap","ContextMenu","ListType","Stylist","Linker","SuperClean","TableOperations"]; +if(!Xinha.loadPlugins(xinha_plugins,xinha_init)){ +return; +} +xinha_config=xinha_config?xinha_config():new Xinha.Config(); +xinha_config.pageStyleSheets=[_editor_url+"examples/full_example.css"]; +xinha_editors=Xinha.makeEditors(xinha_editors,xinha_config,xinha_plugins); +Xinha.startEditors(xinha_editors); +}; +Xinha._addEvent(window,"load",xinha_init); + diff --git a/xinha/examples/custom.css b/xinha/examples/custom.css new file mode 100644 index 0000000..079da8c --- /dev/null +++ b/xinha/examples/custom.css @@ -0,0 +1,40 @@ + /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- + -- CSS plugin example CSS file. This file is used by full_example.js + -- when the CSS plugin is included in an auto-generated example. + -- @TODO Make this CSS more useful. + -- + -- $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/custom.css $ + -- $LastChangedDate: 2007-01-19 23:24:36 +0100 (Fr, 19 Jan 2007) $ + -- $LastChangedRevision: 677 $ + -- $LastChangedBy: ray $ + --------------------------------------------------------------------------*/ + +body { background-color: #234; color: #dd8; font-family: tahoma; font-size: 12px; } + +a:link, a:visited { color: #8cf; } +a:hover { color: #ff8; } + +h1 { background-color: #456; color: #ff8; padding: 2px 5px; border: 1px solid; border-color: #678 #012 #012 #678; } + +/* syntax highlighting (used by the first combo defined for the CSS plugin) */ + +pre { margin: 0px 1em; padding: 5px 1em; background-color: #000; border: 1px dotted #02d; border-left: 2px solid #04f; } +.code { color: #f5deb3; } +.string { color: #00ffff; } +.comment { color: #8fbc8f; } +.variable-name { color: #fa8072; } +.type { color: #90ee90; font-weight: bold; } +.reference { color: #ee82ee; } +.preprocessor { color: #faf; } +.keyword { color: #ffffff; font-weight: bold; } +.function-name { color: #ace; } +.html-tag { font-weight: bold; } +.html-helper-italic { font-style: italic; } +.warning { color: #ffa500; font-weight: bold; } +.html-helper-bold { font-weight: bold; } + +/* info combo */ + +.quote { font-style: italic; color: #ee9; } +.highlight { background-color: yellow; color: #000; } +.deprecated { text-decoration: line-through; color: #aaa; } diff --git a/xinha/examples/dynamic.css b/xinha/examples/dynamic.css new file mode 100644 index 0000000..238b043 --- /dev/null +++ b/xinha/examples/dynamic.css @@ -0,0 +1,56 @@ + /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- + -- DynamicCSS plugin example CSS file. Used by full_example.js + -- when the DynamicCSS plugin is included in an auto-generated example. + -- @TODO Make this CSS more useful. + -- + -- $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/dynamic.css $ + -- $LastChangedDate: 2007-01-19 23:24:36 +0100 (Fr, 19 Jan 2007) $ + -- $LastChangedRevision: 677 $ + -- $LastChangedBy: ray $ + --------------------------------------------------------------------------*/ + +p { + FONT-FAMILY: Arial, Helvetica; + FONT-SIZE: 9pt; + FONT-WEIGHT: normal; + COLOR: #000000; +} + +p.p1 { + FONT-FAMILY: Arial, Helvetica; + FONT-SIZE: 11pt; + FONT-WEIGHT: normal; + COLOR: #000000; +} + +p.p2 { + FONT-FAMILY: Arial, Helvetica; + FONT-SIZE: 13pt; + FONT-WEIGHT: normal; + COLOR: #000000; +} + +div { + FONT-FAMILY: Arial, Helvetica; + FONT-SIZE: 9pt; + FONT-WEIGHT: bold; + COLOR: #000000; +} + +div.div1 { + FONT-FAMILY: Arial, Helvetica; + FONT-SIZE: 11pt; + FONT-WEIGHT: bold; + COLOR: #000000; +} + +div.div2 { + FONT-FAMILY: Arial, Helvetica; + FONT-SIZE: 13pt; + FONT-WEIGHT: bold; + COLOR: #000000; +} + +.quote { font-style: italic; color: #ee9; } +.highlight { background-color: yellow; color: #000; } +.deprecated { text-decoration: line-through; color: #aaa; } diff --git a/xinha/examples/ext_example-body.html b/xinha/examples/ext_example-body.html new file mode 100644 index 0000000..82f501e --- /dev/null +++ b/xinha/examples/ext_example-body.html @@ -0,0 +1,202 @@ + + + + + + + + Example of Xinha + + + + + + + + + + + +
    +
    + + +
    + + diff --git a/xinha/examples/ext_example-dest.php b/xinha/examples/ext_example-dest.php new file mode 100644 index 0000000..5a226e4 --- /dev/null +++ b/xinha/examples/ext_example-dest.php @@ -0,0 +1,23 @@ + + + + Example of Xinha + + + +$value){ + if(substr($key,0,10) == 'myTextarea') { + echo '

    '.$key.'(source):

    '.$value.'
    '; + echo '

    '.$key.'(preview):

    '.$value; + } + } +?> + + diff --git a/xinha/examples/ext_example-menu.php b/xinha/examples/ext_example-menu.php new file mode 100644 index 0000000..2fd27ac --- /dev/null +++ b/xinha/examples/ext_example-menu.php @@ -0,0 +1,331 @@ + + + + + + + + Example of Xinha + + + + + + +
    +

    Xinha Example

    +
    + Settings + + + +
    + +
    +
    + Plugins +
    +read())) //not a dot file or directory + { if(substr($entry,0,1) != '.') + { + $dir_array[] = $entry; + } + } + $d->close(); + sort($dir_array); + foreach ($dir_array as $entry) + { + echo ''."\n"; + } + +?> +
    +
    +
    + + + +
    + + + + diff --git a/xinha/examples/ext_example.html b/xinha/examples/ext_example.html new file mode 100644 index 0000000..4a0f7bf --- /dev/null +++ b/xinha/examples/ext_example.html @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/xinha/examples/full_example.css b/xinha/examples/full_example.css new file mode 100644 index 0000000..cdd57e5 --- /dev/null +++ b/xinha/examples/full_example.css @@ -0,0 +1,48 @@ + /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- + -- Xinha example CSS file. This is ripped from Trac ;) + -- + -- $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/full_example.css $ + -- $LastChangedDate: 2007-01-19 23:24:36 +0100 (Fr, 19 Jan 2007) $ + -- $LastChangedRevision: 677 $ + -- $LastChangedBy: ray $ + --------------------------------------------------------------------------*/ + + body { + background: #fff; + color: #000; + margin: 10px; + } + body, th, td { + font: normal 13px verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif; + } + h1, h2, h3, h4 { + font-family: arial,verdana,'Bitstream Vera Sans',helvetica,sans-serif; + font-weight: bold; + letter-spacing: -0.018em; + } + h1 { font-size: 21px; margin: .15em 1em 0 0 } + h2 { font-size: 16px; margin: 2em 0 .5em; } + h3 { font-size: 14px; margin: 1.5em 0 .5em; } + hr { border: none; border-top: 1px solid #ccb; margin: 2em 0; } + address { font-style: normal } + img { border: none } + + :link, :visited { + text-decoration: none; + color: #b00; + border-bottom: 1px dotted #bbb; + } + :link:hover, :visited:hover { + background-color: #eee; + color: #555; + } + h1 :link, h1 :visited ,h2 :link, h2 :visited, h3 :link, h3 :visited, + h4 :link, h4 :visited, h5 :link, h5 :visited, h6 :link, h6 :visited { + color: inherit; + } + + .area_holder + { + margin:10px; + } + label {font-size: 11px;} \ No newline at end of file diff --git a/xinha/examples/full_example.js b/xinha/examples/full_example.js new file mode 100644 index 0000000..64e4735 --- /dev/null +++ b/xinha/examples/full_example.js @@ -0,0 +1,97 @@ +var num=1; +if(window.parent&&window.parent!=window){ +var f=window.parent.menu.document.forms[0]; +_editor_lang=f.lang[f.lang.selectedIndex].value; +_editor_skin=f.skin[f.skin.selectedIndex].value; +num=parseInt(f.num.value); +if(isNaN(num)){ +num=1; +f.num.value=1; +} +xinha_plugins=[]; +for(var x=0;x + + + +Simple example of Xinha + + + + + + + + + + + + + + +
    + + + +
    + + + \ No newline at end of file diff --git a/xinha/examples/stylist.css b/xinha/examples/stylist.css new file mode 100644 index 0000000..27b9475 --- /dev/null +++ b/xinha/examples/stylist.css @@ -0,0 +1,31 @@ + /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- + -- Stylist plugin example CSS file. Used by full_example.js + -- when the Stylist plugin is included in an auto-generated example. + -- + -- $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/stylist.css $ + -- $LastChangedDate: 2007-01-19 23:24:36 +0100 (Fr, 19 Jan 2007) $ + -- $LastChangedRevision: 677 $ + -- $LastChangedBy: ray $ + --------------------------------------------------------------------------*/ + +.bluetext +{ + color:blue; +} + +p.blue_paragraph +{ + color:darkblue; +} + +li.green_list_item +{ + color:green; +} + +h1.webdings_lvl_1 +{ + font-family:webdings; +} + +img.polaroid { border:1px solid black; background-color:white; padding:10px; padding-bottom:30px; } \ No newline at end of file diff --git a/xinha/examples/testbed.html b/xinha/examples/testbed.html new file mode 100644 index 0000000..a1c8fae --- /dev/null +++ b/xinha/examples/testbed.html @@ -0,0 +1,191 @@ + + + + + + + + + Example of Xinha + + + + + + + + + + + + +
    + + + +
    + + Hide + Show + + \ No newline at end of file diff --git a/xinha/htmlarea.js b/xinha/htmlarea.js new file mode 100644 index 0000000..b103353 --- /dev/null +++ b/xinha/htmlarea.js @@ -0,0 +1,23 @@ + + /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- + -- COMPATABILITY FILE + -- htmlarea.js is now XinhaCore.js + -- + -- $HeadURL: http://svn.xinha.python-hosting.com/trunk/htmlarea.js $ + -- $LastChangedDate: 2007-01-15 15:28:57 +0100 (Mo, 15 Jan 2007) $ + -- $LastChangedRevision: 659 $ + -- $LastChangedBy: gogo $ + --------------------------------------------------------------------------*/ + +if ( typeof _editor_url == "string" ) +{ + // Leave exactly one backslash at the end of _editor_url + _editor_url = _editor_url.replace(/\x2f*$/, '/'); +} +else +{ + alert("WARNING: _editor_url is not set! You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea/', but it can be relative if you prefer. Further we will try to load the editor files correctly but we'll probably fail."); + _editor_url = ''; +} + +document.write(''); \ No newline at end of file diff --git a/xinha/images/de/bold.gif b/xinha/images/de/bold.gif new file mode 100644 index 0000000..21d286f Binary files /dev/null and b/xinha/images/de/bold.gif differ diff --git a/xinha/images/de/italic.gif b/xinha/images/de/italic.gif new file mode 100644 index 0000000..0bf7947 Binary files /dev/null and b/xinha/images/de/italic.gif differ diff --git a/xinha/images/de/underline.gif b/xinha/images/de/underline.gif new file mode 100644 index 0000000..0545489 Binary files /dev/null and b/xinha/images/de/underline.gif differ diff --git a/xinha/images/ed_about.gif b/xinha/images/ed_about.gif new file mode 100644 index 0000000..0f28d40 Binary files /dev/null and b/xinha/images/ed_about.gif differ diff --git a/xinha/images/ed_align.gif b/xinha/images/ed_align.gif new file mode 100644 index 0000000..6c60d50 Binary files /dev/null and b/xinha/images/ed_align.gif differ diff --git a/xinha/images/ed_align_center.gif b/xinha/images/ed_align_center.gif new file mode 100644 index 0000000..75845b7 Binary files /dev/null and b/xinha/images/ed_align_center.gif differ diff --git a/xinha/images/ed_align_justify.gif b/xinha/images/ed_align_justify.gif new file mode 100644 index 0000000..568c595 Binary files /dev/null and b/xinha/images/ed_align_justify.gif differ diff --git a/xinha/images/ed_align_left.gif b/xinha/images/ed_align_left.gif new file mode 100644 index 0000000..8320a2a Binary files /dev/null and b/xinha/images/ed_align_left.gif differ diff --git a/xinha/images/ed_align_right.gif b/xinha/images/ed_align_right.gif new file mode 100644 index 0000000..bc6f651 Binary files /dev/null and b/xinha/images/ed_align_right.gif differ diff --git a/xinha/images/ed_blank.gif b/xinha/images/ed_blank.gif new file mode 100644 index 0000000..1ea396b Binary files /dev/null and b/xinha/images/ed_blank.gif differ diff --git a/xinha/images/ed_buttons_main.gif b/xinha/images/ed_buttons_main.gif new file mode 100644 index 0000000..bc1962b Binary files /dev/null and b/xinha/images/ed_buttons_main.gif differ diff --git a/xinha/images/ed_charmap.gif b/xinha/images/ed_charmap.gif new file mode 100644 index 0000000..289aa7c Binary files /dev/null and b/xinha/images/ed_charmap.gif differ diff --git a/xinha/images/ed_clearfonts.gif b/xinha/images/ed_clearfonts.gif new file mode 100644 index 0000000..38c52a8 Binary files /dev/null and b/xinha/images/ed_clearfonts.gif differ diff --git a/xinha/images/ed_color_bg.gif b/xinha/images/ed_color_bg.gif new file mode 100644 index 0000000..899f133 Binary files /dev/null and b/xinha/images/ed_color_bg.gif differ diff --git a/xinha/images/ed_color_fg.gif b/xinha/images/ed_color_fg.gif new file mode 100644 index 0000000..292ab87 Binary files /dev/null and b/xinha/images/ed_color_fg.gif differ diff --git a/xinha/images/ed_copy.gif b/xinha/images/ed_copy.gif new file mode 100644 index 0000000..0e440eb Binary files /dev/null and b/xinha/images/ed_copy.gif differ diff --git a/xinha/images/ed_custom.gif b/xinha/images/ed_custom.gif new file mode 100644 index 0000000..1444030 Binary files /dev/null and b/xinha/images/ed_custom.gif differ diff --git a/xinha/images/ed_cut.gif b/xinha/images/ed_cut.gif new file mode 100644 index 0000000..23fbf80 Binary files /dev/null and b/xinha/images/ed_cut.gif differ diff --git a/xinha/images/ed_delete.gif b/xinha/images/ed_delete.gif new file mode 100644 index 0000000..aff568e Binary files /dev/null and b/xinha/images/ed_delete.gif differ diff --git a/xinha/images/ed_format_bold.gif b/xinha/images/ed_format_bold.gif new file mode 100644 index 0000000..78686d1 Binary files /dev/null and b/xinha/images/ed_format_bold.gif differ diff --git a/xinha/images/ed_format_italic.gif b/xinha/images/ed_format_italic.gif new file mode 100644 index 0000000..2d3baf2 Binary files /dev/null and b/xinha/images/ed_format_italic.gif differ diff --git a/xinha/images/ed_format_strike.gif b/xinha/images/ed_format_strike.gif new file mode 100644 index 0000000..a5b1429 Binary files /dev/null and b/xinha/images/ed_format_strike.gif differ diff --git a/xinha/images/ed_format_sub.gif b/xinha/images/ed_format_sub.gif new file mode 100644 index 0000000..6c77d74 Binary files /dev/null and b/xinha/images/ed_format_sub.gif differ diff --git a/xinha/images/ed_format_sup.gif b/xinha/images/ed_format_sup.gif new file mode 100644 index 0000000..4ecb9a1 Binary files /dev/null and b/xinha/images/ed_format_sup.gif differ diff --git a/xinha/images/ed_format_underline.gif b/xinha/images/ed_format_underline.gif new file mode 100644 index 0000000..4bc47a1 Binary files /dev/null and b/xinha/images/ed_format_underline.gif differ diff --git a/xinha/images/ed_help.gif b/xinha/images/ed_help.gif new file mode 100644 index 0000000..d5f7d63 Binary files /dev/null and b/xinha/images/ed_help.gif differ diff --git a/xinha/images/ed_hr.gif b/xinha/images/ed_hr.gif new file mode 100644 index 0000000..ec5c778 Binary files /dev/null and b/xinha/images/ed_hr.gif differ diff --git a/xinha/images/ed_html.gif b/xinha/images/ed_html.gif new file mode 100644 index 0000000..026da4e Binary files /dev/null and b/xinha/images/ed_html.gif differ diff --git a/xinha/images/ed_image.gif b/xinha/images/ed_image.gif new file mode 100644 index 0000000..1af79c3 Binary files /dev/null and b/xinha/images/ed_image.gif differ diff --git a/xinha/images/ed_indent_less.gif b/xinha/images/ed_indent_less.gif new file mode 100644 index 0000000..7dda02a Binary files /dev/null and b/xinha/images/ed_indent_less.gif differ diff --git a/xinha/images/ed_indent_more.gif b/xinha/images/ed_indent_more.gif new file mode 100644 index 0000000..c34b47e Binary files /dev/null and b/xinha/images/ed_indent_more.gif differ diff --git a/xinha/images/ed_killword.gif b/xinha/images/ed_killword.gif new file mode 100644 index 0000000..fd934a7 Binary files /dev/null and b/xinha/images/ed_killword.gif differ diff --git a/xinha/images/ed_left_to_right.gif b/xinha/images/ed_left_to_right.gif new file mode 100644 index 0000000..5e95ea5 Binary files /dev/null and b/xinha/images/ed_left_to_right.gif differ diff --git a/xinha/images/ed_link.gif b/xinha/images/ed_link.gif new file mode 100644 index 0000000..76fd537 Binary files /dev/null and b/xinha/images/ed_link.gif differ diff --git a/xinha/images/ed_list_bullet.gif b/xinha/images/ed_list_bullet.gif new file mode 100644 index 0000000..e37e84b Binary files /dev/null and b/xinha/images/ed_list_bullet.gif differ diff --git a/xinha/images/ed_list_num.gif b/xinha/images/ed_list_num.gif new file mode 100644 index 0000000..630cbfd Binary files /dev/null and b/xinha/images/ed_list_num.gif differ diff --git a/xinha/images/ed_overwrite.gif b/xinha/images/ed_overwrite.gif new file mode 100644 index 0000000..e7a8914 Binary files /dev/null and b/xinha/images/ed_overwrite.gif differ diff --git a/xinha/images/ed_paste.gif b/xinha/images/ed_paste.gif new file mode 100644 index 0000000..81b53a0 Binary files /dev/null and b/xinha/images/ed_paste.gif differ diff --git a/xinha/images/ed_print.gif b/xinha/images/ed_print.gif new file mode 100644 index 0000000..fb2bf80 Binary files /dev/null and b/xinha/images/ed_print.gif differ diff --git a/xinha/images/ed_redo.gif b/xinha/images/ed_redo.gif new file mode 100644 index 0000000..3d73dfc Binary files /dev/null and b/xinha/images/ed_redo.gif differ diff --git a/xinha/images/ed_right_to_left.gif b/xinha/images/ed_right_to_left.gif new file mode 100644 index 0000000..9b255bd Binary files /dev/null and b/xinha/images/ed_right_to_left.gif differ diff --git a/xinha/images/ed_rmformat.gif b/xinha/images/ed_rmformat.gif new file mode 100644 index 0000000..09f102a Binary files /dev/null and b/xinha/images/ed_rmformat.gif differ diff --git a/xinha/images/ed_save.gif b/xinha/images/ed_save.gif new file mode 100644 index 0000000..82262d0 Binary files /dev/null and b/xinha/images/ed_save.gif differ diff --git a/xinha/images/ed_save.png b/xinha/images/ed_save.png new file mode 100644 index 0000000..881fe5d Binary files /dev/null and b/xinha/images/ed_save.png differ diff --git a/xinha/images/ed_saveas.gif b/xinha/images/ed_saveas.gif new file mode 100644 index 0000000..4edd988 Binary files /dev/null and b/xinha/images/ed_saveas.gif differ diff --git a/xinha/images/ed_selectall.gif b/xinha/images/ed_selectall.gif new file mode 100644 index 0000000..9acf0a0 Binary files /dev/null and b/xinha/images/ed_selectall.gif differ diff --git a/xinha/images/ed_show_border.gif b/xinha/images/ed_show_border.gif new file mode 100644 index 0000000..42849b7 Binary files /dev/null and b/xinha/images/ed_show_border.gif differ diff --git a/xinha/images/ed_splitblock.gif b/xinha/images/ed_splitblock.gif new file mode 100644 index 0000000..1f1582b Binary files /dev/null and b/xinha/images/ed_splitblock.gif differ diff --git a/xinha/images/ed_splitcel.gif b/xinha/images/ed_splitcel.gif new file mode 100644 index 0000000..a6e5ab5 Binary files /dev/null and b/xinha/images/ed_splitcel.gif differ diff --git a/xinha/images/ed_undo.gif b/xinha/images/ed_undo.gif new file mode 100644 index 0000000..319242f Binary files /dev/null and b/xinha/images/ed_undo.gif differ diff --git a/xinha/images/ed_word_cleaner.gif b/xinha/images/ed_word_cleaner.gif new file mode 100644 index 0000000..d9b0759 Binary files /dev/null and b/xinha/images/ed_word_cleaner.gif differ diff --git a/xinha/images/fr/bold.gif b/xinha/images/fr/bold.gif new file mode 100644 index 0000000..8a0f657 Binary files /dev/null and b/xinha/images/fr/bold.gif differ diff --git a/xinha/images/fr/strikethrough.gif b/xinha/images/fr/strikethrough.gif new file mode 100644 index 0000000..5707aef Binary files /dev/null and b/xinha/images/fr/strikethrough.gif differ diff --git a/xinha/images/fr/underline.gif b/xinha/images/fr/underline.gif new file mode 100644 index 0000000..4ecaf22 Binary files /dev/null and b/xinha/images/fr/underline.gif differ diff --git a/xinha/images/fullscreen_maximize.gif b/xinha/images/fullscreen_maximize.gif new file mode 100644 index 0000000..211c1c5 Binary files /dev/null and b/xinha/images/fullscreen_maximize.gif differ diff --git a/xinha/images/fullscreen_minimize.gif b/xinha/images/fullscreen_minimize.gif new file mode 100644 index 0000000..f679e5a Binary files /dev/null and b/xinha/images/fullscreen_minimize.gif differ diff --git a/xinha/images/insert_table.gif b/xinha/images/insert_table.gif new file mode 100644 index 0000000..a8f4253 Binary files /dev/null and b/xinha/images/insert_table.gif differ diff --git a/xinha/images/insertfilelink.gif b/xinha/images/insertfilelink.gif new file mode 100644 index 0000000..099f04d Binary files /dev/null and b/xinha/images/insertfilelink.gif differ diff --git a/xinha/images/insertmacro.png b/xinha/images/insertmacro.png new file mode 100644 index 0000000..3c874be Binary files /dev/null and b/xinha/images/insertmacro.png differ diff --git a/xinha/images/tidy.gif b/xinha/images/tidy.gif new file mode 100644 index 0000000..a881c64 Binary files /dev/null and b/xinha/images/tidy.gif differ diff --git a/xinha/images/toggle_borders.gif b/xinha/images/toggle_borders.gif new file mode 100644 index 0000000..95bc5be Binary files /dev/null and b/xinha/images/toggle_borders.gif differ diff --git a/xinha/images/xinha_logo.gif b/xinha/images/xinha_logo.gif new file mode 100644 index 0000000..346e313 Binary files /dev/null and b/xinha/images/xinha_logo.gif differ diff --git a/xinha/lang/b5.js b/xinha/lang/b5.js new file mode 100644 index 0000000..f000699 --- /dev/null +++ b/xinha/lang/b5.js @@ -0,0 +1,29 @@ +// I18N constants -- UTF-8 +// by Dave Lo -- dlo@interactivetools.com +{ + "Bold": "粗體", + "Italic": "斜體", + "Underline": "底線", + "Strikethrough": "刪除線", + "Subscript": "下標", + "Superscript": "上標", + "Justify Left": "位置靠左", + "Justify Center": "位置居中", + "Justify Right": "位置靠右", + "Justify Full": "位置左右平等", + "Ordered List": "順序清單", + "Bulleted List": "無序清單", + "Decrease Indent": "減小行前空白", + "Increase Indent": "加寬行前空白", + "Font Color": "文字顏色", + "Background Color": "背景顏色", + "Horizontal Rule": "水平線", + "Insert Web Link": "插入連結", + "Insert/Modify Image": "插入圖形", + "Insert Table": "插入表格", + "Toggle HTML Source": "切換HTML原始碼", + "Enlarge Editor": "放大", + "About this editor": "關於 HTMLArea", + "Help using editor": "說明", + "Current style": "字體例子" +} diff --git a/xinha/lang/ch.js b/xinha/lang/ch.js new file mode 100644 index 0000000..4227fa4 --- /dev/null +++ b/xinha/lang/ch.js @@ -0,0 +1,56 @@ +// I18N constants + +// LANG: "ch", ENCODING: UTF-8 +// Samuel Stone, http://stonemicro.com/ + +{ + "Bold": "粗體", + "Italic": "斜體", + "Underline": "底線", + "Strikethrough": "刪線", + "Subscript": "下標", + "Superscript": "上標", + "Justify Left": "靠左", + "Justify Center": "居中", + "Justify Right": "靠右", + "Justify Full": "整齊", + "Ordered List": "順序清單", + "Bulleted List": "無序清單", + "Decrease Indent": "伸排", + "Increase Indent": "縮排", + "Font Color": "文字顏色", + "Background Color": "背景顏色", + "Horizontal Rule": "水平線", + "Insert Web Link": "插入連結", + "Insert/Modify Image": "插入圖像", + "Insert Table": "插入表格", + "Toggle HTML Source": "切換HTML原始碼", + "Enlarge Editor": "伸出編輯系統", + "About this editor": "關於 HTMLArea", + "Help using editor": "說明", + "Current style": "字體例子", + "Undoes your last action": "回原", + "Redoes your last action": "重来", + "Cut selection": "剪制选项", + "Copy selection": "复制选项", + "Paste from clipboard": "贴上", + "Direction left to right": "从左到右", + "Direction right to left": "从右到左", + "OK": "好", + "Cancel": "取消", + "Path": "途徑", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "你在用純字編輯方式. 用 [<>] 按鈕轉回 所見即所得 編輯方式.", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "整頁式在Internet Explorer 上常出問題, 因為這是 Internet Explorer 的無名問題,我們無法解決。你可能看見一些垃圾,或遇到其他問題。我們已警告了你. 如果要轉到 正頁式 請按 好.", + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.", + "Cancel": "取消", + "Insert/Modify Link": "插入/改寫連結", + "New window (_blank)": "新窗户(_blank)", + "None (use implicit)": "無(use implicit)", + "Other": "其他", + "Same frame (_self)": "本匡 (_self)", + "Target:": "目標匡:", + "Title (tooltip):": "主題 (tooltip):", + "Top frame (_top)": "上匡 (_top)", + "URL:": "網址:", + "You must enter the URL where this link points to": "你必須輸入你要连结的網址" +} diff --git a/xinha/lang/cz.js b/xinha/lang/cz.js new file mode 100644 index 0000000..87faec8 --- /dev/null +++ b/xinha/lang/cz.js @@ -0,0 +1,50 @@ +// I18N constants + +// LANG: "cz", ENCODING: UTF-8 +// Author: Jiri Löw, + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Tučně", + "Italic": "Kurzíva", + "Underline": "Podtržení", + "Strikethrough": "Přeškrtnutí", + "Subscript": "Dolní index", + "Superscript": "Horní index", + "Justify Left": "Zarovnat doleva", + "Justify Center": "Na střed", + "Justify Right": "Zarovnat doprava", + "Justify Full": "Zarovnat do stran", + "Ordered List": "Seznam", + "Bulleted List": "Odrážky", + "Decrease Indent": "Předsadit", + "Increase Indent": "Odsadit", + "Font Color": "Barva písma", + "Background Color": "Barva pozadí", + "Horizontal Rule": "Vodorovná čára", + "Insert Web Link": "Vložit odkaz", + "Insert/Modify Image": "Vložit obrázek", + "Insert Table": "Vložit tabulku", + "Toggle HTML Source": "Přepnout HTML", + "Enlarge Editor": "Nové okno editoru", + "About this editor": "O této aplikaci", + "Help using editor": "Nápověda aplikace", + "Current style": "Zvolený styl", + "Undoes your last action": "Vrátí poslední akci", + "Redoes your last action": "Opakuje poslední akci", + "Cut selection": "Vyjmout", + "Copy selection": "Kopírovat", + "Paste from clipboard": "Vložit", + "OK": "OK", + "Cancel": "Zrušit", + "Path": "Cesta", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Jste v TEXTOVÉM REŽIMU. Použijte tlačítko [<>] pro přepnutí do WYSIWIG." +} diff --git a/xinha/lang/da.js b/xinha/lang/da.js new file mode 100644 index 0000000..5a14e2b --- /dev/null +++ b/xinha/lang/da.js @@ -0,0 +1,30 @@ +// LANG: "da", ENCODING: UTF-8 +// Author: rene, + +{ + "Bold": "Fed", + "Italic": "Kursiv", + "Underline": "Understregning", + "Strikethrough": "Overstregning ", + "Subscript": "Sænket skrift", + "Superscript": "Hævet skrift", + "Justify Left": "Venstrejuster", + "Justify Center": "Centrer", + "Justify Right": "Højrejuster", + "Justify Full": "Lige margener", + "Ordered List": "Opstilling med tal", + "Bulleted List": "Opstilling med punkttegn", + "Decrease Indent": "Formindsk indrykning", + "Increase Indent": "Forøg indrykning", + "Font Color": "Skriftfarve", + "Background Color": "Baggrundsfarve", + "Horizontal Rule": "Horisontal linie", + "Insert Web Link": "Indsæt hyperlink", + "Insert/Modify Image": "Indsæt billede", + "Insert Table": "Indsæt tabel", + "Toggle HTML Source": "HTML visning", + "Enlarge Editor": "Vis editor i popup", + "About this editor": "Om htmlarea", + "Help using editor": "Hjælp", + "Current style": "Anvendt stil" +} diff --git a/xinha/lang/de.js b/xinha/lang/de.js new file mode 100644 index 0000000..ff10313 --- /dev/null +++ b/xinha/lang/de.js @@ -0,0 +1,169 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +{ + "Bold": "Fett", + "Italic": "Kursiv", + "Underline": "Unterstrichen", + "Strikethrough": "Durchgestrichen", + "Subscript": "Tiefgestellt", + "Superscript": "Hochgestellt", + "Justify Left": "Linksbündig", + "Justify Center": "Zentriert", + "Justify Right": "Rechtsbündig", + "Justify Full": "Blocksatz", + "Ordered List": "Nummerierte Liste", + "Bulleted List": "Aufzählungsliste", + "Decrease Indent": "Einzug verkleinern", + "Increase Indent": "Einzug vergrößern", + "Font Color": "Schriftfarbe", + "Background Color": "Hindergrundfarbe", + "Horizontal Rule": "Horizontale Linie", + "Insert Web Link": "Hyperlink einfügen", + "Insert/Modify Image": "Bild einfügen/verändern", + "Insert Table": "Tabelle einfügen", + "Toggle HTML Source": "HTML Quelltext ein/ausschalten", + "Enlarge Editor": "Editor vergrößern", + "About this editor": "Über diesen Editor", + "Help using editor": "Hilfe", + "Current style": "Derzeitiger Stil", + "Undoes your last action": "Rückgängig", + "Redoes your last action": "Wiederholen", + "Cut selection": "Ausschneiden", + "Copy selection": "Kopieren", + "Paste from clipboard": "Einfügen aus der Zwischenablage", + "Direction left to right": "Textrichtung von Links nach Rechts", + "Direction right to left": "Textrichtung von Rechts nach Links", + "Remove formatting": "Formatierung entfernen", + "Select all": "Alles markieren", + "Print document": "Dokument ausdrucken", + "Clear MSOffice tags": "MSOffice filter", + "Clear Inline Font Specifications": "Zeichensatz Formatierungen entfernen", + "Would you like to clear font typefaces?": "Wollen Sie Zeichensatztypen entfernen", + "Would you like to clear font sizes?": "Wollen Sie Zeichensatzgrößen entfernen", + "Would you like to clear font colours?": "Wollen sie Zeichensatzfarben entfernen", + "Split Block": "Block teilen", + "Toggle Borders": "Tabellenränder ein/ausblenden", + "Save as": "speichern unter", + "Insert/Overwrite": "Einfügen/Überschreiben", + "— format —": "— Format —", + "Heading 1": "Überschrift 1", + "Heading 2": "Überschrift 2", + "Heading 3": "Überschrift 3", + "Heading 4": "Überschrift 4", + "Heading 5": "Überschrift 5", + "Heading 6": "Überschrift 6", + "Normal": "Normal (Absatz)", + "Address": "Adresse", + "Formatted": "Formatiert", + + //dialogs + "OK": "OK", + "Cancel": "Abbrechen", + "Path": "Pfad", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Sie sind im Text-Modus. Benutzen Sie den [<>] Button, um in den visuellen Modus (WYSIWIG) zu gelangen.", + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Aus Sicherheitsgründen dürfen Skripte normalerweise nicht auf Ausschneiden/Kopieren/Einfügen zugreifen. Benutzen Sie bitte die entsprechenden Tastatur-Kommandos (Strg + x/c/v).", + + "You need to select some text before create a link": "Sie müssen einen Text markieren, um einen Link zu erstellen", + "Your Document is not well formed. Check JavaScript console for details.": "Ihr Dokument ist in keinem sauberen Format. Benutzen Sie die Javascript Console für weitere Informationen.", + + "Alignment:": "Ausrichtung:", + "Not set": "nicht eingestellt", + "Left": "links", + "Right": "rechts", + "Texttop": "oben bündig", + "Absmiddle": "mittig", + "Baseline": "Grundlinie", + "Absbottom": "unten bündig", + "Bottom": "unten", + "Middle": "zentriert", + "Top": "oben", + + "Layout": "Layout", + "Spacing": "Abstand", + "Horizontal:": "horizontal:", + "Horizontal padding": "horizontaler Inhaltsabstand", + "Vertical:": "vertikal:", + "Vertical padding": "vertikaler Inhaltsabstand", + "Border thickness:": "Randstärke:", + "Leave empty for no border": "leer lassen für keinen Rand", + + //Insert Link + "Insert/Modify Link": "Verknüpfung hinzufügen/ändern", + "None (use implicit)": "k.A. (implizit)", + "New window (_blank)": "Neues Fenster (_blank)", + "Same frame (_self)": "Selber Rahmen (_self)", + "Top frame (_top)": "Oberster Rahmen (_top)", + "Other": "Anderes", + "Target:": "Ziel:", + "Title (tooltip):": "Titel (Tooltip):", + "URL:": "URL:", + "You must enter the URL where this link points to": "Sie müssen eine Ziel-URL angeben für die Verknüpfung angeben", + + // Insert Table + "Insert Table": "Tabelle einfügen", + "Rows:": "Zeilen:", + "Number of rows": "Zeilenanzahl", + "Cols:": "Spalten:", + "Number of columns": "Spaltenanzahl", + "Width:": "Breite:", + "Width of the table": "Tabellenbreite", + "Percent": "Prozent", + "Pixels": "Pixel", + "Em": "Geviert", + "Width unit": "Größeneinheit", + "Fixed width columns": "Spalten mit fester Breite", + "Positioning of this table": "Positionierung der Tabelle", + "Cell spacing:": "Zellenabstand:", + "Space between adjacent cells": "Raum zwischen angrenzenden Zellen", + "Cell padding:": "Innenabstand:", + "Space between content and border in cell": "Raum zwischen Inhalt und Rand der Zelle", + "You must enter a number of rows": "Bitte geben Sie die Anzahl der Zeilen an", + "You must enter a number of columns": "Bitte geben Sie die Anzahl der Spalten an", + + // Insert Image + "Insert Image": "Bild einfügen", + "Image URL:": "Bild URL:", + "Enter the image URL here": "Bitte geben sie hier die Bild URL ein", + "Preview": "Voransicht", + "Preview the image in a new window": "Voransicht des Bildes in einem neuen Fenster", + "Alternate text:": "Alternativer Text:", + "For browsers that don't support images": "für Browser, die keine Bilder unterstützen", + "Positioning of this image": "Positionierung dieses Bildes", + "Image Preview:": "Bild Voransicht:", + "You must enter the URL": "Bitte geben Sie die URL ein", + + "button_bold": "de/bold.gif", + "button_italic": "de/italic.gif", + "button_underline": "de/underline.gif", + + // Editor Help + "Keyboard shortcuts": "Tastaturkürzel", + "The editor provides the following key combinations:": "Der Editor unterstützt die folgenden kombinationen:", + "new paragraph": "Neuer Absatz(Paragraph)", + "insert linebreak": "Harter Umbruch einfügen", + "Set format to paragraph": "Setze Formatierung auf Absatz", + "Clean content pasted from Word": "Von Word eingefügter Text bereinigen", + "Headings": "Überschrift Typ 1 bis 6", + "Close": "Schließen", + + // Loading messages + "Loading in progress. Please wait!": "Editor wird geladen. Bitte warten !", + "Loading plugin $plugin" : "Plugin $plugin wird geladen", + "Register plugin $plugin" : "Plugin $plugin wird registriert", + "Constructing object": "Objekt wird generiert", + "Generate Xinha framework": "Xinha Framework wird generiert", + "Init editor size":"Größe wird berechnet", + "Create Toolbar": "Werkzeugleiste wird generiert", + "Create Statusbar" : "Statusleiste wird generiert", + "Register right panel" : "Rechtes Panel wird generiert", + "Register left panel" : "Linkes Panel wird generiert", + "Register bottom panel" : "Unteres Panel wird generiert", + "Register top panel" : "Oberes Panel wird generiert", + "Finishing" : "Laden wird abgeschlossen", + + // ColorPicker + "Click a color..." : "Farbe wählen", + "Sample" : "Beispiel", + "Web Safe: " : "Web Safe: ", + "Color: " : "Farbe: " +}; \ No newline at end of file diff --git a/xinha/lang/ee.js b/xinha/lang/ee.js new file mode 100644 index 0000000..2c961e5 --- /dev/null +++ b/xinha/lang/ee.js @@ -0,0 +1,50 @@ +// I18N constants + +// LANG: "ee", ENCODING: UTF-8 +// Author: Martin Raie, + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Paks", + "Italic": "Kursiiv", + "Underline": "Allakriipsutatud", + "Strikethrough": "Läbikriipsutatud", + "Subscript": "Allindeks", + "Superscript": "Ülaindeks", + "Justify Left": "Joonda vasakule", + "Justify Center": "Joonda keskele", + "Justify Right": "Joonda paremale", + "Justify Full": "Rööpjoonda", + "Ordered List": "Nummerdus", + "Bulleted List": "Täpploend", + "Decrease Indent": "Vähenda taanet", + "Increase Indent": "Suurenda taanet", + "Font Color": "Fondi värv", + "Background Color": "Tausta värv", + "Horizontal Rule": "Horisontaaljoon", + "Insert Web Link": "Lisa viit", + "Insert/Modify Image": "Lisa pilt", + "Insert Table": "Lisa tabel", + "Toggle HTML Source": "HTML/tavaline vaade", + "Enlarge Editor": "Suurenda toimeti aken", + "About this editor": "Teave toimeti kohta", + "Help using editor": "Spikker", + "Current style": "Kirjastiil", + "Undoes your last action": "Võta tagasi", + "Redoes your last action": "Tee uuesti", + "Cut selection": "Lõika", + "Copy selection": "Kopeeri", + "Paste from clipboard": "Kleebi", + "OK": "OK", + "Cancel": "Loobu", + "Path": "Path", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Sa oled tekstireziimis. Kasuta nuppu [<>] lülitamaks tagasi WYSIWIG reziimi." +} diff --git a/xinha/lang/el.js b/xinha/lang/el.js new file mode 100644 index 0000000..8476a4d --- /dev/null +++ b/xinha/lang/el.js @@ -0,0 +1,55 @@ +// I18N constants + +// LANG: "el", ENCODING: UTF-8 +// Author: Dimitris Glezos, dimitris@glezos.com + +{ + "Bold": "ΞˆΞ½Ο„ΞΏΞ½Ξ±", + "Italic": "Πλάγια", + "Underline": "Ξ�πογραμμισμένα", + "Strikethrough": "Διαγραμμένα", + "Subscript": "ΔΡίκτης", + "Superscript": "ΔΡίκτης", + "Justify Left": "Στοίχιση ΑριστΡρά", + "Justify Center": "Στοίχιση ΞšΞ­Ξ½Ο„ΟΞΏ", + "Justify Right": "Στοίχιση ΔΡξιά", + "Justify Full": "Ξ Ξ»Ξ�ρης Στοίχιση", + "Ordered List": "Αρίθμηση", + "Bulleted List": "ΞšΞΏΟ…ΞΊΞΊΞ―Ξ΄Ξ΅Ο‚", + "Decrease Indent": "ΞœΞ΅Ξ―Ο‰ΟƒΞ· ΕσοχΞ�Ο‚", + "Increase Indent": "Αύξηση ΕσοχΞ�Ο‚", + "Font Color": "Χρώμα ΓραμματοσΡιράς", + "Background Color": "Χρώμα Ξ¦ΟŒΞ½Ο„ΞΏΟ…", + "Horizontal Rule": "ΞŸΟΞΉΞΆΟŒΞ½Ο„ΞΉΞ± ΓραμμΞ�", + "Insert Web Link": "ΕισαγωγΞ� Συνδέσμου", + "Insert/Modify Image": "ΕισαγωγΞ�/Ξ�ροποποίηση Ξ•ΞΉΞΊΟŒΞ½Ξ±Ο‚", + "Insert Table": "ΕισαγωγΞ� Ξ Ξ―Ξ½Ξ±ΞΊΞ±", + "Toggle HTML Source": "ΕναλλαγΞ� σΡ/Ξ±Ο€ΟŒ HTML", + "Enlarge Editor": "ΞœΞ΅Ξ³Ξ­Ξ½ΞΈΟ…Ξ½ΟƒΞ· ΡπΡξΡργαστΞ�", + "About this editor": "ΠληροφορίΡς", + "Help using editor": "Ξ’ΞΏΞ�θΡια", + "Current style": "Παρών στυλ", + "Undoes your last action": "ΑναίρΡση τΡλΡυταίας ΡνέργΡιας", + "Redoes your last action": "Επαναφορά Ξ±Ο€ΟŒ αναίρΡση", + "Cut selection": "ΑποκοπΞ�", + "Copy selection": "ΑντιγραφΞ�", + "Paste from clipboard": "Ξ•Ο€ΞΉΞΊΟŒΞ»Ξ»Ξ·ΟƒΞ·", + "Direction left to right": "ΞšΞ±Ο„Ξ΅ΟΞΈΟ…Ξ½ΟƒΞ· αριστΡρά προς δΡξιά", + "Direction right to left": "ΞšΞ±Ο„Ξ΅ΟΞΈΟ…Ξ½ΟƒΞ· Ξ±Ο€ΟŒ δΡξιά προς τα αριστΡρά", + "OK": "OK", + "Cancel": "Ακύρωση", + "Path": "ΔιαδρομΞ�", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "ΕίστΡ σΡ TEXT MODE. ΧρησιμοποιΞ�στΡ το κουμπί [<>] Ξ³ΞΉΞ± Ξ½Ξ± ΡπανέρθΡτΡ στο WYSIWIG.", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Ξ— κατάσταση πλΞ�ρης ΞΏΞΈΟŒΞ½Ξ·Ο‚ έχΡι προβλΞ�ματα ΞΌΞ΅ τον Internet Explorer, Ξ»ΟŒΞ³Ο‰ σφαλμάτων στον ίδιο τον browser. Αν το σύστημα σας Ρίναι Windows 9x μπορΡί ΞΊΞ±ΞΉ Ξ½Ξ± χρΡιαστΡίτΡ reboot. Αν ΡίστΡ σίγουροι, πατΞ�στΡ ΟΚ.", + "Cancel": "Ακύρωση", + "Insert/Modify Link": "ΕισαγωγΞ�/Ξ�ροποποίηση σύνδΡσμου", + "New window (_blank)": "Νέο παράθυρο (_blank)", + "None (use implicit)": "Κανένα (χρΞ�ση Ξ±Ο€ΟŒΞ»Ο…Ο„ΞΏΟ…)", + "Other": "Αλλο", + "Same frame (_self)": "Ίδιο frame (_self)", + "Target:": "Target:", + "Title (tooltip):": "Ξ�ίτλος (tooltip):", + "Top frame (_top)": "Πάνω frame (_top)", + "URL:": "URL:", + "You must enter the URL where this link points to": "ΠρέπΡι Ξ½Ξ± ΡισάγΡτΡ το URL που οδηγΡί Ξ±Ο…Ο„ΟŒΟ‚ ΞΏ σύνδΡσμος" +} diff --git a/xinha/lang/es.js b/xinha/lang/es.js new file mode 100644 index 0000000..e1ea5c1 --- /dev/null +++ b/xinha/lang/es.js @@ -0,0 +1,40 @@ +// I18N constants + +// LANG: "es", ENCODING: UTF-8 + +{ + "Bold": "Negrita", + "Italic": "Cursiva", + "Underline": "Subrayado", + "Strikethrough": "Tachado", + "Subscript": "Sub?ndice", + "Superscript": "Super?ndice", + "Justify Left": "Alinear a la Izquierda", + "Justify Center": "Centrar", + "Justify Right": "Alinear a la Derecha", + "Justify Full": "Justificar", + "Ordered List": "Lista Ordenada", + "Bulleted List": "Lista No Ordenada", + "Decrease Indent": "Aumentar Sangr?a", + "Increase Indent": "Disminuir Sangr?a", + "Font Color": "Color del Texto", + "Background Color": "Color del Fondo", + "Horizontal Rule": "L?nea Horizontal", + "Insert Web Link": "Insertar Enlace", + "Insert/Modify Image": "Insertar Imagen", + "Insert Table": "Insertar Tabla", + "Toggle HTML Source": "Ver Documento en HTML", + "Enlarge Editor": "Ampliar Editor", + "About this editor": "Acerca del Editor", + "Help using editor": "Ayuda", + "Current style": "Estilo Actual", + "Undoes your last action": "Deshacer", + "Redoes your last action": "Rehacer", + "Cut selection": "Cortar selecci?n", + "Copy selection": "Copiar selecci?n", + "Paste from clipboard": "Pegar desde el portapapeles", + "OK": "Aceptar", + "Cancel": "Cancelar", + "Path": "Ruta", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Esta en modo TEXTO. Use el boton [<>] para cambiar a WYSIWIG" +} diff --git a/xinha/lang/eu.js b/xinha/lang/eu.js new file mode 100644 index 0000000..ec06ed5 --- /dev/null +++ b/xinha/lang/eu.js @@ -0,0 +1,169 @@ +// I18N constants +// LANG: "eu", ENCODING: UTF-8 +{ + "Bold": "Lodia", + "Italic": "Etzana", + "Underline": "Azpimarratua", + "Strikethrough": "Marratua", + "Subscript": "Azpindizea", + "Superscript": "Goi-indizea", + "Justify Left": "Ezkerretara lerrokatu", + "Justify Center": "Zentratu", + "Justify Right": "Eskuinetara lerrokatu", + "Justify Full": "Justifikatu", + "Ordered List": "Zerrenda ordenatua", + "Bulleted List": "Zerrenda ez ordenatua", + "Decrease Indent": "Koska handitu", + "Increase Indent": "Koska txikitu", + "Font Color": "Testu-kolorea", + "Background Color": "Atzeko kolorea", + "Horizontal Rule": "Marra horizontala", + "Insert Web Link": "Lotura txertatu", + "Insert/Modify Image": "Irudia txertatu", + "Insert Table": "Taula txertatu", + "Toggle HTML Source": "Ikusi dokumentua HTML-n", + "Enlarge Editor": "Editorea handitu", + "About this editor": "Editoreari buruz...", + "Help using editor": "Laguntza", + "Current style": "Uneko estiloa", + "Undoes your last action": "Desegin", + "Redoes your last action": "Berregin", + "Cut selection": "Ebaki hautaketa", + "Copy selection": "Kopiatu hautaketa", + "Paste from clipboard": "Itsatsi arbelean dagoena", + "Direction left to right": "Ezkerretik eskuinetarako norabidea", + "Direction right to left": "Eskuinetik ezkerretarako norabidea", + "Remove formatting": "Formatoa kendu", + "Select all": "Dena aukeratu", + "Print document": "Dokumentua inprimatu", + "Clear MSOffice tags": "MSOffice etiketak ezabatu", + "Clear Inline Font Specifications": "Ezabatu testuaren ezaugarriak", + "Would you like to clear font typefaces?": "Letra-tipoak ezabatu nahi al dituzu?", + "Would you like to clear font sizes?": "Letra-tipoen neurriak ezabatu nahi al dituzu?", + "Would you like to clear font colours?": "Letra-tipoen koloreak ezabatu nahi al dituzu?", + "Split Block": "Blokea zatitu", + "Toggle Borders": "Ertzak trukatu", + "Save as": "Gorde honela:", + "Insert/Overwrite": "Txertatu/Gainidatzi", + "— format —": "— Formatua —", + "Heading 1": "Goiburua 1", + "Heading 2": "Goiburua 2", + "Heading 3": "Goiburua 3", + "Heading 4": "Goiburua 4", + "Heading 5": "Goiburua 5", + "Heading 6": "Goiburua 6", + "Normal": "Normala", + "Address": "Helbidea", + "Formatted": "Formateatua", + + //dialogs + "OK": "Ados", + "Cancel": "Utzi", + "Path": "Bidea", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "TESTU eran ari zara. Erabil ezazu [<>] botoia WYSIWIG erara itzultzeko.", + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Itsatsi botoia ez dabil Mozillan oinarritutako nabigatzaileetan (arrazoi teknikoengatik). Sacatu CTRL-V zure teklatuan, zuzenean itsasteko.", + + "You need to select some text before create a link": "Testu-atal bat aukeratu behar duzu lehendabizi, lotura bat sortzeko", + "Your Document is not well formed. Check JavaScript console for details.": "Zure dokumentuak ez du formatu zuzena. Begira ezazu JavaScript kontsola xehetasunetarako.", + + "Alignment:": "Lerrokatzea:", + "Not set": "Ez gaitua", + "Left": "Ezkerretara", + "Right": "Eskuinetara", + "Texttop": "Irudiaren goialdean", + "Absmiddle": "Irudiaren erdian", + "Baseline": "Irudiaren oinean", + "Absbottom": "Irudiaren behekaldean", + "Bottom": "Behean", + "Middle": "Erdian", + "Top": "Goian", + + "Layout": "Diseinua", + "Spacing": "Tartea", + "Horizontal:": "Horizontala:", + "Horizontal padding": "Betegarri horizontala", + "Vertical:": "Bertikala:", + "Vertical padding": "Betegarri bertikala", + "Border thickness:": "Ertzaren lodiera:", + "Leave empty for no border": "Uztazu hutsik ertzik ez sortzeko", + + //Insert Link + "Insert/Modify Link": "Lotura txertatu/aldatu", + "None (use implicit)": "Bat ere ez (implizituki erabili)", + "New window (_blank)": "Lehio berrian (_blank)", + "Same frame (_self)": "Frame berean (_self)", + "Top frame (_top)": "Goiko frame-an (_top)", + "Other": "Beste bat", + "Target:": "Helburua:", + "Title (tooltip):": "Izenburua (argibidea):", + "URL:": "URL-a:", + "You must enter the URL where this link points to": "Loturaren helburu den URL-a idatzi behar duzu", + + // Insert Table + "Insert Table": "Taula txertatu", + "Rows:": "Lerroak:", + "Number of rows": "Lerro-kopurua", + "Cols:": "Zutabeak:", + "Number of columns": "Zutabe-kopurua", + "Width:": "Zabalera:", + "Width of the table": "Taularen zabalera", + "Percent": "Portzentaia", + "Pixels": "Pixelak", + "Em": "Em", + "Width unit": "Zabalera-unitatea", + "Fixed width columns": "Zabalera finkodun zutabeak", + "Positioning of this table": "Taula honen kokapena", + "Cell spacing:": "Gelaxka-tartea:", + "Space between adjacent cells": "Gelaxka auzokideen arteko tartea", + "Cell padding:": "Gelaxkaren betegarria:", + "Space between content and border in cell": "Gelaxkaren edukia eta ertzaren arteko tartea", + "You must enter a number of rows": "Lerro-kopurua idatzi behar duzu", + "You must enter a number of columns": "Zutabe-kopurua idatzi behar duzu", + + // Insert Image + "Insert Image": "Irudia txertatu", + "Image URL:": "Irudiaren URL-a:", + "Enter the image URL here": "Idatz ezazu irudiaren URL-a hemen", + "Preview": "Aurrebista", + "Preview the image in a new window": "Aurreikusi irudia beste lehio batean", + "Alternate text:": "Testu alternatiboa:", + "For browsers that don't support images": "Irudirik onartzen ez duten nabigatzaileentzat", + "Positioning of this image": "Irudiaren kokapena", + "Image Preview:": "Irudiaren aurrebista:", + "You must enter the URL": "URL-a idatzi behar duzu", + + "button_bold": "de/bold.gif", + "button_italic": "de/italic.gif", + "button_underline": "de/underline.gif", + + // Editor Help + "Keyboard shortcuts": "Laster-teklak", + "The editor provides the following key combinations:": "Editoreak ondorengo tekla-konbinazioak eskaintzen ditu:", + "new paragraph": "Paragrafo berria", + "insert linebreak": "Lerro-jauzia txertatu", + "Set format to paragraph": "Formatua ezarri paragrafoari", + "Clean content pasted from Word": "Word-etik itsatsitako edukia ezabatu", + "Headings": "Goiburuak", + "Close": "Itxi", + + // Loading messages + "Loading in progress. Please wait!": "Kargatzen. Itxaron mesedez", + "Loading plugin $plugin" : "$plugin plugina kargatzen", + "Register plugin $plugin" : "$plugin plugina erregistratu", + "Constructing object": "Objektua eraikitzen", + "Generate Xinha framework": "Xinha Framework sortzen", + "Init editor size":"Editorearen hasierako neurria", + "Create Toolbar": "Tresna-barra sortu", + "Create Statusbar" : "Egoera-barra sortu", + "Register right panel" : "Eskuin-panela erregistratu", + "Register left panel" : "Ezker-panela erregistratu", + "Register bottom panel" : "Beheko panela erregistratu", + "Register top panel" : "Goiko panela erregistratu", + "Finishing" : "Bukatzen", + + // ColorPicker + "Click a color..." : "Kolore bat aukeratu...", + "Sample" : "Lagina", + "Web Safe: " : "Web Safe: ", + "Color: " : "Kolorea: " +}; \ No newline at end of file diff --git a/xinha/lang/fa.js b/xinha/lang/fa.js new file mode 100644 index 0000000..106e831 --- /dev/null +++ b/xinha/lang/fa.js @@ -0,0 +1,167 @@ +// I18N constants +// LANG: "fa", ENCODING: UTF-8 +{ + "Bold": "ضخیم", + "Italic": "مورب", + "Underline": "زیر خط", + "Strikethrough": "رو خط", + "Subscript": "زیروند", + "Superscript": "بالاوند", + "Justify Left": "تراز از چپ", + "Justify Center": "تراز در وسط", + "Justify Right": "تراز در راست", + "Justify Full": "تراز از چپ و راست", + "Ordered List": "فهرست مرتب", + "Bulleted List": "فهرست گلوله ای", + "Decrease Indent": "کاهش سر خط", + "Increase Indent": "افزایش سر خط", + "Font Color": "رنگ فلم", + "Background Color": "رنگ پس زمینه", + "Horizontal Rule": "خط افقی", + "Insert Web Link": "افزودن لینک وب", + "Insert/Modify Image": "افزودن یا ویرایش تصویر", + "Insert Table": "افزودن جدول", + "Toggle HTML Source": "مشاهده یا عدم مشاهده متن در قالب HTML", + "Enlarge Editor": "بزرگ کردن ویرایش گر", + "About this editor": "درباره این ویرایش گر", + "Help using editor": "راهنمای استفاده ویرایش گر", + "Current style": "شیوه کنونی", + "Undoes your last action": "برگرداندن آخرین عمل", + "Redoes your last action": "انجام مجدد آخرین عمل", + "Cut selection": "بریدن انتخاب شده", + "Copy selection": "کپی انتخاب شده", + "Paste from clipboard": "چسباندن از تخته کار", + "Direction left to right": "جهت از چپ به راست", + "Direction right to left": "جهت از راست به چپ", + "Remove formatting": "حذف فرمت بندی", + "Select all": "انتخاب همه", + "Print document": "چاپ سند", + "Clear MSOffice tags": "پاک کردن متن از برچسب های MSOffice", + "Clear Inline Font Specifications": "پاک کردن متن از مشخصات فونت", + "Would you like to clear font typefaces?": "آیا تمایل دارید ظاهر فلم را پاک کنید؟", + "Would you like to clear font sizes?": "آیا تمایل دارید اندازه قلم را پاک کنید", + "Would you like to clear font colours?": "آیا تمایل دارید رنگ قلم را پاک کنید؟", + "Split Block": "بلاک جداسازی", + "Toggle Borders": "فعال/غیر فعال کردن لبه ها", + "Save as": "ذخیره مانند...", + "Insert/Overwrite": "افزودن/جانویسی", + "— format —": "— قالب —", + "Heading 1": "تیتر 1", + "Heading 2": "تیتر 2", + "Heading 3": "تیتر 3", + "Heading 4": "تیتر 4", + "Heading 5": "تیتر 5", + "Heading 6": "تیتر 6", + "Normal": "معمولی", + "Address": "آدرس", + "Formatted": "قالب بندی شده", + + //dialogs + "OK": "بله", + "Cancel": "انصراف", + "Path": "مسیر", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "در مد متنی هستید. از دکمه [<>] استفاده نمایید تا به مد WYSIWYG برگردید.", + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "دکمه چسباندن در مرورگرهای سری Mozilla کار نمی کند (به دلایل فنی امنیتی).برای چسباندن مستقیم ، دکمه CTRL-V را در صفحه کلید بزنید.", + "Your Document is not well formed. Check JavaScript console for details.": "سند شما بدرستی قالب بندی نشده است. برای اطلاعات بیشتر پایانه نمایش جاوااسکریپت را بررسی کنید.", + + "Alignment:": "تراز بندی", + "Not set": "تنظیم نشده", + "Left": "چپ", + "Right": "راست", + "Texttop": "بالای متن", + "Absmiddle": "دقیقا وسط", + "Baseline": "ابتدای خط", + "Absbottom": "دقیقا پایین", + "Bottom": "پایین", + "Middle": "وسط", + "Top": "بالا", + + "Layout": "لایه", + "Spacing": "فاصله گذاری", + "Horizontal:": "افقی", + "Horizontal padding": "پرکننده افقی", + "Vertical:": "عمودی", + "Vertical padding": "پرکننده عمودی", + "Border thickness:": "ضخامت لبه", + "Leave empty for no border": "برای بدون لبه خالی رها کن", + + //Insert Link + "Insert/Modify Link": "افزودن / ویرایش لینک", + "None (use implicit)": "هیچکدام (استفاده از بدون شرط)", + "New window (_blank)": "پنجره جدید (_blank)", + "Same frame (_self)": "فریم یکسان (_self)", + "Top frame (_top)": "فریم بالایی (_top)", + "Other": "سایر", + "Target:": "هدف", + "Title (tooltip):": "عنوان (راهنمای یک خطی)", + "URL:": "URL:", + "You must enter the URL where this link points to": "باید URLی که این لینک به آن اشاره دارد را وارد کنید", + "You need to select some text before creating a link": "باید قبل از ساخت لینک ، متنی را انتخاب نمایید", + + // Insert Table + "Insert Table": "افزودن جدول", + "Rows:": "ردیف ها", + "Number of rows": "تعداد ردیف ها", + "Cols:": "ستون ها", + "Number of columns": "تعداد ستون ها", + "Width:": "طول", + "Width of the table": "طول جدول", + "Percent": "درصد", + "Pixels": "پیکسل ها", + "Em": "Em", + "Width unit": "واحد طول", + "Fixed width columns": "ستون های طول ثابت", + "Positioning of this table": "موقعیت یابی این جدول", + "Cell spacing:": "فاصله سلول ها", + "Space between adjacent cells": "فاصله بین سلول های همجوار", + "Cell padding:": "پر کننده سلول", + "Space between content and border in cell": "فاصله بین محتوا و لبه در سلول", + "You must enter a number of rows": "باید تعداد ردیف ها را وارد کنید", + "You must enter a number of columns": "باید تعداد ستون ها را وارد کنید", + + // Insert Image + "Insert Image": "افزودن تصویر", + "Image URL:": "URL تصویر", + "Enter the image URL here": "URL تصویر را اینجا وارد کنید", + "Preview": "پیش نمایش", + "Preview the image in a new window": "پیش نمایش تصویر در پنجره ای جدید", + "Alternate text:": "متن جایگزین", + "For browsers that don't support images": "برای مرورگرهایی که از تصاویر پشتیبانی نمی کنند", + "Positioning of this image": "موقعیت یابی تصویر", + "Image Preview:": "پیش نمایش تصویر", + "You must enter the URL": "شما باید URL را وارد کنید", + + // toolbar + "button_bold": "fr/bold.gif", + "button_underline": "fr/underline.gif", + "button_strikethrough": "fr/strikethrough.gif", + + // Editor Help + "Xinha Help": "راهنمای Xinha", + "Editor Help": "راهنمای ویرایشگر", + "Keyboard shortcuts": "میانبرهای صفحه کلید", + "The editor provides the following key combinations:": "ویرایشگر استفاده از کلید های گروهی زیر را مسیر می سازد :", + "ENTER": "ENTREE", + "new paragraph": "پاراگراف جدید", + "SHIFT-ENTER": "SHIFT+ENTREE", + "insert linebreak": "افزودن جدا کننده خط", + "Set format to paragraph": "تغییر قالب به پاراگراف", + "Clean content pasted from Word": "تمیز کردن محتوای چسبانده شده از Word", + "Headings": "عنوان گذاری", + "Close": "بستن", + + // Loading messages + "Loading in progress. Please wait !": "بارگذاری در حال انجام است. لطفا صبر کنید !", + "Constructing main object": "ساختن شیء اصلی", + "Constructing object": "ساختن شیء", + "Register panel right": "ثبت قاب راست", + "Register panel left": "ثبت قاب چپ", + "Register panel top": "ثبت قاب بالا", + "Register panel bottom": "ثبت قاب پایین", + "Create Toolbar": "ساخت نوار ابزار", + "Create StatusBar": "ساخت نوار وضعیت", + "Generate Xinha object": "تولید شیء Xinha", + "Init editor size": "مقدار دهی اندازه ویرایشگر", + "Init IFrame": "مقدار دهی IFrame", + "Register plugin $plugin": "ثبت پلاگین $plugin" +}; \ No newline at end of file diff --git a/xinha/lang/fi.js b/xinha/lang/fi.js new file mode 100644 index 0000000..0297c78 --- /dev/null +++ b/xinha/lang/fi.js @@ -0,0 +1,38 @@ +// I18N constants + +// LANG: "en", ENCODING: UTF-8 + +{ + "Bold": "Lihavoitu", + "Italic": "Kursivoitu", + "Underline": "Alleviivattu", + "Strikethrough": "Yliviivattu", + "Subscript": "Alaindeksi", + "Superscript": "Yläindeksi", + "Justify Left": "Tasaa vasemmat reunat", + "Justify Center": "Keskitä", + "Justify Right": "Tasaa oikeat reunat", + "Justify Full": "Tasaa molemmat reunat", + "Ordered List": "Numerointi", + "Bulleted List": "Luettelomerkit", + "Decrease Indent": "Pienennä sisennystä", + "Increase Indent": "Lisää sisennystä", + "Font Color": "Fontin väri", + "Background Color": "Taustaväri", + "Horizontal Rule": "Vaakaviiva", + "Insert Web Link": "Lisää linkki", + "Insert/Modify Image": "Lisää kuva", + "Insert Table": "Lisää taulukko", + "Toggle HTML Source": "HTML-lähdekoodi vs WYSIWYG", + "Enlarge Editor": "Suurenna editori", + "About this editor": "Tietoja editorista", + "Help using editor": "Näytä ohje", + "Current style": "Nykyinen tyyli", + "Undoes your last action": "Peruuta viimeinen toiminto", + "Redoes your last action": "Palauta viimeinen toiminto", + "Cut selection": "Leikkaa maalattu", + "Copy selection": "Kopioi maalattu", + "Paste from clipboard": "Liitä leikepyödältä", + "OK": "Hyväksy", + "Cancel": "Peruuta" +} diff --git a/xinha/lang/fr.js b/xinha/lang/fr.js new file mode 100644 index 0000000..56bf537 --- /dev/null +++ b/xinha/lang/fr.js @@ -0,0 +1,169 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Bold": "Gras", + "Italic": "Italique", + "Underline": "Souligné", + "Strikethrough": "Barré", + "Subscript": "Indice", + "Superscript": "Exposant", + "Justify Left": "Aligner à gauche", + "Justify Center": "Centrer", + "Justify Right": "Aligner à droite", + "Justify Full": "Justifier", + "Ordered List": "Liste numérotée", + "Bulleted List": "Liste à puces", + "Decrease Indent": "Diminuer le retrait", + "Increase Indent": "Augmenter le retrait", + "Font Color": "Couleur de police", + "Background Color": "Surlignage", + "Horizontal Rule": "Ligne horizontale", + "Insert Web Link": "Insérer un lien", + "Insert/Modify Image": "Insérer / Modifier une image", + "Insert Table": "Insérer un tableau", + "Toggle HTML Source": "Afficher / Masquer code source", + "Enlarge Editor": "Agrandir l'éditeur", + "About this editor": "A propos", + "Help using editor": "Aide", + "Current style": "Style courant", + "Undoes your last action": "Annuler la dernière action", + "Redoes your last action": "Répéter la dernière action", + "Cut selection": "Couper la sélection", + "Copy selection": "Copier la sélection", + "Paste from clipboard": "Coller depuis le presse-papier", + "Direction left to right": "Direction de gauche à droite", + "Direction right to left": "Direction de droite à gauche", + "Remove formatting": "Supprimer mise en forme", + "Select all": "Tout sélectionner", + "Print document": "Imprimer document", + "Clear MSOffice tags": "Supprimer tags MSOffice", + "Clear Inline Font Specifications": "Supprimer paramètres inline de la police", + "Would you like to clear font typefaces?": "Voulez-vous supprimer les types ?", + "Would you like to clear font sizes?": "Voulez-vous supprimer les tailles ?", + "Would you like to clear font colours?": "Voulez-vous supprimer les couleurs ?", + "Split Block": "Séparer les blocs", + "Toggle Borders": "Afficher / Masquer les bordures", + "Save as": "Enregistrer sous", + "Insert/Overwrite": "Insertion / Remplacement", + "— format —": "— Format —", + "Heading 1": "Titre 1", + "Heading 2": "Titre 2", + "Heading 3": "Titre 3", + "Heading 4": "Titre 4", + "Heading 5": "Titre 5", + "Heading 6": "Titre 6", + "Normal": "Normal", + "Address": "Adresse", + "Formatted": "Formaté", + + //dialogs + "OK": "OK", + "Cancel": "Annuler", + "Path": "Chemin", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Vous êtes en MODE TEXTE. Appuyez sur le bouton [<>] pour retourner au mode WYSIWYG.", + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Le bouton Coller ne fonctionne pas sur les navigateurs basés sur Mozilla (pour des raisons de sécurité). Pressez CTRL-V au clavier pour coller directement.", + "Your Document is not well formed. Check JavaScript console for details.": "Le document est mal formé. Vérifiez la console JavaScript pour plus de détails.", + + "Alignment:": "Alignement", + "Not set": "Indéfini", + "Left": "Gauche", + "Right": "Droite", + "Texttop": "Texttop", + "Absmiddle": "Absmiddle", + "Baseline": "Baseline", + "Absbottom": "Absbottom", + "Bottom": "Bas", + "Middle": "Milieu", + "Top": "Haut", + + "Layout": "Mise en page", + "Spacing": "Espacement", + "Horizontal:": "Horizontal", + "Horizontal padding": "Marge horizontale interne", + "Vertical:": "Vertical", + "Vertical padding": "Marge verticale interne", + "Border thickness:": "Epaisseur de bordure", + "Leave empty for no border": "Laisser vide pour pas de bordure", + + //Insert Link + "Insert/Modify Link": "Insérer / Modifier un lien", + "None (use implicit)": "Aucune (implicite)", + "New window (_blank)": "Nouvelle fenêtre (_blank)", + "Same frame (_self)": "Même frame (_self)", + "Top frame (_top)": "Frame principale (_top)", + "Other": "Autre", + "Target:": "Cible", + "Title (tooltip):": "Texte alternatif", + "URL:": "URL:", + "You must enter the URL where this link points to": "Vous devez entrer l'URL de ce lien", + "You need to select some text before creating a link": "Vous devez sélectionner du texte avant de créer un lien", + + // Insert Table + "Insert Table": "Insérer un tableau", + "Rows:": "Lignes", + "Number of rows": "Nombre de lignes", + "Cols:": "Colonnes", + "Number of columns": "Nombre de colonnes", + "Width:": "Largeur", + "Width of the table": "Largeur du tableau", + "Percent": "Pourcent", + "Pixels": "Pixels", + "Em": "Em", + "Width unit": "Unités de largeur", + "Fixed width columns": "Colonnes à taille fixe", + "Positioning of this table": "Position du tableau", + "Cell spacing:": "Espacement", + "Space between adjacent cells": "Espace entre les cellules adjacentes", + "Cell padding:": "Marge interne", + "Space between content and border in cell": "Espace entre le contenu et la bordure d'une cellule", + "You must enter a number of rows": "Vous devez entrer le nombre de lignes", + "You must enter a number of columns": "Vous devez entrer le nombre de colonnes", + + // Insert Image + "Insert Image": "Insérer une image", + "Image URL:": "URL image", + "Enter the image URL here": "Entrer l'URL de l'image ici", + "Preview": "Prévisualiser", + "Preview the image in a new window": "Prévisualiser l'image dans une nouvelle fenêtre", + "Alternate text:": "Texte alternatif", + "For browsers that don't support images": "Pour les navigateurs qui ne supportent pas les images", + "Positioning of this image": "Position de l'image", + "Image Preview:": "Prévisualisation", + "You must enter the URL": "Vous devez entrer l'URL", + + // toolbar + "button_bold": "fr/bold.gif", + "button_underline": "fr/underline.gif", + "button_strikethrough": "fr/strikethrough.gif", + + // Editor Help + "Xinha Help": "Aide Xinha", + "Editor Help": "Aide de l'éditeur", + "Keyboard shortcuts": "Raccourcis clavier", + "The editor provides the following key combinations:": "L'éditeur fournit les combinaisons de touches suivantes :", + "ENTER": "ENTREE", + "new paragraph": "Nouveau paragraphe", + "SHIFT-ENTER": "SHIFT+ENTREE", + "insert linebreak": "Insère un saut de ligne", + "Set format to paragraph": "Applique le format paragraphe", + "Clean content pasted from Word": "Nettoyage du contenu copié depuis Word", + "Headings": "Titres", + "Close": "Fermer", + + // Loading messages + "Loading in progress. Please wait!": "Chargement en cours. Veuillez patienter!", + "Finishing" : "Chargement bientôt terminé", + "Constructing object": "Construction de l'objet", + "Create Toolbar": "Construction de la barre d'icones", + "Create Statusbar": "Construction de la barre de status", + "Register right panel" : "Enregistrement du panneau droit", + "Register left panel" : "Enregistrement du panneau gauche", + "Register bottom panel" : "Enregistrement du panneau supérieur", + "Register top panel" : "Enregistrement du panneau inférieur", + "Generate Xinha framework": "Génération de Xinha", + "Init editor size": "Initialisation de la taille d'édition", + "Init IFrame": "Initialisation de l'iframe", + "Register plugin $plugin": "Enregistrement du plugin $plugin" + "Loading plugin $plugin" : "Chargement du plugin $plugin" + +}; \ No newline at end of file diff --git a/xinha/lang/gb.js b/xinha/lang/gb.js new file mode 100644 index 0000000..d3c8df8 --- /dev/null +++ b/xinha/lang/gb.js @@ -0,0 +1,29 @@ +// I18N constants -- Chinese GB +// by Dave Lo -- dlo@interactivetools.com +{ + "Bold": "粗体", + "Italic": "斜体", + "Underline": "底线", + "Strikethrough": "删除线", + "Subscript": "下标", + "Superscript": "上标", + "Justify Left": "位置靠左", + "Justify Center": "位置居中", + "Justify Right": "位置靠右", + "Justify Full": "位置左右平等", + "Ordered List": "顺序清单", + "Bulleted List": "无序清单", + "Decrease Indent": "减小行前空白", + "Increase Indent": "加宽行前空白", + "Font Color": "文字颜色", + "Background Color": "背景颜色", + "Horizontal Rule": "水平线", + "Insert Web Link": "插入连结", + "Insert/Modify Image": "插入图形", + "Insert Table": "插入表格", + "Toggle HTML Source": "切换HTML原始码", + "Enlarge Editor": "放大", + "About this editor": "关於 HTMLArea", + "Help using editor": "说明", + "Current style": "字体例子" +} diff --git a/xinha/lang/he.js b/xinha/lang/he.js new file mode 100644 index 0000000..60dbd76 --- /dev/null +++ b/xinha/lang/he.js @@ -0,0 +1,64 @@ +// I18N constants + +// LANG: "he", ENCODING: UTF-8 +// Author: Liron Newman, http://www.eesh.net, + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "מודגש", + "Italic": "נטוי", + "Underline": "קו תחתי", + "Strikethrough": "קו אמצע", + "Subscript": "כתב עילי", + "Superscript": "כתב תחתי", + "Justify Left": " ישור לשמאל", + "Justify Center": "ישור למרכז", + "Justify Right": "ישור לימין", + "Justify Full": "ישור לשורה מלאה", + "Ordered List": "רשימה ממוספרת", + "Bulleted List": "רשימה לא ממוספרת", + "Decrease Indent": "הקטן כניסה", + "Increase Indent": "הגדל כניסה", + "Font Color": "צבע גופן", + "Background Color": "צבע רקע", + "Horizontal Rule": "קו אנכי", + "Insert Web Link": "הכנס היפר-קישור", + "Insert/Modify Image": "הכנס/שנה תמונה", + "Insert Table": "הכנס טבלה", + "Toggle HTML Source": "שנה מצב קוד HTML", + "Enlarge Editor": "הגדל את העורך", + "About this editor": "אודות עורך זה", + "Help using editor": "עזרה לשימוש בעורך", + "Current style": "סגנון נוכחי", + "Undoes your last action": "מבטל את פעולתך האחרונה", + "Redoes your last action": "מבצע מחדש את הפעולה האחרונה שביטלת", + "Cut selection": "גזור בחירה", + "Copy selection": "העתק בחירה", + "Paste from clipboard": "הדבק מהלוח", + "Direction left to right": "כיוון משמאל לימין", + "Direction right to left": "כיוון מימין לשמאל", + "OK": "אישור", + "Cancel": "ביטול", + "Path": "נתיב עיצוב", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "אתה במצב טקסט נקי (קוד). השתמש בכפתור [<>] כדי לחזור למצב WYSIWYG (תצוגת עיצוב).", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "מצב מסך מלא יוצר בעיות בדפדפן Internet Explorer, עקב באגים בדפדפן לא יכולנו לפתור את זה. את/ה עלול/ה לחוות תצוגת זבל, בעיות בתפקוד העורך ו/או קריסה של הדפדפן. אם המערכת שלך היא Windows 9x סביר להניח שתקבל/י ", + "Cancel": "ביטול", + "Insert/Modify Link": "הוסף/שנה קישור", + "New window (_blank)": "חלון חדש (_blank)", + "None (use implicit)": "ללא (השתמש ב-frame הקיים)", + "Other": "אחר", + "Same frame (_self)": "אותו frame (_self)", + "Target:": "יעד:", + "Title (tooltip):": "כותרת (tooltip):", + "Top frame (_top)": "Frame עליון (_top)", + "URL:": "URL:", + "You must enter the URL where this link points to": "חובה לכתוב URL שאליו קישור זה מצביע" +} diff --git a/xinha/lang/hu.js b/xinha/lang/hu.js new file mode 100644 index 0000000..75c541c --- /dev/null +++ b/xinha/lang/hu.js @@ -0,0 +1,64 @@ +// I18N constants + +// LANG: "hu", ENCODING: UTF-8 +// Author: Miklós Somogyi, + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Félkövér", + "Italic": "Dőlt", + "Underline": "Aláhúzott", + "Strikethrough": "Áthúzott", + "Subscript": "Alsó index", + "Superscript": "Felső index", + "Justify Left": "Balra zárt", + "Justify Center": "Középre zárt", + "Justify Right": "Jobbra zárt", + "Justify Full": "Sorkizárt", + "Ordered List": "Számozott lista", + "Bulleted List": "Számozatlan lista", + "Decrease Indent": "Behúzás csökkentése", + "Increase Indent": "Behúzás növelése", + "Font Color": "Karakterszín", + "Background Color": "Háttérszín", + "Horizontal Rule": "Elválasztó vonal", + "Insert Web Link": "Hiperhivatkozás beszúrása", + "Insert/Modify Image": "Kép beszúrása", + "Insert Table": "Táblázat beszúrása", + "Toggle HTML Source": "HTML forrás be/ki", + "Enlarge Editor": "Szerkesztő külön ablakban", + "About this editor": "Névjegy", + "Help using editor": "Súgó", + "Current style": "Aktuális stílus", + "Undoes your last action": "Visszavonás", + "Redoes your last action": "Újra végrehajtás", + "Cut selection": "Kivágás", + "Copy selection": "Másolás", + "Paste from clipboard": "Beillesztés", + "Direction left to right": "Irány balról jobbra", + "Direction right to left": "Irány jobbról balra", + "OK": "Rendben", + "Cancel": "Mégsem", + "Path": "Hierarchia", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Forrás mód. Visszaváltás [<>] gomb", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "A teljesképrenyős szerkesztés hibát okozhat Internet Explorer használata esetén, ez a böngésző a hibája, amit nem tudunk kikerülni. Szemetet észlelhet a képrenyőn, illetve néhány funkció hiányozhat és/vagy véletlenszerűen lefagyhat a böngésző. Windows 9x operaciós futtatása esetén elég valószínű, hogy ", + "Cancel": "Mégsem", + "Insert/Modify Link": "Hivatkozás Beszúrása/Módosítása", + "New window (_blank)": "Új ablak (_blank)", + "None (use implicit)": "Nincs (use implicit)", + "Other": "Más", + "Same frame (_self)": "Ugyanabba a keretbe (_self)", + "Target:": "Cél:", + "Title (tooltip):": "Cím (tooltip):", + "Top frame (_top)": "Felső keret (_top)", + "URL:": "URL:", + "You must enter the URL where this link points to": "Be kell írnia az URL-t, ahova a hivatkozás mutasson" +} diff --git a/xinha/lang/it.js b/xinha/lang/it.js new file mode 100644 index 0000000..426e74c --- /dev/null +++ b/xinha/lang/it.js @@ -0,0 +1,55 @@ +// I18N constants + +// LANG: "it", ENCODING: UTF-8 +// Author: Mattia Landoni, http://www.webpresident.org/ + +{ + "Bold": "Grassetto", + "Italic": "Corsivo", + "Underline": "Sottolineato", + "Strikethrough": "Barrato", + "Subscript": "Pedice", + "Superscript": "Apice", + "Justify Left": "Sinistra", + "Justify Center": "Centrato", + "Justify Right": "Destra", + "Justify Full": "Giustificato", + "Ordered List": "Lista numerata", + "Bulleted List": "Lista non numerata", + "Decrease Indent": "Diminuisci indentazione", + "Increase Indent": "Aumenta indentazione", + "Font Color": "Colore font", + "Background Color": "Colore sfondo", + "Horizontal Rule": "Righello orizzontale", + "Insert Web Link": "Inserisci link", + "Insert/Modify Image": "Inserisci/modifica Immagine", + "Insert Table": "Inserisci tabella", + "Toggle HTML Source": "Visualizza/nascondi sorgente HTML", + "Enlarge Editor": "Allarga editor", + "About this editor": "Informazioni su HTMLArea", + "Help using editor": "Aiuto", + "Current style": "Stile corrente", + "Undoes your last action": "Annulla ultima azione", + "Redoes your last action": "Ripeti ultima azione", + "Cut selection": "Taglia", + "Copy selection": "Copia", + "Paste from clipboard": "Incolla", + "Direction left to right": "Testo da sx a dx", + "Direction right to left": "Testo da dx a sx", + "OK": "OK", + "Cancel": "Annulla", + "Path": "Percorso", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Sei in MODALITA", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "E", + "Cancel": "Annulla", + "Insert/Modify Link": "Inserisci/modifica link", + "New window (_blank)": "Nuova finestra (_blank)", + "None (use implicit)": "Niente (usa implicito)", + "Other": "Altro", + "Same frame (_self)": "Stessa frame (_self)", + "Target:": "Target:", + "Title (tooltip):": "Title (suggerimento):", + "Top frame (_top)": "Pagina intera (_top)", + "URL:": "URL:", + "You must enter the URL where this link points to": "Devi inserire l'indirizzo a cui punta il link" +} diff --git a/xinha/lang/ja.js b/xinha/lang/ja.js new file mode 100644 index 0000000..dd8adf0 --- /dev/null +++ b/xinha/lang/ja.js @@ -0,0 +1,175 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8N + +{ + "Bold": "太字", + "Italic": "斜体", + "Underline": "下線", + "Strikethrough": "打ち消し線", + "Subscript": "下付き添え字", + "Superscript": "上付き添え字", + "Justify Left": "左寄せ", + "Justify Center": "中央寄せ", + "Justify Right": "右寄せ", + "Justify Full": "均等割付", + "Ordered List": "番号付き箇条書き", + "Bulleted List": "記号付き箇条書き", + "Decrease Indent": "インデント解除", + "Increase Indent": "インデント設定", + "Font Color": "文字色", + "Background Color": "背景色", + "Horizontal Rule": "水平線", + "Insert Web Link": "リンクの挿入", + "Insert/Modify Image": "画像の挿入/修正", + "Insert Table": "テーブルを挿入", + "Toggle HTML Source": "HTML編集モードを切替", + "Enlarge Editor": "エディタを最大化", + "About this editor": "バージョン情報", + "Help using editor": "ヘルプ", + "Current style": "現在のスタイル", + "Undoes your last action": "元に戻す", + "Redoes your last action": "やり直し", + "Cut selection": "切り取り", + "Copy selection": "コピー", + "Paste from clipboard": "貼り付け", + "Direction left to right": "左から右へ", + "Direction right to left": "右から左へ", + "Remove formatting": "書式削除", + "Select all": "すべて選択", + "Print document": "印刷", + "Clear MSOffice tags": "MSOfficeタグをクリア", + "Clear Inline Font Specifications": "インラインフォント指定をクリア", + "Would you like to clear font typefaces?": "フォント名をクリアしますか?", + "Would you like to clear font sizes?": "サイズをクリアしますか?", + "Would you like to clear font colours?": "色をクリアしますか?", + "Split Block": "領域分割", + "Toggle Borders": "境界線の切替", + "Save as": "名前をつけて保存", + "Insert/Overwrite": "挿入/上書き", + "— format —": "— 書式 —", + "Heading 1": "見出し1", + "Heading 2": "見出し2", + "Heading 3": "見出し3", + "Heading 4": "見出し4", + "Heading 5": "見出し5", + "Heading 6": "見出し6", + "Normal": "標準", + "Address": "アドレス", + "Formatted": "整形済み", + "— font —": "— フォント —", + "— size —": "— サイズ —", + + //dialogs + "OK": "OK", + "Cancel": "中止", + "Path": "パス", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "テキストモードで操作しています。WYSIWYG編集に戻るには[<>]ボタンを使ってください。", + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "MozillaベースのWebブラウザでは、貼り付けボタンは機能しません(技術的なセキュリティ上の理由で)。Ctrl+Vキーを押して直接貼り付けてください。", + "Your Document is not well formed. Check JavaScript console for details.": "この文書には構文的な問題があります。詳細はJavaScriptコンソールを参照してください。", + "You need to select some text before creating a link": "リンクを作成するにはテキストを選択する必要があります", + + "Alignment:": "行揃え:", + "Not set": "なし", + "Left": "左", + "Right": "右", + "Texttop": "テキスト上部", + "Absmiddle": "中央(絶対的)", + "Baseline": "ベースライン", + "Absbottom": "下(絶対的)", + "Bottom": "下", + "Middle": "中央", + "Top": "上", + + "Layout": "レイアウト", + "Spacing": "間隔", + "Horizontal:": "水平:", + "Horizontal padding": "水平余白", + "Vertical:": "垂直:", + "Vertical padding": "垂直余白", + "Border thickness:": "境界線の太さ:", + "Leave empty for no border": "境界線がない場合は空のままにする", + + //Insert Link + "Insert/Modify Link": "リンクの挿入/修正", + "None (use implicit)": "なし (デフォルトに任せる)", + "New window (_blank)": "新しいウィンドウ (_blank)", + "Same frame (_self)": "自己フレーム内 (_self)", + "Top frame (_top)": "最上位フレーム (_top)", + "Other": "その他", + "Target:": "ターゲット:", + "Title (tooltip):": "タイトル:", + "URL:": "URL:", + "You must enter the URL where this link points to": "このリンクが指し示すURLを入力してください", + + // Insert Table + "Insert Table": "テーブルの挿入", + "Rows:": "行:", + "Number of rows": "行数", + "Cols:": "列:", + "Number of columns": "列数", + "Width:": "幅:", + "Width of the table": "テーブルの幅", + "Percent": "パーセント(%)", + "Pixels": "ピクセル(px)", + "Em": "相対値(em)", + "Width unit": "幅の単位", + "Fixed width columns": "列の幅を固定", + "Positioning of this table": "このテーブルの配置", + "Cell spacing:": "セル間隔:", + "Space between adjacent cells": "隣接するセル間の距離", + "Cell padding:": "セル余白:", + "Space between content and border in cell": "セル内における内容と境界線との距離", + "You must enter a number of rows": "行数を入力してください", + "You must enter a number of columns": "列数を入力してください", + + // Insert Image + "Insert Image": "画像の挿入", + "Image URL:": "画像URL:", + "Enter the image URL here": "画像のURLをここに入力します", + "Preview": "表示", + "Preview the image in a new window": "ウィンドウで画像を表示", + "Alternate text:": "代替テキスト:", + "For browsers that don't support images": "画像表示をサポートしないブラウザに必要です", + "Positioning of this image": "画像の配置", + "Image Preview:": "画像表示:", + "You must enter the URL": "URLを入力する必要があります", + + //"button_bold": "fr/bold.gif", + //"button_underline": "fr/underline.gif", + //"button_strikethrough": "fr/strikethrough.gif", + + // Editor Help + "Xinha Help": "ヘルプ", + "Editor Help": "エディタのヘルプ", + "Keyboard shortcuts": "キーボードショートカット", + "The editor provides the following key combinations:": "エディタは以下のキー操作を提供しています:", + "ENTER": "ENTER", + "new paragraph": "新規段落", + "SHIFT-ENTER": "SHIFT+ENTER", + "insert linebreak": "段落内改行の挿入", + "Set format to paragraph": "段落書式の設定", + "Clean content pasted from Word": "Wordから貼り付けられた内容の清書", + "Headings": "見出し", + "Close": "閉じる", + + // Loading messages + "Loading in progress. Please wait!": "ロード中です。しばらくお待ちください", + "Loading plugin $plugin" : "ロード中プラグイン $plugin", + "Register plugin $plugin" : "登録中プラグイン $plugin", + "Constructing object": "オブジェクト構築中", + "Generate Xinha framework": "Xinhaフレームワーク生成中", + "Init editor size":"エディタサイズの初期化", + "Create Toolbar": "ツールバーの作成", + "Create Statusbar" : "ステータスバーの作成", + "Register right panel" : "登録 右パネル", + "Register left panel" : "登録 左パネル", + "Register bottom panel" : "登録 下パネル", + "Register top panel" : "登録 上パネル", + "Finishing" : "完了", + + // ColorPicker + "Click a color..." : "色をクリック...", + "Sample" : "サンプル", + "Web Safe: " : "Webセーフ: ", + "Color: " : "色: " +}; \ No newline at end of file diff --git a/xinha/lang/lt.js b/xinha/lang/lt.js new file mode 100644 index 0000000..1235676 --- /dev/null +++ b/xinha/lang/lt.js @@ -0,0 +1,53 @@ +// I18N constants + +// LANG: "lt", ENCODING: UTF-8 +// Author: Jaroslav Šatkevič, + +{ + "Bold": "Paryškinti", + "Italic": "Kursyvas", + "Underline": "Pabraukti", + "Strikethrough": "Perbraukti", + "Subscript": "Apatinis indeksas", + "Superscript": "Viršutinis indeksas", + "Justify Left": "Lygiavimas pagal kairę", + "Justify Center": "Lygiavimas pagal centrą", + "Justify Right": "Lygiavimas pagal dešinę", + "Justify Full": "Lygiuoti pastraipą", + "Ordered List": "Numeruotas sąrašas", + "Bulleted List": "Suženklintas sąrašas", + "Decrease Indent": "Sumažinti paraštę", + "Increase Indent": "Padidinti paraštę", + "Font Color": "Šrifto spalva", + "Background Color": "Fono spalva", + "Horizontal Rule": "Horizontali linija", + "Insert Web Link": "Įterpti nuorodą", + "Insert/Modify Image": "Įterpti paveiksliuką", + "Insert Table": "Įterpti lentelę", + "Toggle HTML Source": "Perjungti į HTML/WYSIWYG", + "Enlarge Editor": "Išplėstas redagavimo ekranas/Enlarge Editor", + "About this editor": "Apie redaktorių", + "Help using editor": "Pagalba naudojant redaktorių", + "Current style": "Dabartinis stilius", + "Undoes your last action": "Atšaukia paskutini jūsų veiksmą", + "Redoes your last action": "Pakartoja paskutinį atšauktą jūsų veiksmą", + "Cut selection": "Iškirpti", + "Copy selection": "Kopijuoti", + "Paste from clipboard": "Įterpti", + "OK": "OK", + "Cancel": "Atšaukti", + "Path": "Kelias", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Jūs esete teksto režime. Naudokite [<>] mygtuką grįžimui į WYSIWYG.", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren", + "Cancel": "Atšaukti", + "Insert/Modify Link": "Idėti/Modifikuoti", + "New window (_blank)": "Naujas langas (_blank)", + "None (use implicit)": "None (use implicit)", + "Other": "Kitas", + "Same frame (_self)": "Same frame (_self)", + "Target:": "Target:", + "Title (tooltip):": "Pavadinimas (tooltip):", + "Top frame (_top)": "Top frame (_top)", + "URL:": "URL:", + "You must enter the URL where this link points to": "Jus privalote nurodyti URL į kuri rodo šitą nuoroda" +} diff --git a/xinha/lang/lv.js b/xinha/lang/lv.js new file mode 100644 index 0000000..b24593d --- /dev/null +++ b/xinha/lang/lv.js @@ -0,0 +1,42 @@ +// I18N constants + +// LANG: "lv", ENCODING: UTF-8 +// Author: Mihai Bazon, http://dynarch.com/mishoo +// Translated by: Janis Klavins, + +{ + "Bold": "Trekniem burtiem", + "Italic": "Kursv", + "Underline": "Pasvtrots", + "Strikethrough": "Prsvtrots", + "Subscript": "Novietot zem rindas", + "Superscript": "Novietot virs rindas", + "Justify Left": "Izldzint pa kreisi", + "Justify Center": "Izldzint centr", + "Justify Right": "Izldzint pa labi", + "Justify Full": "Izldzint pa visu lapu", + "Ordered List": "Numurts saraksts", + "Bulleted List": "Saraksts", + "Decrease Indent": "Samazint atkpi", + "Increase Indent": "Palielint atkpi", + "Font Color": "Burtu krsa", + "Background Color": "Fona krsa", + "Horizontal Rule": "Horizontla atdaltjsvtra", + "Insert Web Link": "Ievietot hipersaiti", + "Insert/Modify Image": "Ievietot attlu", + "Insert Table": "Ievietot tabulu", + "Toggle HTML Source": "Skatt HTML kodu", + "Enlarge Editor": "Palielint Reditju", + "About this editor": "Par o reditju", + "Help using editor": "Reditja palgs", + "Current style": "Patreizjais stils", + "Undoes your last action": "Atcelt pdjo darbbu", + "Redoes your last action": "Atkrtot pdjo darbbu", + "Cut selection": "Izgriezt iezmto", + "Copy selection": "Kopt iezmto", + "Paste from clipboard": "Ievietot iezmto", + "OK": "Labi", + "Cancel": "Atcelt", + "Path": "Ce", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Js patlaban darbojaties TEKSTA REM. Lai prietu atpaka uz GRAFISKO REMU (WYSIWIG), lietojiet [<>] pogu." +} diff --git a/xinha/lang/nb.js b/xinha/lang/nb.js new file mode 100644 index 0000000..6ae0451 --- /dev/null +++ b/xinha/lang/nb.js @@ -0,0 +1,78 @@ +// I18N constants + +// LANG: "nb", ENCODING: UTF-8 + +// - translated by ses +// Additional translations by Håvard Wigtil +// Additional translations by Kim Steinhaug + +{ + "Bold": "Fet", + "Italic": "Kursiv", + "Underline": "Understreket", + "Strikethrough": "Gjennomstreket", + "Subscript": "Nedsenket", + "Superscript": "Opphøyet", + "Justify Left": "Venstrejuster", + "Justify Center": "Midtjuster", + "Justify Right": "Høyrejuster", + "Justify Full": "Blokkjuster", + "Ordered List": "Nummerert liste", + "Bulleted List": "Punktliste", + "Decrease Indent": "Reduser innrykk", + "Increase Indent": "Øke innrykk", + "Font Color": "Tekstfarge", + "Background Color": "Bakgrundsfarge", + "Horizontal Rule": "Vannrett linje", + "Insert Web Link": "Lag lenke", + "Insert/Modify Image": "Sett inn bilde", + "Insert Table": "Sett inn tabell", + "Toggle HTML Source": "Vis kildekode", + "Enlarge Editor": "Vis i eget vindu", + "About this editor": "Om denne editor", + "Help using editor": "Hjelp", + "Current style": "Nåværende stil", + "Undoes your last action": "Angrer siste redigering", + "Redoes your last action": "Gjør om siste angring", + "Cut selection": "Klipp ut område", + "Copy selection": "Kopier område", + "Save as": "Lagre som", + "Paste from clipboard": "Lim inn", + "Remove formatting": "Fjern formattering", + "Direction left to right": "Fra venstre mot høyre", + "Direction right to left": "Fra høyre mot venstre", + "Insert/Overwrite": "Sett inn/Overskriv", + "OK": "OK", + "Cancel": "Avbryt", + "Path": "Tekstvelger", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Du er i tekstmodus Klikk på [<>] for å gå tilbake til WYSIWIG.", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Visning i eget vindu har kjente problemer med Internet Explorer, på grunn av problemer med denne nettleseren. Mulige problemer er et uryddig skjermbilde, manglende editorfunksjoner og/eller at nettleseren crasher. Hvis du bruker Windows 95 eller Windows 98 er det også muligheter for at Windows will crashe.\n\nTrykk ", + "Cancel": "Avbryt", + "Insert/Modify Link": "Rediger lenke", + "New window (_blank)": "Eget vindu (_blank)", + "None (use implicit)": "Ingen (bruk standardinnstilling)", + "Other": "Annen", + "Same frame (_self)": "Samme ramme (_self)", + "Target:": "Mål:", + "Title (tooltip):": "Tittel (tooltip):", + "Top frame (_top)": "Toppramme (_top)", + "URL:": "Adresse:", + "You must enter the URL where this link points to": "Du må skrive inn en adresse som denne lenken skal peke til", + "Clear Inline Font Specifications": "Fjerne inline font spesifikasjoner", + "Would you like to clear font typefaces?": "Ønsker du å fjerne skrifttyper", + "Would you like to clear font sizes?": "Ønsker du å fjerne skrift størrelser", + "Would you like to clear font colours?": "Ønsker du å fjerne farger på skriften", + "Print document": "Skriv ut dokumentet", + "Split Block": "Seperasjonsblokk", + "Toggle Borders": "Skru av/på hjelpelinjer på tabeller", + "Select all": "Merk alt", + // Loading messages + "Loading in progress. Please wait !": "WYSIWYG laster, vennligst vent!", + "Constructing main object": "Vennligst vent", + "Create Toolbar": "Lag verktøylinje", + "Register panel right": "Registrer høyrepanel", + "Register panel left": "Registrer venstrepanel", + "Register panel top": "Registrer toppanel", + "Register panel bottom": "Registrer bunnpanel" + +}; diff --git a/xinha/lang/nl.js b/xinha/lang/nl.js new file mode 100644 index 0000000..3fe6b8c --- /dev/null +++ b/xinha/lang/nl.js @@ -0,0 +1,64 @@ +// I18N constants + +// LANG: "nl", ENCODING: UTF-8 +// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Vet", + "Italic": "Cursief", + "Underline": "Onderstrepen", + "Strikethrough": "Doorhalen", + "Subscript": "Subscript", + "Superscript": "Superscript", + "Justify Left": "Links uitlijnen", + "Justify Center": "Centreren", + "Justify Right": "Rechts uitlijnen", + "Justify Full": "Uitvullen", + "Ordered List": "Nummering", + "Bulleted List": "Opsommingstekens", + "Decrease Indent": "Inspringing verkleinen", + "Increase Indent": "Inspringing vergroten", + "Font Color": "Tekstkleur", + "Background Color": "Achtergrondkleur", + "Horizontal Rule": "Horizontale lijn", + "Insert Web Link": "Hyperlink invoegen/aanpassen", + "Insert/Modify Image": "Afbeelding invoegen/aanpassen", + "Insert Table": "Tabel invoegen", + "Toggle HTML Source": "HTML broncode", + "Enlarge Editor": "Vergroot Editor", + "About this editor": "Over deze editor", + "Help using editor": "HTMLArea help", + "Current style": "Huidige stijl", + "Undoes your last action": "Ongedaan maken", + "Redoes your last action": "Herhalen", + "Cut selection": "Knippen", + "Copy selection": "Kopi?ren", + "Paste from clipboard": "Plakken", + "Direction left to right": "Tekstrichting links naar rechts", + "Direction right to left": "Tekstrichting rechts naar links", + "OK": "OK", + "Cancel": "Annuleren", + "Path": "Pad", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Je bent in TEKST-mode. Gebruik de [<>] knop om terug te keren naar WYSIWYG-mode.", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Fullscreen-mode veroorzaakt problemen met Internet Explorer door bugs in de webbrowser die we niet kunnen omzeilen. Hierdoor kunnen de volgende effecten optreden: verknoeide teksten, een verlies aan editor-functionaliteit en/of willekeurig vastlopen van de webbrowser. Als u Windows 95 of 98 gebruikt, is het zeer waarschijnlijk dat u een algemene beschermingsfout (", + "Cancel": "Annuleren", + "Insert/Modify Link": "Hyperlink invoegen/aanpassen", + "New window (_blank)": "Nieuw venster (_blank)", + "None (use implicit)": "Geen", + "Other": "Ander", + "Same frame (_self)": "Zelfde frame (_self)", + "Target:": "Doel:", + "Title (tooltip):": "Titel (tooltip):", + "Top frame (_top)": "Bovenste frame (_top)", + "URL:": "URL:", + "You must enter the URL where this link points to": "Geef de URL in waar de link naar verwijst" +} diff --git a/xinha/lang/pl.js b/xinha/lang/pl.js new file mode 100644 index 0000000..b5bd5ce --- /dev/null +++ b/xinha/lang/pl.js @@ -0,0 +1,125 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz, http://www.eskot.krakow.pl/portfolio/, koto@webworkers.pl +{ + "Bold": "Pogrubienie", + "Italic": "Pochylenie", + "Underline": "Podkreślenie", + "Strikethrough": "Przekreślenie", + "Subscript": "Indeks dolny", + "Superscript": "Indeks górny", + "Justify Left": "Wyrównaj do lewej", + "Justify Center": "Wyśrodkuj", + "Justify Right": "Wyrównaj do prawej", + "Justify Full": "Wyjustuj", + "Ordered List": "Numerowanie", + "Bulleted List": "Wypunktowanie", + "Decrease Indent": "Zmniejsz wcięcie", + "Increase Indent": "Zwiększ wcięcie", + "Font Color": "Kolor czcionki", + "Background Color": "Kolor tła", + "Horizontal Rule": "Linia pozioma", + "Insert Web Link": "Wstaw adres sieci Web", + "Insert/Modify Image": "Wstaw obraz", + "Insert Table": "Wstaw tabelę", + "Toggle HTML Source": "Edycja WYSIWYG/w źródle strony", + "Enlarge Editor": "Pełny ekran", + "About this editor": "Informacje o tym edytorze", + "Help using editor": "Pomoc", + "Current style": "Obecny styl", + "Undoes your last action": "Cofa ostatnio wykonane polecenie", + "Redoes your last action": "Ponawia ostatnio wykonane polecenie", + "Cut selection": "Wycina zaznaczenie do schowka", + "Copy selection": "Kopiuje zaznaczenie do schowka", + "Paste from clipboard": "Wkleja zawartość schowka", + "Direction left to right": "Kierunek tekstu lewo-prawo", + "Direction right to left": "Kierunek tekstu prawo-lewo", + "Remove formatting": "Usuń formatowanie", + "Select all": "Zaznacz wszystko", + "Print document": "Drukuj dokument", + "Clear MSOffice tags": "Wyczyść tagi MSOffice", + "Clear Inline Font Specifications": "Wycisz bezpośrednie przypisania czcionek", + "Split Block": "Podziel blok", + "Toggle Borders": "Włącz / wyłącz ramki", + + "— format —": "— Format —", + "Heading 1": "Nagłówek 1", + "Heading 2": "Nagłówek 2", + "Heading 3": "Nagłówek 3", + "Heading 4": "Nagłówek 4", + "Heading 5": "Nagłówek 5", + "Heading 6": "Nagłówek 6", + "Normal": "Normalny", + "Address": "Adres", + "Formatted": "Preformatowany", + + //dialogs + "OK": "OK", + "Cancel": "Anuluj", + "Path": "Ścieżka", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Jesteś w TRYBIE TEKSTOWYM. Użyj przycisku [<>], aby przełączyć się na tryb WYSIWYG.", + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Przycisk Wklej nie działa w przeglądarkach Mozilla z uwagi na ustawienia bezpieczeństwa. Naciśnij CRTL-V, aby wkleić zawartość schowka.", + + "Alignment:": "Wyrównanie:", + "Not set": "Nie ustawione", + "Left": "Do lewej", + "Right": "Do prawej", + "Texttop": "Góra tekstu", + "Absmiddle": "Abs. środek", + "Baseline": "Linia bazowa", + "Absbottom": "Abs. dół", + "Bottom": "Dół", + "Middle": "Środek", + "Top": "Góra", + + "Layout": "Layout", + "Spacing": "Spacjowanie", + "Horizontal:": "Poziome:", + "Horizontal padding": "Wcięcie poziome", + "Vertical:": "Pionowe:", + "Vertical padding": "Wcięcie pionowe", + "Border thickness:": "Grubość obramowania:", + "Leave empty for no border": "Bez ramek - zostaw puste", + + //Insert Link + "Insert/Modify Link": "Wstaw/edytuj odnośnik", + "None (use implicit)": "Brak", + "New window (_blank)": "Nowe okno (_blank)", + "Same frame (_self)": "Ta sama ramka (_self)", + "Top frame (_top)": "Główna ramka (_top)", + "Other": "Inne", + "Target:": "Okno docelowe:", + "Title (tooltip):": "Tytuł (tooltip):", + "URL:": "URL:", + "You must enter the URL where this link points to": "Musisz podać URL, na jaki będzie wskazywał odnośnik", + + // Insert Table + "Insert Table": "Wstaw tabelę", + "Rows:": "Wierszy:", + "Number of rows": "Liczba wierszy", + "Cols:": "Kolumn:", + "Number of columns": "Liczba kolumn", + "Width:": "Szerokość:", + "Width of the table": "Szerokość tabeli", + "Percent": "Procent", + "Pixels": "Pikseli", + "Em": "Em", + "Width unit": "Jednostka", + "Fixed width columns": "Kolumny o stałej szerokości", + "Positioning of this table": "Pozycjonowanie tabeli", + "Cell spacing:": "Odstęp komórek:", + "Space between adjacent cells": "Przestrzeń pomiędzy komórkami", + "Cell padding:": "Wcięcie komórek:", + "Space between content and border in cell": "Przestrzeń między krawędzią a zawartością komórki", + + // Insert Image + "Insert Image": "Wstaw obrazek", + "Image URL:": "URL obrazka:", + "Enter the image URL here": "Podaj URL obrazka", + "Preview": "Podgląd", + "Preview the image in a new window": "Podgląd obrazka w nowym oknie", + "Alternate text:": "Tekst alternatywny:", + "For browsers that don't support images": "Dla przeglądarek, które nie obsługują obrazków", + "Positioning of this image": "Pozycjonowanie obrazka", + "Image Preview:": "Podgląd obrazka:" +} diff --git a/xinha/lang/pt_br.js b/xinha/lang/pt_br.js new file mode 100644 index 0000000..156216d --- /dev/null +++ b/xinha/lang/pt_br.js @@ -0,0 +1,32 @@ +// I18N constants + +// LANG: "bt_br", ENCODING: UTF-8 +// Brazilian Portuguese Translation by Alex Piaz + +{ + "Bold": "Negrito", + "Italic": "Itálico", + "Underline": "Sublinhado", + "Strikethrough": "Tachado", + "Subscript": "Subescrito", + "Superscript": "Sobrescrito", + "Justify Left": "Alinhar à Esquerda", + "Justify Center": "Centralizar", + "Justify Right": "Alinhar à Direita", + "Justify Full": "Justificar", + "Ordered List": "Lista Numerada", + "Bulleted List": "Lista Marcadores", + "Decrease Indent": "Diminuir Indentação", + "Increase Indent": "Aumentar Indentação", + "Font Color": "Cor da Fonte", + "Background Color": "Cor do Fundo", + "Horizontal Rule": "Linha Horizontal", + "Insert Web Link": "Inserir Link", + "Insert/Modify Image": "Inserir Imagem", + "Insert Table": "Inserir Tabela", + "Toggle HTML Source": "Ver Código-Fonte", + "Enlarge Editor": "Expandir Editor", + "About this editor": "Sobre", + "Help using editor": "Ajuda", + "Current style": "Estilo Atual" +} diff --git a/xinha/lang/ro.js b/xinha/lang/ro.js new file mode 100644 index 0000000..6565bd2 --- /dev/null +++ b/xinha/lang/ro.js @@ -0,0 +1,63 @@ +// I18N constants + +// LANG: "ro", ENCODING: UTF-8 +// Author: Mihai Bazon, http://dynarch.com/mishoo + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Îngroşat", + "Italic": "Italic", + "Underline": "Subliniat", + "Strikethrough": "Tăiat", + "Subscript": "Indice jos", + "Superscript": "Indice sus", + "Justify Left": "Aliniere la stânga", + "Justify Center": "Aliniere pe centru", + "Justify Right": "Aliniere la dreapta", + "Justify Full": "Aliniere în ambele părţi", + "Ordered List": "Listă ordonată", + "Bulleted List": "Listă marcată", + "Decrease Indent": "Micşorează alineatul", + "Increase Indent": "Măreşte alineatul", + "Font Color": "Culoarea textului", + "Background Color": "Culoare de fundal", + "Horizontal Rule": "Linie orizontală", + "Insert Web Link": "Inserează/modifică link", + "Insert/Modify Image": "Inserează/modifică imagine", + "Insert Table": "Inserează un tabel", + "Toggle HTML Source": "Sursa HTML / WYSIWYG", + "Enlarge Editor": "Maximizează editorul", + "About this editor": "Despre editor", + "Help using editor": "Documentaţie (devel)", + "Current style": "Stilul curent", + "Undoes your last action": "Anulează ultima acţiune", + "Redoes your last action": "Reface ultima acţiune anulată", + "Cut selection": "Taie în clipboard", + "Copy selection": "Copie în clipboard", + "Paste from clipboard": "Aduce din clipboard", + "Direction left to right": "Direcţia de scriere: stânga - dreapta", + "Direction right to left": "Direcţia de scriere: dreapta - stânga", + "OK": "OK", + "Cancel": "Anulează", + "Path": "Calea", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Eşti în modul TEXT. Apasă butonul [<>] pentru a te întoarce în modul WYSIWYG.", + "Cancel": "Renunţă", + "Insert/Modify Link": "Inserează/modifcă link", + "New window (_blank)": "Fereastră nouă (_blank)", + "None (use implicit)": "Nimic (foloseşte ce-i implicit)", + "Other": "Alt target", + "Same frame (_self)": "Aceeaşi fereastră (_self)", + "Target:": "Ţinta:", + "Title (tooltip):": "Titlul (tooltip):", + "Top frame (_top)": "Fereastra principală (_top)", + "URL:": "URL:", + "You must enter the URL where this link points to": "Trebuie să introduceţi un URL" +} diff --git a/xinha/lang/ru.js b/xinha/lang/ru.js new file mode 100644 index 0000000..5290b7f --- /dev/null +++ b/xinha/lang/ru.js @@ -0,0 +1,185 @@ +// I18N constants + +// LANG: "ru", ENCODING: UTF-8 +// Author: Yulya Shtyryakova, + +// Some additions by: Alexey Kirpichnikov, +// I took French version as a source of English phrases because French version was the most comprehensive +// (fr.js was the largest file, actually) %) + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Полужирный", + "Italic": "Наклонный", + "Underline": "Подчеркнутый", + "Strikethrough": "Перечеркнутый", + "Subscript": "Нижний индекс", + "Superscript": "Верхний индекс", + "Justify Left": "По левому краю", + "Justify Center": "По центру", + "Justify Right": "По правому краю", + "Justify Full": "По ширине", + "Ordered List": "Нумерованный список", + "Bulleted List": "Маркированный список", + "Decrease Indent": "Уменьшить отступ", + "Increase Indent": "Увеличить отступ", + "Font Color": "Цвет шрифта", + "Background Color": "Цвет фона", + "Horizontal Rule": "Горизонтальный разделитель", + "Insert Web Link": "Вставить гиперссылку", + "Insert/Modify Image": "Вставить изображение", + "Insert Table": "Вставить таблицу", + "Toggle HTML Source": "Показать Html-код", + "Enlarge Editor": "Увеличить редактор", + "About this editor": "О редакторе", + "Help using editor": "Помощь", + "Current style": "Текущий стиль", + "Undoes your last action": "Отменить", + "Redoes your last action": "Повторить", + "Cut selection": "Вырезать", + "Copy selection": "Копировать", + "Paste from clipboard": "Вставить", + "Direction left to right": "Направление слева направо", + "Direction right to left": "Направление справа налево", + "Remove formatting": "Убрать форматирование", + "Select all": "Выделить все", + "Print document": "Печать", + "Clear MSOffice tags": "Удалить разметку MSOffice", + "Clear Inline Font Specifications": "Удалить непосредственное задание шрифтов", + "Would you like to clear font typefaces?": "Удалить типы шрифтов?", + "Would you like to clear font sizes?": "Удалить размеры шрифтов ?", + "Would you like to clear font colours?": "Удалить цвета шрифтов ?", + "Split Block": "Разделить блок", + "Toggle Borders": "Включить/выключить отображение границ", + "Save as": "Сохранить как", + "Insert/Overwrite": "Вставка/замена", + "— format —": "— форматирование —", + "Heading 1": "Заголовок 1", + "Heading 2": "Заголовок 2", + "Heading 3": "Заголовок 3", + "Heading 4": "Заголовок 4", + "Heading 5": "Заголовок 5", + "Heading 6": "Заголовок 6", + "Normal": "Обычный текст", + "Address": "Адрес", + "Formatted": "Отформатированный текст", + + "— font —": "— шрифт —", + "— size —": "— размер —", + + +// Диалоги + + "OK": "OK", + "Cancel": "Отмена", + "Path": "Путь", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Вы в режиме отображения Html-кода. нажмите кнопку [<>], чтобы переключиться в визуальный режим.", + +"The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Кнопка Вставить не работает в браузерах на основе Mozilla (по техническим причинам, связанным с безопасностью). Нажмите Ctrl-V на клавиатуре, чтобы вставить.", + + "Your Document is not well formed. Check JavaScript console for details.": "Ваш документ неправильно сформирован. Посмотрите Консоль JavaScript, чтобы узнать подробности.", + + "Alignment:": "Выравнивание", + "Not set": "Не установлено", + "Left": "По левому краю", + "Right": "По правому краю", + "Texttop": "По верхней границе текста", + "Absmiddle": "По середине текста", + "Baseline": "По нижней границе текста", + "Absbottom": "По нижней границе", + "Bottom": "По нижнему краю", + "Middle": "Посредине", + "Top": "По верхнему краю", + + "Layout": "Расположение", + "Spacing": "Поля", + "Horizontal:": "По горизонтали", + "Horizontal padding": "Горизонтальные поля", + "Vertical:": "По вертикали", + "Vertical padding": "Вертикальные поля", + "Border thickness:": "Толщина рамки", + "Leave empty for no border": "Оставьте пустым, чтобы убрать рамку", + + //Insert Link + "Insert/Modify Link": "Вставка/изменение ссылки", + "None (use implicit)": "По умолчанию", + "New window (_blank)": "Новое окно (_blank)", + "Same frame (_self)": "То же окно (_self)", + "Top frame (_top)": "Родительское окно (_top)", + "Other": "Другое", + "Target:": "Открывать в окне:", + "Title (tooltip):": "Всплывающая подсказка", + "URL:": "URL:", + "You must enter the URL where this link points to": "Вы должны указать URL, на который будет указывать ссылка", + "You need to select some text before creating a link": "Вы должны выделить текст, который будет преобразован в ссылку", + + // Insert Table + "Insert Table": "Вставка таблицы", + "Rows:": "Строки", + "Number of rows": "Количество строк", + "Cols:": "Столбцы", + "Number of columns": "Количество столбцов", + "Width:": "Ширина", + "Width of the table": "Ширина таблицы", + "Percent": "проценты", + "Pixels": "пикселы", + "Em": "em", + "Width unit": "Единицы измерения", + "Fixed width columns": "Столбцы фиксированной ширины", + "Positioning of this table": "Расположение таблицы", + "Cell spacing:": "Расстояние между ячейками", + "Space between adjacent cells": "Расстояние между соседними ячейками", + "Cell padding:": "Поля в ячейках", + "Space between content and border in cell": "Расстояние между границей ячейки и текстом", + "You must enter a number of rows": "Вы должны ввести количество строк", + "You must enter a number of columns": "Вы должны ввести количество столбцов", + + // Insert Image + "Insert Image": "Вставка изображения", + "Image URL:": "URL изображения", + "Enter the image URL here": "Вставьте адрес изображения", + "Preview": "Предварительный просмотр", + "Preview the image in a new window": "Предварительный просмотр в отдельном окне", + "Alternate text:": "Альтернативный текст", + "For browsers that don't support images": "Для браузеров, которые не отображают картинки", + "Positioning of this image": "Расположение изображения", + "Image Preview:": "Предварительный просмотр", + "You must enter the URL": "Вы должны ввести URL", + + // Editor Help + "Xinha Help": "Помощь", + "Editor Help": "Помощь", + "Keyboard shortcuts": "Горячие клавиши", + "The editor provides the following key combinations:": "Редактор поддерживает следующие комбинации клавиш:", + "ENTER": "ENTER", + "new paragraph": "новый абзац", + "SHIFT-ENTER": "SHIFT+ENTER", + "insert linebreak": "перенос строки", + "Set format to paragraph": "Отформатировать абзац", + "Clean content pasted from Word": "Очистить текст, вставленный из Word", + "Headings": "Заголовки", + "Close": "Закрыть", + + // Loading messages + "Loading in progress. Please wait !": "Загрузка... Пожалуйста, подождите.", + "Constructing main object": "Создание главного объекта", + "Constructing object": "Создание объекта", + "Register panel right": "Регистрация правой панели", + "Register panel left": "Регистрация левой панели", + "Register panel top": "Регистрация верхней панели", + "Register panel bottom": "Регистрация нижней панели", + "Create Toolbar": "Создание панели инструментов", + "Create StatusBar": "Создание панели состояния", + "Generate Xinha object": "Создание объекта Xinha", + "Init editor size": "Инициализация размера редактора", + "Init IFrame": "инициализация iframe", + "Register plugin $plugin": "Регистрация $plugin" +}; diff --git a/xinha/lang/sh.js b/xinha/lang/sh.js new file mode 100644 index 0000000..2706304 --- /dev/null +++ b/xinha/lang/sh.js @@ -0,0 +1,140 @@ +// I18N constants + +// LANG: "sh", ENCODING: UTF-8 | ISO-8859-2 +// Author: Ljuba Ranković, http://www.rankovic.net/ljubar + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Masno", + "Italic": "Kurziv", + "Underline": "Podvučeno", + "Strikethrough": "Precrtano", + "Subscript": "Indeks-tekst", + "Superscript": "Eksponent-tekst", + "Justify Left":"Ravnanje ulevo", + "Justify Center": "Ravnanje po simetrali", + "Justify Right": "Ravnanje udesno", + "Justify Full": "Puno ravnanje", + "Ordered List": "Lista sa rednim brojevima", + "Bulleted List": "Lista sa simbolima", + "Decrease Indent": "smanji uvlačenje", + "Increase Indent": "Povećaj uvlačenje", + "Font Color": "Boja slova", + "Background Color": "Boja pozadine", + "Horizontal Rule": "Horizontalna linija", + "Insert Web Link": "Dodaj web link", + "Insert/Modify Image": "Dodaj/promeni sliku", + "Insert Table": "Ubaci tabelu", + "Toggle HTML Source": "Prebaci na HTML kod", + "Enlarge Editor": "Povećaj editor", + "About this editor": "O ovom editoru", + "Help using editor": "Pomoć pri korišćenju editora", + "Current style": "Važeći stil", + "Undoes your last action": "Poništava poslednju radnju", + "Redoes your last action": "Vraća poslednju radnju", + "Cut selection": "Iseci izabrano", + "Copy selection": "Kopiraj izabrano", + "Paste from clipboard": "Zalepi iz klipborda", + "Direction left to right": "Pravac s leva na desno", + "Direction right to left": "Pravac s desna na levo", + "Remove formatting": "Ukoni formatiranje", + "Select all": "Izaberi sve", + "Print document": "Štampaj dokument", + "Clear MSOffice tags": "Obriši MSOffice tagove", + "Clear Inline Font Specifications": "Obriši dodeljene osobine fonta", + "Split Block": "Podeli blok", + "Toggle Borders": "Izmeni okvire", + + "— format —": "— Format —", + "Heading 1": "Zaglavlje 1", + "Heading 2": "Zaglavlje 2", + "Heading 3": "Zaglavlje 3", + "Heading 4": "Zaglavlje 4", + "Heading 5": "Zaglavlje 5", + "Heading 6": "Zaglavlje 6", + "Normal": "Običan", + "Address": "Adresa", + "Formatted": "Formatiran", + + // dialogs + "OK": "OK", + "Cancel": "Poništi", + "Path": "Putanja", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Nalazite se u TEXT režimu. Koristite [<>] dugme za povratak na WYSIWYG.", + + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "", + + "Alignment:": "Ravnanje", + "Not set": "Nije postavljeno", + "Left": "Levo", + "Right": "Desno", + "Texttop": "Vrh teksta", + "Absmiddle": "Apsolutna sredina", + "Baseline": "Donja linija", + "Absbottom": "Apsolutno dno", + "Bottom": "Dno", + "Middle": "Sredina", + "Top": "Vrh", + + "Layout": "Prelom", + "Spacing": "Razmak", + "Horizontal:": "Po horizontali", + "Horizontal padding": "Horizontalno odstojanje", + "Vertical:": "Po vertikali", + "Vertical padding": "Vertikalno odstojanje", + "Border thickness:": "Debljina okvira", + "Leave empty for no border": "Ostavi prazno kad nema okvira", + + // Insert Link + "Insert/Modify Link": "Dodaj/promeni Link", + "None (use implicit)": "koristi podrazumevano", + "New window (_blank)": "Novom prozoru (_blank)", + "Same frame (_self)": "Isti frejm (_self)", + "Top frame (_top)": "Glavni frejm (_top)", + "Other": "Drugo", + "Target:": "Otvori u:", + "Title (tooltip):": "Naziv (tooltip):", + "URL:": "URL:", + "You must enter the URL where this link points to": "Morate uneti URL na koji vodi ovaj link", + + // Insert Table + "Insert Table": "Ubaci tabelu", + "Rows:": "Redovi", + "Number of rows": "Broj redova", + "Cols:": "Kolone", + "Number of columns": "Broj kolona", + "Width:": "Širina", + "Width of the table": "Širina tabele", + "Percent": "Procenat", + "Pixels": "Pikseli", + "Em": "Em", + "Width unit": "Jedinica širine", + "Fixed width columns": "Fiksirana širina kolona", + "Positioning of this table": "Postavljanje ove tabele", + "Cell spacing:": "Rastojanje ćelija", + "Space between adjacent cells": "Rastojanje naspramnih ćelija", + "Cell padding:": "Unutrašnja odstojanja u ćeliji", + "Space between content and border in cell": "Rastojanje između sadržaja i okvira ćelije", + + // Insert Image + "Insert Image": "Ubaci sliku", + "Image URL:": "URL slike", + "Enter the image URL here": "Unesite URL slike ovde", + "Preview": "Pregled", + "Preview the image in a new window": "Pregledaj sliku u novom prozoru", + "Alternate text:": "Alternativni tekst", + "For browsers that don't support images": "Za pretraživače koji ne podržavaju slike", + "Positioning of this image": "Postavljanje ove slike", + "Image Preview:": "Pregled slike", + + // Select Color popup + "Select Color": "Izaberite boju" +}; diff --git a/xinha/lang/si.js b/xinha/lang/si.js new file mode 100644 index 0000000..90a69b5 --- /dev/null +++ b/xinha/lang/si.js @@ -0,0 +1,50 @@ +// I18N constants + +// LANG: "si", ENCODING: UTF-8 +// Author: Tomaz Kregar, x_tomo_x@email.si + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Krepko", + "Italic": "Ležeče", + "Underline": "Podčrtano", + "Strikethrough": "Prečrtano", + "Subscript": "Podpisano", + "Superscript": "Nadpisano", + "Justify Left": "Poravnaj levo", + "Justify Center": "Na sredino", + "Justify Right": "Poravnaj desno", + "Justify Full": "Porazdeli vsebino", + "Ordered List": "Oštevilčevanje", + "Bulleted List": "Označevanje", + "Decrease Indent": "Zmanjšaj zamik", + "Increase Indent": "Povečaj zamik", + "Font Color": "Barva pisave", + "Background Color": "Barva ozadja", + "Horizontal Rule": "Vodoravna črta", + "Insert Web Link": "Vstavi hiperpovezavo", + "Insert/Modify Image": "Vstavi sliko", + "Insert Table": "Vstavi tabelo", + "Toggle HTML Source": "Preklopi na HTML kodo", + "Enlarge Editor": "Povečaj urejevalnik", + "About this editor": "Vizitka za urejevalnik", + "Help using editor": "Pomoč za urejevalnik", + "Current style": "Trenutni slog", + "Undoes your last action": "Razveljavi zadnjo akcijo", + "Redoes your last action": "Uveljavi zadnjo akcijo", + "Cut selection": "Izreži", + "Copy selection": "Kopiraj", + "Paste from clipboard": "Prilepi", + "OK": "V redu", + "Cancel": "Prekliči", + "Path": "Pot", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Si v tekstovnem načinu. Uporabi [<>] gumb za prklop nazaj na WYSIWYG." +} diff --git a/xinha/lang/sr.js b/xinha/lang/sr.js new file mode 100644 index 0000000..06f78c4 --- /dev/null +++ b/xinha/lang/sr.js @@ -0,0 +1,140 @@ +// I18N constants + +// LANG: "sh", ENCODING: UTF-8 | ISO-8859-5 +// Author: Ljuba Ranković, http://www.rankovic.net/ljubar + +// FOR TRANSLATORS: +// +// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE +// (at least a valid email address) +// +// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING; +// (if this is not possible, please include a comment +// that states what encoding is necessary.) + +{ + "Bold": "Масно", + "Italic": "Курзив", + "Underline": "Подвучено", + "Strikethrough": "Прецртано", + "Subscript": "Индекс-текст", + "Superscript": "Експонент-текст", + "Justify Left": "Равнање улево", + "Justify Center": "Равнање по симетрали", + "Justify Right": "Равнање удесно", + "Justify Full": "Пуно равнање", + "Ordered List": "Листа са редним бројевима", + "Bulleted List": "Листа са симболима", + "Decrease Indent": "Смањи увлачење", + "Increase Indent": "Повећај увлачење", + "Font Color": "Боја слова", + "Background Color": "Боја позадине", + "Horizontal Rule": "Хоризонтална линија", + "Insert Web Link": "додај веб линк", + "Insert/Modify Image": "додај/промени слику", + "Insert Table": "Убаци табелу", + "Toggle HTML Source": "Пребаци на приказ ХТМЛ кода", + "Enlarge Editor": "Повећај едитор", + "About this editor": "О овом едитору", + "Help using editor": "Помоћ при коришћењу едитора", + "Current style": "Важећи стил", + "Undoes your last action": "Поништава последњу радњу", + "Redoes your last action": "Враћа последњу радњу", + "Cut selection": "Исеци изабрано", + "Copy selection": "Копирај изабрано", + "Paste from clipboard": "Залепи из клипборда", + "Direction left to right": "Правац с лева на десно", + "Direction right to left": "Правац с десна на лево", + "Remove formatting": "Уклони форматирање", + "Select all": "Изабери све", + "Print document": "Штампај документ", + "Clear MSOffice tags": "Обриши MSOffice тагове", + "Clear Inline Font Specifications": "Обриши примењене особине фонта", + "Split Block": "Подели блок", + "Toggle Borders": "Пребаци оквирне линије", + + "— format —": "— Format —", + "Heading 1": "Заглавље 1", + "Heading 2": "Заглавље 2", + "Heading 3": "Заглавље 3", + "Heading 4": "Заглавље 4", + "Heading 5": "Заглавље 5", + "Heading 6": "Заглавље 6", + "Normal": "обичан", + "Address": "адреса", + "Formatted": "форматиран", + + // dialogs + "OK": "OK", + "Cancel": "Поништи", + "Path": "Путања", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Налазите се у ТЕКСТ режиму. Користите [<>] дугме за повратак на ШВТИД (WYSIWYG).", + + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Дугме 'залепи' не ради у претраживачима породице Mozilla (из разлога сигурности). Притисните CTRL-V на тастатури да директно залепите.", + + "Alignment:": "Равнање", + "Not set": "Није постављено", + "Left": "Лево", + "Right": "Десно", + "Texttop": "Врх текста", + "Absmiddle": "Апсолутна средина", + "Baseline": "Доња линија", + "Absbottom": "Апсолутно дно", + "Bottom": "Дно", + "Middle": "Средина", + "Top": "Врх", + + "Layout": "Прелом", + "Spacing": "Размак", + "Horizontal:": "По хоризонтали", + "Horizontal padding": "Хортизонтално одстојање", + "Vertical:": "По вертикали", + "Vertical padding": "Вертикално одстојање", + "Border thickness:": "Дебљина оквира", + "Leave empty for no border": "Остави празно кад нема оквира", + + // Insert Link + "Insert/Modify Link": "додај/промени линк", + "None (use implicit)": "користи подразумевано", + "New window (_blank)": "Новом прозору (_blank)", + "Same frame (_self)": "Исти фрејм (_self)", + "Top frame (_top)": "Главни фрејм (_top)", + "Other": "Друго", + "Target:": "Отвори у:", + "Title (tooltip):": "Назив (tooltip):", + "URL:": "УРЛ:", + "You must enter the URL where this link points to": "Морате унети УРЛ на који води овај линк", + + // Insert Table + "Insert Table": "Убаци табелу", + "Rows:": "Редови", + "Number of rows": "Број редова", + "Cols:": "Колоне", + "Number of columns": "Број колона", + "Width:": "Ширина", + "Width of the table": "Ширина табеле", + "Percent": "Процената", + "Pixels": "Пиксела", + "Em": "Ем", + "Width unit": "Јединица ширине", + "Fixed width columns": "Фиксирана ширина колоне", + "Positioning of this table": "Постављање ове табеле", + "Cell spacing:": "Размак између ћелија", + "Space between adjacent cells": "Размак између наспрамних ћелија", + "Cell padding:": "Унутрашња одстојања од ивица ћелије", + "Space between content and border in cell": "Растојање између садржаја у ћелији и њеног оквира", + + // Insert Image + "Insert Image": "Убаци слику", + "Image URL:": "УРЛ слике", + "Enter the image URL here": "Унесите УРЛ слике овде", + "Preview": "Преглед", + "Preview the image in a new window": "Прегледај слику у новом прозору", + "Alternate text:": "алтернативни текст", + "For browsers that don't support images": "За претраживаче који не подржавају слике", + "Positioning of this image": "Постављање ове слике", + "Image Preview:": "Преглед слике", + + // Select Color popup + "Select Color": "Изабери боју" +}; diff --git a/xinha/lang/sv.js b/xinha/lang/sv.js new file mode 100644 index 0000000..61af49e --- /dev/null +++ b/xinha/lang/sv.js @@ -0,0 +1,116 @@ +// I18N constants +// LANG: "sv", ENCODING: UTF-8 + +// Swedish version for htmlArea v3.0 +// Initital translation by pat +// Synced with additional contants in rev. 477 (Mar 2006) by Thomas Loo + +{ + "Bold": "Fet", + "Italic": "Kursiv", + "Underline": "Understruken", + "Strikethrough": "Genomstruken", + "Subscript": "Nedsänkt", + "Superscript": "Upphöjd", + "Justify Left": "Vänsterjustera", + "Justify Center": "Centrera", + "Justify Right": "Högerjustera", + "Justify Full": "Marginaljustera", + "Ordered List": "Numrerad lista", + "Bulleted List": "Punktlista", + "Decrease Indent": "Minska indrag", + "Increase Indent": "Öka indrag", + "Font Color": "Textfärg", + "Background Color": "Bakgrundsfärg", + "Horizontal Rule": "Vågrät linje", + "Insert Web Link": "Infoga länk", + "Insert/Modify Image": "Infoga bild", + "Toggle HTML Source": "Visa källkod", + "Enlarge Editor": "Visa i eget fönster", + "About this editor": "Om denna editor", + "Help using editor": "Hjälp", + "Current style": "Nuvarande stil", + + "Undoes your last action": "Ångra kommando", + "Redoes your last action": "Upprepa kommando", + "Select all": "Markera allt", + "Print document": "Skriv ut", + "Clear MSOffice tags": "Städa bort MS Office taggar", + "Clear Inline Font Specifications": "Rensa inbäddad typsnittsinformation", + "Remove formatting": "Rensa formattering", + "Toggle Borders": "Objektramar", + "Split Block": "Dela block", + "Direction left to right": "Vänster till höger", + "Direction right to left": "Höger till vänster", + + "Insert/Overwrite": "Infoga/Skriv över", + "OK": "OK", + "Cancel": "Avbryt", + "Path": "Objekt", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Du befinner dig i texläge. Klicka på ikonen [<>] ovan för att växla tillbaka till WYSIWIG läge", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Visning i fullskärmsläga fungerar dåligt i din webläsare. Möjliga problem resulterar i en ryckig editor, saknade editorfunktioner och/eller att webläsaren kraschar. Om du använder Windows 95/98 finns också möjligheten att Windows kraschar.\n\nTryck ", + "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Denna knapp fungerar ej i Mozillabaserad webläsare, använd istället snabbtangenterna CTRL-V på tangentbordet för att klistra in.", + + "Insert/Modify Link": "Redigera länk", + "New window (_blank)": "Nytt fönster (_blank)", + "None (use implicit)": "Ingen (använd standardinställing)", + "Other": "Annan", + "Same frame (_self)": "Samma ram (_self)", + "Target:": "Mål:", + "Title (tooltip):": "Titel (tooltip):", + "Top frame (_top)": "Toppram (_top)", + "URL:": "Sökväg:", + "You must enter the URL where this link points to": "Du måsta ange en adress till vilken länken skall peka på", + "Would you like to clear font typefaces?": "Radera alla typsnittsinformation ?", + "Would you like to clear font sizes?": "Radera alla fontstorlekar ?", + "Would you like to clear font colours?": "Ta bort all textfärger ?", + + "You need to select some text before creating a link": "Du måsta markera ett objekt att applicera länken på!", + + // Insert Table + "Insert Table": "Infoga tabell", + "Rows:": "Rader:", + "Number of rows": "Antal rader", + "Cols:": "Kolumner:", + "Number of columns": "Antal kolumner", + "Width:": "Bredd:", + "Width of the table": "Tabellbredd", + "Percent": "Procent", + "Pixels": "Pixlar", + "Em": "", + "Width unit": "Breddenheter", + "Fixed width columns": "Fixerad bredd", + "Alignment:": "Marginaljustering", + "Positioning of this table": "Tabellposition", + "Border thickness:": "Ramtjocklek", + "Leave empty for no border": "Lämna fältet tomt för att undvika ramar", + "Spacing": "Cellegenskaper", + "Cell spacing:": "Cellmarginaler:", + "Space between adjacent cells": "Utrymme mellan celler", + "Cell padding:": "Cellindrag:", + "Space between content and border in cell": "Utrymme mellan ram och cellinnehåll", + "You must enter a number of rows": "Ange ental rader", + "You must enter a number of columns": "Ange antal kolumner", + + // Editor Help + "Keyboard shortcuts": "Snabbtangenter", + "The editor provides the following key combinations:": "Editorn nyttjar följande kombinationer:", + "new paragraph": "Ny paragraf ", + "insert linebreak": "Infoga radbrytning ", + "Set format to paragraph": "Aktivera paragrafläge", + "Clean content pasted from Word": "Rensa innehåll inklistrat från MS Word", + "Headings": "Skapa standardrubrik", + "Cut selection": "Klipp ut markering", + "Copy selection": "Kopiera markering", + "Paste from clipboard": "Klistra in", + "Close": "Stäng", + + // Loading messages + "Loading in progress. Please wait !": "Editorn laddas. Vänta...", + "Constructing main object": "Skapar huvudobjekt", + "Create Toolbar": "Skapar verktygspanel", + "Register panel right": "Registerar panel höger", + "Register panel left": "Registerar panel vänster", + "Register panel top": "Registerar toppanel", + "Register panel bottom": "Registerar fotpanel" +} diff --git a/xinha/lang/vn.js b/xinha/lang/vn.js new file mode 100644 index 0000000..4bdd0d3 --- /dev/null +++ b/xinha/lang/vn.js @@ -0,0 +1,56 @@ +// I18N constants : Vietnamese +// LANG: "en", ENCODING: UTF-8 +// Author: Nguyễn Đình Nam, +// Modified 21/07/2004 by Phạm Mai Quân + +{ + "Bold": "Đậm", + "Italic": "Nghiêng", + "Underline": "Gạch Chân", + "Strikethrough": "Gạch Xóa", + "Subscript": "Viết Xuống Dưới", + "Superscript": "Viết Lên Trên", + "Justify Left": "Căn Trái", + "Justify Center": "Căn Giữa", + "Justify Right": "Căn Phải", + "Justify Full": "Căn Đều", + "Ordered List": "Danh Sách Có Thứ Tự (1, 2, 3)", + "Bulleted List": "Danh Sách Phi Thứ Tự (Chấm đầu dòng)", + "Decrease Indent": "Lùi Ra Ngoài", + "Increase Indent": "Thụt Vào Trong", + "Font Color": "Màu Chữ", + "Background Color": "Màu Nền", + "Horizontal Rule": "Dòng Kẻ Ngang", + "Insert Web Link": "Tạo Liên Kết", + "Insert/Modify Image": "Chèn Ảnh", + "Insert Table": "Chèn Bảng", + "Toggle HTML Source": "Chế Độ Mã HTML", + "Enlarge Editor": "Phóng To Ô Soạn Thảo", + "About this editor": "Tự Giới Thiệu", + "Help using editor": "Giúp Đỡ", + "Current style": "Định Dạng Hiện Thời", + "Undoes your last action": "Hủy thao tác trước", + "Redoes your last action": "Lấy lại thao tác vừa bỏ", + "Cut selection": "Cắt", + "Copy selection": "Sao chép", + "Paste from clipboard": "Dán", + "Direction left to right": "Viết từ trái sang phải", + "Direction right to left": "Viết từ phải sang trái", + "OK": "Đồng ý", + "Cancel": "Hủy", + "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Chế độ phóng to ô soạn thảo có thể gây lỗi với Internet Explorer vì một số lỗi của trình duyệt này, vì thế chế độ này có thể sẽ không chạy. Hiển thị không đúng, lộn xộn, không có đầy đủ chức năng, và cũng có thể làm trình duyệt của bạn bị tắt ngang. Nếu bạn đang sử dụng Windows 9x bạn có thể bị báo lỗi ", + "Path": "Đường Dẫn", + "You are in TEXT MODE. Use the [<>] button to switch back to WYSIWYG.": "Bạn đang ở chế độ text. Sử dụng nút [<>] để chuyển lại chế độ WYSIWIG.", + "Cancel": "Hủy", + "Insert/Modify Link": "Thêm/Chỉnh sửa đường dẫn", + "New window (_blank)": "Cửa sổ mới (_blank)", + "None (use implicit)": "Không (sử dụng implicit)", + "OK": "Đồng ý", + "Other": "Khác", + "Same frame (_self)": "Trên cùng khung (_self)", + "Target:": "Nơi hiện thị:", + "Title (tooltip):": "Tiêu đề (của hướng dẫn):", + "Top frame (_top)": "Khung trên cùng (_top)", + "URL:": "URL:", + "You must enter the URL where this link points to": "Bạn phải điền địa chỉ (URL) mà đường dẫn sẽ liên kết tới" +} diff --git a/xinha/license.txt b/xinha/license.txt new file mode 100644 index 0000000..e7798cf --- /dev/null +++ b/xinha/license.txt @@ -0,0 +1,30 @@ +htmlArea License (based on BSD license) +Copyright (c) 2002-2004, interactivetools.com, inc. +Copyright (c) 2003-2004 dynarch.com +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1) Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2) Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3) Neither the name of interactivetools.com, inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/xinha/modules/ColorPicker/ColorPicker.js b/xinha/modules/ColorPicker/ColorPicker.js new file mode 100644 index 0000000..45535ee --- /dev/null +++ b/xinha/modules/ColorPicker/ColorPicker.js @@ -0,0 +1,590 @@ +ColorPicker._pluginInfo={name:"colorPicker",version:"1.0",developer:"James Sleeman",developer_url:"http://www.gogo.co.nz/",c_owner:"Gogo Internet Services",license:"htmlArea",sponsor:"Gogo Internet Services",sponsor_url:"http://www.gogo.co.nz/"}; +function ColorPicker(){ +} +if(window.opener&&window.opener.Xinha){ +var openerColorPicker=window.opener.Xinha.colorPicker; +Xinha._addEvent(window,"unload",function(){ +Xinha.colorPicker=openerColorPicker; +}); +} +Xinha.colorPicker=function(_1){ +if(Xinha.colorPicker.savedColors.length===0){ +Xinha.colorPicker.loadColors(); +} +var _2=this; +var _3=false; +var _4=false; +var _5=0; +var _6=0; +this.callback=_1.callback?_1.callback:function(_7){ +alert("You picked "+_7); +}; +this.websafe=_1.websafe?_1.websafe:false; +this.savecolors=_1.savecolors?_1.savecolors:20; +this.cellsize=parseInt(_1.cellsize?_1.cellsize:"10px",10); +this.side=_1.granularity?_1.granularity:18; +var _8=this.side+1; +var _9=this.side-1; +this.value=1; +this.saved_cells=null; +this.table=document.createElement("table"); +this.table.className="dialog"; +this.table.cellSpacing=this.table.cellPadding=0; +this.table.onmouseup=function(){ +_3=false; +_4=false; +}; +this.tbody=document.createElement("tbody"); +this.table.appendChild(this.tbody); +this.table.style.border="1px solid WindowFrame"; +this.table.style.zIndex="1050"; +var tr=document.createElement("tr"); +var td=document.createElement("td"); +td.colSpan=this.side; +td.className="title"; +td.style.fontFamily="small-caption,caption,sans-serif"; +td.style.fontSize="x-small"; +td.unselectable="on"; +td.style.MozUserSelect="none"; +td.style.cursor="default"; +td.appendChild(document.createTextNode(Xinha._lc("Click a color..."))); +td.style.borderBottom="1px solid WindowFrame"; +tr.appendChild(td); +td=null; +var td=document.createElement("td"); +td.className="title"; +td.colSpan=2; +td.style.fontFamily="Tahoma,Verdana,sans-serif"; +td.style.borderBottom="1px solid WindowFrame"; +td.style.paddingRight="0"; +tr.appendChild(td); +var _c=document.createElement("div"); +_c.title=Xinha._lc("Close"); +_c.className="buttonColor"; +_c.style.height="11px"; +_c.style.width="11px"; +_c.style.cursor="pointer"; +_c.onclick=function(){ +_2.close(); +}; +_c.appendChild(document.createTextNode("\xd7")); +_c.align="center"; +_c.style.verticalAlign="top"; +_c.style.position="relative"; +_c.style.cssFloat="right"; +_c.style.styleFloat="right"; +_c.style.padding="0"; +_c.style.margin="2px"; +_c.style.backgroundColor="transparent"; +_c.style.fontSize="11px"; +if(!Xinha.is_ie){ +_c.style.lineHeight="9px"; +} +_c.style.letterSpacing="0"; +td.appendChild(_c); +this.tbody.appendChild(tr); +_c=tr=td=null; +this.constrain_cb=document.createElement("input"); +this.constrain_cb.type="checkbox"; +this.chosenColor=document.createElement("input"); +this.chosenColor.type="text"; +this.chosenColor.maxLength=7; +this.chosenColor.style.width="50px"; +this.chosenColor.style.fontSize="11px"; +this.chosenColor.onchange=function(){ +if(/#[0-9a-f]{6,6}/i.test(this.value)){ +_2.backSample.style.backgroundColor=this.value; +_2.foreSample.style.color=this.value; +} +}; +this.backSample=document.createElement("div"); +this.backSample.appendChild(document.createTextNode("\xa0")); +this.backSample.style.fontWeight="bold"; +this.backSample.style.fontFamily="small-caption,caption,sans-serif"; +this.backSample.fontSize="x-small"; +this.foreSample=document.createElement("div"); +this.foreSample.appendChild(document.createTextNode(Xinha._lc("Sample"))); +this.foreSample.style.fontWeight="bold"; +this.foreSample.style.fontFamily="small-caption,caption,sans-serif"; +this.foreSample.fontSize="x-small"; +function toHex(_d){ +var h=_d.toString(16); +if(h.length<2){ +h="0"+h; +} +return h; +} +function tupleToColor(_f){ +return "#"+toHex(_f.red)+toHex(_f.green)+toHex(_f.blue); +} +function nearestPowerOf(num,_11){ +return Math.round(Math.round(num/_11)*_11); +} +function doubleHexDec(dec){ +return parseInt(dec.toString(16)+dec.toString(16),16); +} +function rgbToWebsafe(_13){ +_13.red=doubleHexDec(nearestPowerOf(parseInt(toHex(_13.red).charAt(0),16),3)); +_13.blue=doubleHexDec(nearestPowerOf(parseInt(toHex(_13.blue).charAt(0),16),3)); +_13.green=doubleHexDec(nearestPowerOf(parseInt(toHex(_13.green).charAt(0),16),3)); +return _13; +} +function hsvToRGB(h,s,v){ +var _17; +if(s===0){ +_17={red:v,green:v,blue:v}; +}else{ +h/=60; +var i=Math.floor(h); +var f=h-i; +var p=v*(1-s); +var q=v*(1-s*f); +var t=v*(1-s*(1-f)); +switch(i){ +case 0: +_17={red:v,green:t,blue:p}; +break; +case 1: +_17={red:q,green:v,blue:p}; +break; +case 2: +_17={red:p,green:v,blue:t}; +break; +case 3: +_17={red:p,green:q,blue:v}; +break; +case 4: +_17={red:t,green:p,blue:v}; +break; +default: +_17={red:v,green:p,blue:q}; +break; +} +} +_17.red=Math.ceil(_17.red*255); +_17.green=Math.ceil(_17.green*255); +_17.blue=Math.ceil(_17.blue*255); +return _17; +} +var _1d=this; +function closeOnBodyClick(ev){ +ev=ev?ev:window.event; +el=ev.target?ev.target:ev.srcElement; +do{ +if(el==_1d.table){ +return; +} +}while(el=el.parentNode); +_1d.close(); +} +this.open=function(_1f,_20,_21){ +this.table.style.display=""; +this.pick_color(); +if(_21&&/#[0-9a-f]{6,6}/i.test(_21)){ +this.chosenColor.value=_21; +this.backSample.style.backgroundColor=_21; +this.foreSample.style.color=_21; +} +Xinha._addEvent(document.body,"mousedown",closeOnBodyClick); +this.table.style.position="absolute"; +var e=_20; +var top=0; +var _24=0; +do{ +top+=e.offsetTop; +_24+=e.offsetLeft; +e=e.offsetParent; +}while(e); +var x,y; +if(/top/.test(_1f)||(top+this.table.offsetHeight>document.body.offsetHeight)){ +if(top-this.table.offsetHeight>0){ +this.table.style.top=(top-this.table.offsetHeight)+"px"; +}else{ +this.table.style.top=0; +} +}else{ +this.table.style.top=(top+_20.offsetHeight)+"px"; +} +if(/left/.test(_1f)||(_24+this.table.offsetWidth>document.body.offsetWidth)){ +if(_24-(this.table.offsetWidth-_20.offsetWidth)>0){ +this.table.style.left=(_24-(this.table.offsetWidth-_20.offsetWidth))+"px"; +}else{ +this.table.style.left=0; +} +}else{ +this.table.style.left=_24+"px"; +} +}; +function pickCell(_26){ +_2.chosenColor.value=_26.colorCode; +_2.backSample.style.backgroundColor=_26.colorCode; +_2.foreSample.style.color=_26.colorCode; +if((_26.hue>=195&&_26.saturation>0.5)||(_26.hue===0&&_26.saturation===0&&_26.value<0.5)||(_26.hue!==0&&_2.value<0.75)){ +_26.style.borderColor="#fff"; +}else{ +_26.style.borderColor="#000"; +} +_5=_26.thisrow; +_6=_26.thiscol; +} +function pickValue(_27){ +if(_2.value<0.5){ +_27.style.borderColor="#fff"; +}else{ +_27.style.borderColor="#000"; +} +_9=_27.thisrow; +_8=_27.thiscol; +_2.chosenColor.value=_2.saved_cells[_5][_6].colorCode; +_2.backSample.style.backgroundColor=_2.saved_cells[_5][_6].colorCode; +_2.foreSample.style.color=_2.saved_cells[_5][_6].colorCode; +} +function unpickCell(row,col){ +_2.saved_cells[row][col].style.borderColor=_2.saved_cells[row][col].colorCode; +} +this.pick_color=function(){ +var _2a,cols; +var _2b=this; +var _2c=359/(this.side); +var _2d=1/(this.side-1); +var _2e=1/(this.side-1); +var _2f=this.constrain_cb.checked; +if(this.saved_cells===null){ +this.saved_cells=[]; +for(var row=0;row=195&&_41.saturation>0.5)||(_41.hue===0&&_41.saturation===0&&_41.value<0.5)||(_41.hue!==0&&_2b.value<0.75)){ +_41.style.borderColor="#fff"; +}else{ +_41.style.borderColor="#000"; +} +} +}; +this.close=function(){ +Xinha._removeEvent(document.body,"mousedown",closeOnBodyClick); +this.table.style.display="none"; +}; +}; +Xinha.colorPicker.savedColors=[]; +Xinha.colorPicker.remember=function(_42,_43){ +for(var i=Xinha.colorPicker.savedColors.length;i--;){ +if(Xinha.colorPicker.savedColors[i]==_42){ +return false; +} +} +Xinha.colorPicker.savedColors.splice(0,0,_42); +Xinha.colorPicker.savedColors=Xinha.colorPicker.savedColors.slice(0,_43); +var _45=new Date(); +_45.setMonth(_45.getMonth()+1); +document.cookie="XinhaColorPicker="+escape(Xinha.colorPicker.savedColors.join("-"))+";expires="+_45.toGMTString(); +return true; +}; +Xinha.colorPicker.loadColors=function(){ +var _46=document.cookie.indexOf("XinhaColorPicker"); +if(_46!=-1){ +var _47=(document.cookie.indexOf("=",_46)+1); +var end=document.cookie.indexOf(";",_46); +if(end==-1){ +end=document.cookie.length; +} +Xinha.colorPicker.savedColors=unescape(document.cookie.substring(_47,end)).split("-"); +} +}; +Xinha.colorPicker._lc=function(_49){ +return Xinha._lc(_49); +}; +Xinha.colorPicker.InputBinding=function(_4a,_4b){ +var _4c=document.createElement("span"); +_4c.className="buttonColor"; +var _4d=this.chooser=document.createElement("span"); +_4d.className="chooser"; +if(_4a.value){ +_4d.style.backgroundColor=_4a.value; +} +_4d.onmouseover=function(){ +_4d.className="chooser buttonColor-hilite"; +}; +_4d.onmouseout=function(){ +_4d.className="chooser"; +}; +_4d.appendChild(document.createTextNode("\xa0")); +_4c.appendChild(_4d); +var _4e=document.createElement("span"); +_4e.className="nocolor"; +_4e.onmouseover=function(){ +_4e.className="nocolor buttonColor-hilite"; +_4e.style.color="#f00"; +}; +_4e.onmouseout=function(){ +_4e.className="nocolor"; +_4e.style.color="#000"; +}; +_4e.onclick=function(){ +_4a.value=""; +_4d.style.backgroundColor=""; +}; +_4e.appendChild(document.createTextNode("\xd7")); +_4c.appendChild(_4e); +_4a.parentNode.insertBefore(_4c,_4a.nextSibling); +Xinha._addEvent(_4a,"change",function(){ +_4d.style.backgroundColor=this.value; +}); +_4b=(_4b)?Xinha.cloneObject(_4b):{cellsize:"5px"}; +_4b.callback=(_4b.callback)?_4b.callback:function(_4f){ +_4d.style.backgroundColor=_4f; +_4a.value=_4f; +}; +_4d.onclick=function(){ +var _50=new Xinha.colorPicker(_4b); +_50.open("",_4d,_4a.value); +}; +}; + diff --git a/xinha/modules/CreateLink/link.html b/xinha/modules/CreateLink/link.html new file mode 100644 index 0000000..adad400 --- /dev/null +++ b/xinha/modules/CreateLink/link.html @@ -0,0 +1,136 @@ + + + + Insert/Modify Link + + + + + + + + +
    Insert/Modify Link
    +
    + + + + + + + + + + + + + +
    URL:
    Title (tooltip):
    Target: + +
    + +
    + + +
    +
    + + \ No newline at end of file diff --git a/xinha/modules/CreateLink/link.js b/xinha/modules/CreateLink/link.js new file mode 100644 index 0000000..e1d4cb0 --- /dev/null +++ b/xinha/modules/CreateLink/link.js @@ -0,0 +1,84 @@ +CreateLink._pluginInfo={name:"CreateLink",origin:"Xinha Core",version:"$LastChangedRevision: 694 $".replace(/^[^:]*: (.*) \$$/,"$1"),developer:"The Xinha Core Developer Team",developer_url:"$HeadURL: http://svn.xinha.python-hosting.com/trunk/modules/CreateLink/link.js $".replace(/^[^:]*: (.*) \$$/,"$1"),sponsor:"",sponsor_url:"",license:"htmlArea"}; +function CreateLink(_1){ +} +Xinha.prototype._createLink=function(_2){ +var _3=this; +var _4=null; +if(typeof _2=="undefined"){ +_2=this.getParentElement(); +if(_2){ +while(_2&&!/^a$/i.test(_2.tagName)){ +_2=_2.parentNode; +} +} +} +if(!_2){ +var _5=_3.getSelection(); +var _6=_3.createRange(_5); +var _7=0; +if(Xinha.is_ie){ +if(_5.type=="Control"){ +_7=_6.length; +}else{ +_7=_6.compareEndPoints("StartToEnd",_6); +} +}else{ +_7=_6.compareBoundaryPoints(_6.START_TO_END,_6); +} +if(_7===0){ +alert(Xinha._lc("You need to select some text before creating a link")); +return; +} +_4={f_href:"",f_title:"",f_target:"",f_usetarget:_3.config.makeLinkShowsTarget}; +}else{ +_4={f_href:Xinha.is_ie?_3.stripBaseURL(_2.href):_2.getAttribute("href"),f_title:_2.title,f_target:_2.target,f_usetarget:_3.config.makeLinkShowsTarget}; +} +Dialog(_3.config.URIs.link,function(_8){ +if(!_8){ +return false; +} +var a=_2; +if(!a){ +try{ +var _a=Xinha.uniq("http://www.example.com/Link"); +_3._doc.execCommand("createlink",false,_a); +var _b=_3._doc.getElementsByTagName("a"); +for(var i=0;i<_b.length;i++){ +var _d=_b[i]; +if(_d.href==_a){ +if(!a){ +a=_d; +} +_d.href=_8.f_href; +if(_8.f_target){ +_d.target=_8.f_target; +} +if(_8.f_title){ +_d.title=_8.f_title; +} +} +} +} +catch(ex){ +} +}else{ +var _e=_8.f_href.trim(); +_3.selectNodeContents(a); +if(_e===""){ +_3._doc.execCommand("unlink",false,null); +_3.updateToolbar(); +return false; +}else{ +a.href=_e; +} +} +if(!(a&&a.tagName.toLowerCase()=="a")){ +return false; +} +a.target=_8.f_target.trim(); +a.title=_8.f_title.trim(); +_3.selectNodeContents(a); +_3.updateToolbar(); +},_4); +}; + diff --git a/xinha/modules/Dialogs/dialog.js b/xinha/modules/Dialogs/dialog.js new file mode 100644 index 0000000..fcb57d5 --- /dev/null +++ b/xinha/modules/Dialogs/dialog.js @@ -0,0 +1,62 @@ +function Dialog(_1,_2,_3){ +if(typeof _3=="undefined"){ +_3=window; +} +Dialog._geckoOpenModal(_1,_2,_3); +} +Dialog._parentEvent=function(ev){ +setTimeout(function(){ +if(Dialog._modal&&!Dialog._modal.closed){ +Dialog._modal.focus(); +} +},50); +try{ +if(Dialog._modal&&!Dialog._modal.closed){ +Xinha._stopEvent(ev); +} +} +catch(e){ +} +}; +Dialog._return=null; +Dialog._modal=null; +Dialog._arguments=null; +Dialog._geckoOpenModal=function(_5,_6,_7){ +var _8=window.open(_5,"hadialog","toolbar=no,menubar=no,personalbar=no,width=10,height=10,"+"scrollbars=no,resizable=yes,modal=yes,dependable=yes"); +Dialog._modal=_8; +Dialog._arguments=_7; +function capwin(w){ +Xinha._addEvent(w,"click",Dialog._parentEvent); +Xinha._addEvent(w,"mousedown",Dialog._parentEvent); +Xinha._addEvent(w,"focus",Dialog._parentEvent); +} +function relwin(w){ +Xinha._removeEvent(w,"click",Dialog._parentEvent); +Xinha._removeEvent(w,"mousedown",Dialog._parentEvent); +Xinha._removeEvent(w,"focus",Dialog._parentEvent); +} +capwin(window); +for(var i=0;i(.*?)<\/l10n>/ig,function(_9,_a){ +return _4._lc(_a); +}).replace(/="_\((.*?)\)"/g,function(_b,_c){ +return "=\""+_4._lc(_c)+"\""; +}); +this.rootElem.innerHTML=_2; +this.editor.notifyOn("resize",function(e,_e){ +_4.rootElem.style.width=_4.width=_4.editor._framework.ed_cell.offsetWidth+"px"; +_4.rootElem.style.height=_4.height=_4.editor._framework.ed_cell.offsetHeight+"px"; +_4.onresize(); +}); +}; +Xinha.Dialog.prototype.onresize=function(){ +return true; +}; +Xinha.Dialog.prototype.show=function(_f){ +if(Xinha.is_ie){ +this._lastRange=this.editor._createRange(this.editor._getSelection()); +} +if(typeof _f!="undefined"){ +this.setValues(_f); +} +this._restoreTo=[this.editor._textArea.style.display,this.editor._iframe.style.visibility,this.editor.hidePanels()]; +this.editor._textArea.style.display="none"; +this.editor._iframe.style.visibility="hidden"; +this.rootElem.style.display=""; +}; +Xinha.Dialog.prototype.hide=function(){ +this.rootElem.style.display="none"; +this.editor._textArea.style.display=this._restoreTo[0]; +this.editor._iframe.style.visibility=this._restoreTo[1]; +this.editor.showPanels(this._restoreTo[2]); +if(Xinha.is_ie){ +this._lastRange.select(); +} +this.editor.updateToolbar(); +return this.getValues(); +}; +Xinha.Dialog.prototype.toggle=function(){ +if(this.rootElem.style.display=="none"){ +this.show(); +}else{ +this.hide(); +} +}; +Xinha.Dialog.prototype.setValues=function(_10){ +for(var i in _10){ +var _12=this.getElementsByName(i); +if(!_12){ +continue; +} +for(var x=0;x<_12.length;x++){ +var e=_12[x]; +switch(e.tagName.toLowerCase()){ +case "select": +for(var j=0;j=0){ +v=i.options[i.selectedIndex]; +} +} +break; +case "textarea": +case "input": +default: +switch(i.type.toLowerCase()){ +case "radio": +if(i.checked){ +v=i.value; +break; +} +case "checkbox": +if(v==null){ +if(this.getElementsByName(this.r_id[i.name]).length>1){ +v=new Array(); +} +} +if(i.checked){ +if(v!=null&&typeof v=="object"&&v.push){ +v.push(i.value); +}else{ +v=i.value; +} +} +break; +default: +v=i.value; +break; +} +} +_17[this.r_id[i.name]]=v; +} +return _17; +}; +Xinha.Dialog.prototype.getElementById=function(id){ +return this.document.getElementById(this.id[id]?this.id[id]:id); +}; +Xinha.Dialog.prototype.getElementsByName=function(_1e){ +return this.document.getElementsByName(this.id[_1e]?this.id[_1e]:_1e); +}; + diff --git a/xinha/modules/Dialogs/panel-dialog.js b/xinha/modules/Dialogs/panel-dialog.js new file mode 100644 index 0000000..321dac0 --- /dev/null +++ b/xinha/modules/Dialogs/panel-dialog.js @@ -0,0 +1,76 @@ + +Xinha.PanelDialog = function(editor, side, html, localizer) +{ + this.id = { }; + this.r_id = { }; // reverse lookup id + this.editor = editor; + this.document = document; + this.rootElem = editor.addPanel(side); + + var dialog = this; + if(typeof localizer == 'function') + { + this._lc = localizer; + } + else if(localizer) + { + this._lc = function(string) + { + return Xinha._lc(string,localizer); + }; + } + else + { + this._lc = function(string) + { + return string; + }; + } + + html = html.replace(/\[([a-z0-9_]+)\]/ig, + function(fullString, id) + { + if(typeof dialog.id[id] == 'undefined') + { + dialog.id[id] = Xinha.uniq('Dialog'); + dialog.r_id[dialog.id[id]] = id; + } + return dialog.id[id]; + } + ).replace(/(.*?)<\/l10n>/ig, + function(fullString,translate) + { + return dialog._lc(translate) ; + } + ).replace(/="_\((.*?)\)"/g, + function(fullString, translate) + { + return '="' + dialog._lc(translate) + '"'; + } + ); + + this.rootElem.innerHTML = html; +}; + +Xinha.PanelDialog.prototype.show = function(values) +{ + this.editor.showPanel(this.rootElem); +}; + +Xinha.PanelDialog.prototype.hide = function() +{ + this.editor.hidePanel(this.rootElem); + return this.getValues(); +}; + +Xinha.PanelDialog.prototype.onresize = Xinha.Dialog.prototype.onresize; + +Xinha.PanelDialog.prototype.toggle = Xinha.Dialog.prototype.toggle; + +Xinha.PanelDialog.prototype.setValues = Xinha.Dialog.prototype.setValues; + +Xinha.PanelDialog.prototype.getValues = Xinha.Dialog.prototype.getValues; + +Xinha.PanelDialog.prototype.getElementById = Xinha.Dialog.prototype.getElementById; + +Xinha.PanelDialog.prototype.getElementsByName = Xinha.Dialog.prototype.getElementsByName; \ No newline at end of file diff --git a/xinha/modules/Dialogs/popupwin.js b/xinha/modules/Dialogs/popupwin.js new file mode 100644 index 0000000..21c9ab9 --- /dev/null +++ b/xinha/modules/Dialogs/popupwin.js @@ -0,0 +1,120 @@ +function PopupWin(_1,_2,_3,_4){ +this.editor=_1; +this.handler=_3; +var _5=window.open("","__ha_dialog","toolbar=no,menubar=no,personalbar=no,width=600,height=600,left=20,top=40,scrollbars=no,resizable=yes"); +this.window=_5; +var _6=_5.document; +this.doc=_6; +var _7=this; +var _8=document.baseURI||document.URL; +if(_8&&_8.match(/(.*)\/([^\/]+)/)){ +_8=RegExp.$1+"/"; +} +if(typeof _editor_url!="undefined"&&!(/^\//.test(_editor_url))&&!(/http:\/\//.test(_editor_url))){ +_8+=_editor_url; +}else{ +_8=_editor_url; +} +if(!(/\/$/.test(_8))){ +_8+="/"; +} +this.baseURL=_8; +_6.open(); +var _9=""+_2+"\n"; +_9+="\n"; +if(_editor_skin!=""){ +_9+="\n"; +} +_9+="\n"; +_9+=""; +_6.write(_9); +_6.close(); +function init2(){ +var _a=_6.body; +if(!_a){ +setTimeout(init2,25); +return false; +} +_5.title=_2; +_6.documentElement.style.padding="0px"; +_6.documentElement.style.margin="0px"; +var _b=_6.createElement("div"); +_b.className="content"; +_7.content=_b; +_a.appendChild(_b); +_7.element=_a; +_4(_7); +_5.focus(); +} +init2(); +} +PopupWin.prototype.callHandler=function(){ +var _c=["input","textarea","select"]; +var _d={}; +for(var ti=_c.length;--ti>=0;){ +var _f=_c[ti]; +var els=this.content.getElementsByTagName(_f); +for(var j=0;j +{ + "Maximize/Minimize Editor": "Maximera/Minimera WYSIWYG fönster" +}; diff --git a/xinha/modules/Gecko/Gecko.js b/xinha/modules/Gecko/Gecko.js new file mode 100644 index 0000000..ce584c6 --- /dev/null +++ b/xinha/modules/Gecko/Gecko.js @@ -0,0 +1,413 @@ +Gecko._pluginInfo={name:"Gecko",origin:"Xinha Core",version:"$LastChangedRevision: 808 $".replace(/^[^:]*: (.*) \$$/,"$1"),developer:"The Xinha Core Developer Team",developer_url:"$HeadURL: http://svn.xinha.python-hosting.com/trunk/modules/Gecko/Gecko.js $".replace(/^[^:]*: (.*) \$$/,"$1"),sponsor:"",sponsor_url:"",license:"htmlArea"}; +function Gecko(_1){ +this.editor=_1; +_1.Gecko=this; +} +Gecko.prototype.onKeyPress=function(ev){ +var _3=this.editor; +var s=_3.getSelection(); +if(_3.isShortCut(ev)){ +switch(_3.getKey(ev).toLowerCase()){ +case "z": +if(_3._unLink&&_3._unlinkOnUndo){ +Xinha._stopEvent(ev); +_3._unLink(); +_3.updateToolbar(); +return true; +} +break; +case "a": +sel=_3.getSelection(); +sel.removeAllRanges(); +range=_3.createRange(); +range.selectNodeContents(_3._doc.body); +sel.addRange(range); +Xinha._stopEvent(ev); +return true; +break; +case "v": +if(!_3.config.htmlareaPaste){ +return true; +} +break; +} +} +switch(_3.getKey(ev)){ +case " ": +var _5=function(_6,_7){ +var _8=_6.nextSibling; +if(typeof _7=="string"){ +_7=_3._doc.createElement(_7); +} +var a=_6.parentNode.insertBefore(_7,_8); +Xinha.removeFromParent(_6); +a.appendChild(_6); +_8.data=" "+_8.data; +s.collapse(_8,1); +_3._unLink=function(){ +var t=a.firstChild; +a.removeChild(t); +a.parentNode.insertBefore(t,a); +Xinha.removeFromParent(a); +_3._unLink=null; +_3._unlinkOnUndo=false; +}; +_3._unlinkOnUndo=true; +return a; +}; +if(_3.config.convertUrlsToLinks&&s&&s.isCollapsed&&s.anchorNode.nodeType==3&&s.anchorNode.data.length>3&&s.anchorNode.data.indexOf(".")>=0){ +var _b=s.anchorNode.data.substring(0,s.anchorOffset).search(/\S{4,}$/); +if(_b==-1){ +break; +} +if(_3._getFirstAncestor(s,"a")){ +break; +} +var _c=s.anchorNode.data.substring(0,s.anchorOffset).replace(/^.*?(\S*)$/,"$1"); +var _d=_c.match(Xinha.RE_email); +if(_d){ +var _e=s.anchorNode; +var _f=_e.splitText(s.anchorOffset); +var _10=_e.splitText(_b); +_5(_10,"a").href="mailto:"+_d[0]; +break; +} +RE_date=/([0-9]+\.)+/; +RE_ip=/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/; +var _11=_c.match(Xinha.RE_url); +if(_11){ +if(RE_date.test(_c)){ +if(!RE_ip.test(_c)){ +break; +} +} +var _12=s.anchorNode; +var _13=_12.splitText(s.anchorOffset); +var _14=_12.splitText(_b); +_5(_14,"a").href=(_11[1]?_11[1]:"http://")+_11[2]; +break; +} +} +break; +} +switch(ev.keyCode){ +case 27: +if(_3._unLink){ +_3._unLink(); +Xinha._stopEvent(ev); +} +break; +break; +case 8: +case 46: +if(!ev.shiftKey&&this.handleBackspace()){ +Xinha._stopEvent(ev); +} +default: +_3._unlinkOnUndo=false; +if(s.anchorNode&&s.anchorNode.nodeType==3){ +var a=_3._getFirstAncestor(s,"a"); +if(!a){ +break; +} +if(!a._updateAnchTimeout){ +if(s.anchorNode.data.match(Xinha.RE_email)&&a.href.match("mailto:"+s.anchorNode.data.trim())){ +var _16=s.anchorNode; +var _17=function(){ +a.href="mailto:"+_16.data.trim(); +a._updateAnchTimeout=setTimeout(_17,250); +}; +a._updateAnchTimeout=setTimeout(_17,1000); +break; +} +var m=s.anchorNode.data.match(Xinha.RE_url); +if(m&&a.href.match(s.anchorNode.data.trim())){ +var _19=s.anchorNode; +var _1a=function(){ +m=_19.data.match(Xinha.RE_url); +if(m){ +a.href=(m[1]?m[1]:"http://")+m[2]; +} +a._updateAnchTimeout=setTimeout(_1a,250); +}; +a._updateAnchTimeout=setTimeout(_1a,1000); +} +} +} +break; +} +return false; +}; +Gecko.prototype.handleBackspace=function(){ +var _1b=this.editor; +setTimeout(function(){ +var sel=_1b.getSelection(); +var _1d=_1b.createRange(sel); +var SC=_1d.startContainer; +var SO=_1d.startOffset; +var EC=_1d.endContainer; +var EO=_1d.endOffset; +var _22=SC.nextSibling; +if(SC.nodeType==3){ +SC=SC.parentNode; +} +if(!(/\S/.test(SC.tagName))){ +var p=document.createElement("p"); +while(SC.firstChild){ +p.appendChild(SC.firstChild); +} +SC.parentNode.insertBefore(p,SC); +Xinha.removeFromParent(SC); +var r=_1d.cloneRange(); +r.setStartBefore(_22); +r.setEndAfter(_22); +r.extractContents(); +sel.removeAllRanges(); +sel.addRange(r); +} +},10); +}; +Gecko.prototype.inwardHtml=function(_25){ +_25=_25.replace(/<(\/?)strong(\s|>|\/)/ig,"<$1b$2"); +_25=_25.replace(/<(\/?)em(\s|>|\/)/ig,"<$1i$2"); +_25=_25.replace(/<(\/?)del(\s|>|\/)/ig,"<$1strike$2"); +return _25; +}; +Gecko.prototype.outwardHtml=function(_26){ +_26=_26.replace(/[\s]*<\/script>/ig,""); +return _26; +}; +Gecko.prototype.onExecCommand=function(_27,UI,_29){ +try{ +this.editor._doc.execCommand("useCSS",false,true); +this.editor._doc.execCommand("styleWithCSS",false,false); +} +catch(ex){ +} +switch(_27){ +case "paste": +alert(Xinha._lc("The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.")); +return true; +} +return false; +}; +Gecko.prototype.onMouseDown=function(ev){ +if(ev.target.tagName.toLowerCase()=="hr"){ +var sel=this.editor.getSelection(); +var _2c=this.editor.createRange(sel); +_2c.selectNode(ev.target); +} +}; +Xinha.prototype.insertNodeAtSelection=function(_2d){ +var sel=this.getSelection(); +var _2f=this.createRange(sel); +sel.removeAllRanges(); +_2f.deleteContents(); +var _30=_2f.startContainer; +var pos=_2f.startOffset; +var _32=_2d; +switch(_30.nodeType){ +case 3: +if(_2d.nodeType==3){ +_30.insertData(pos,_2d.data); +_2f=this.createRange(); +_2f.setEnd(_30,pos+_2d.length); +_2f.setStart(_30,pos+_2d.length); +sel.addRange(_2f); +}else{ +_30=_30.splitText(pos); +if(_2d.nodeType==11){ +_32=_32.firstChild; +} +_30.parentNode.insertBefore(_2d,_30); +this.selectNodeContents(_32); +this.updateToolbar(); +} +break; +case 1: +if(_2d.nodeType==11){ +_32=_32.firstChild; +} +_30.insertBefore(_2d,_30.childNodes[pos]); +this.selectNodeContents(_32); +this.updateToolbar(); +break; +} +}; +Xinha.prototype.getParentElement=function(sel){ +if(typeof sel=="undefined"){ +sel=this.getSelection(); +} +var _34=this.createRange(sel); +try{ +var p=_34.commonAncestorContainer; +if(!_34.collapsed&&_34.startContainer==_34.endContainer&&_34.startOffset-_34.endOffset<=1&&_34.startContainer.hasChildNodes()){ +p=_34.startContainer.childNodes[_34.startOffset]; +} +while(p.nodeType==3){ +p=p.parentNode; +} +return p; +} +catch(ex){ +return null; +} +}; +Xinha.prototype.activeElement=function(sel){ +if((sel===null)||this.selectionEmpty(sel)){ +return null; +} +if(!sel.isCollapsed){ +if(sel.anchorNode.childNodes.length>sel.anchorOffset&&sel.anchorNode.childNodes[sel.anchorOffset].nodeType==1){ +return sel.anchorNode.childNodes[sel.anchorOffset]; +}else{ +if(sel.anchorNode.nodeType==1){ +return sel.anchorNode; +}else{ +return null; +} +} +} +return null; +}; +Xinha.prototype.selectionEmpty=function(sel){ +if(!sel){ +return true; +} +if(typeof sel.isCollapsed!="undefined"){ +return sel.isCollapsed; +} +return true; +}; +Xinha.prototype.saveSelection=function(){ +return this.createRange(this.getSelection()).cloneRange(); +}; +Xinha.prototype.restoreSelection=function(_38){ +var sel=this.getSelection(); +sel.removeAllRanges(); +sel.addRange(_38); +}; +Xinha.prototype.selectNodeContents=function(_3a,pos){ +this.focusEditor(); +this.forceRedraw(); +var _3c; +var _3d=typeof pos=="undefined"?true:false; +var sel=this.getSelection(); +_3c=this._doc.createRange(); +if(_3d&&_3a.tagName&&_3a.tagName.toLowerCase().match(/table|img|input|textarea|select/)){ +_3c.selectNode(_3a); +}else{ +_3c.selectNodeContents(_3a); +} +sel.removeAllRanges(); +sel.addRange(_3c); +}; +Xinha.prototype.insertHTML=function(_3f){ +var sel=this.getSelection(); +var _41=this.createRange(sel); +this.focusEditor(); +var _42=this._doc.createDocumentFragment(); +var div=this._doc.createElement("div"); +div.innerHTML=_3f; +while(div.firstChild){ +_42.appendChild(div.firstChild); +} +var _44=this.insertNodeAtSelection(_42); +}; +Xinha.prototype.getSelectedHTML=function(){ +var sel=this.getSelection(); +var _46=this.createRange(sel); +return Xinha.getHTML(_46.cloneContents(),false,this); +}; +Xinha.prototype.getSelection=function(){ +return this._iframe.contentWindow.getSelection(); +}; +Xinha.prototype.createRange=function(sel){ +this.activateEditor(); +if(typeof sel!="undefined"){ +try{ +return sel.getRangeAt(0); +} +catch(ex){ +return this._doc.createRange(); +} +}else{ +return this._doc.createRange(); +} +}; +Xinha.prototype.isKeyEvent=function(_48){ +return _48.type=="keypress"; +}; +Xinha.prototype.getKey=function(_49){ +return String.fromCharCode(_49.charCode); +}; +Xinha.getOuterHTML=function(_4a){ +return (new XMLSerializer()).serializeToString(_4a); +}; +Xinha.prototype.cc=String.fromCharCode(173); +Xinha.prototype.setCC=function(_4b){ +try{ +if(_4b=="textarea"){ +var ta=this._textArea; +var _4d=ta.selectionStart; +var _4e=ta.value.substring(0,_4d); +var _4f=ta.value.substring(_4d,ta.value.length); +if(_4f.match(/^[^<]*>/)){ +var _50=_4f.indexOf(">")+1; +ta.value=_4e+_4f.substring(0,_50)+this.cc+_4f.substring(_50,_4f.length); +}else{ +ta.value=_4e+this.cc+_4f; +} +}else{ +var sel=this.getSelection(); +sel.getRangeAt(0).insertNode(document.createTextNode(this.cc)); +} +} +catch(e){ +} +}; +Xinha.prototype.findCC=function(_52){ +try{ +var _53=(_52=="textarea")?window:this._iframe.contentWindow; +if(_53.find(this.cc)){ +if(_52=="textarea"){ +var ta=this._textArea; +var _55=pos=ta.selectionStart; +var end=ta.selectionEnd; +var _57=ta.scrollTop; +ta.value=ta.value.substring(0,_55)+ta.value.substring(end,ta.value.length); +ta.selectionStart=pos; +ta.selectionEnd=pos; +ta.scrollTop=_57; +ta.focus(); +}else{ +var sel=this.getSelection(); +sel.getRangeAt(0).deleteContents(); +this._iframe.contentWindow.focus(); +} +} +} +catch(e){ +} +}; +Xinha.prototype._standardToggleBorders=Xinha.prototype._toggleBorders; +Xinha.prototype._toggleBorders=function(){ +var _59=this._standardToggleBorders(); +var _5a=this._doc.getElementsByTagName("TABLE"); +for(var i=0;i<_5a.length;i++){ +_5a[i].style.display="none"; +_5a[i].style.display="table"; +} +return _59; +}; +Xinha.getDoctype=function(doc){ +var d=""; +if(doc.doctype){ +d+=""; +} +return d; +}; + diff --git a/xinha/modules/Gecko/paraHandlerBest.js b/xinha/modules/Gecko/paraHandlerBest.js new file mode 100644 index 0000000..317fead --- /dev/null +++ b/xinha/modules/Gecko/paraHandlerBest.js @@ -0,0 +1,293 @@ +EnterParagraphs._pluginInfo={name:"EnterParagraphs",version:"1.0",developer:"Adam Wright",developer_url:"http://www.hipikat.org/",sponsor:"The University of Western Australia",sponsor_url:"http://www.uwa.edu.au/",license:"htmlArea"}; +EnterParagraphs.prototype._whiteSpace=/^\s*$/; +EnterParagraphs.prototype._pExclusions=/^(address|blockquote|body|dd|div|dl|dt|fieldset|form|h1|h2|h3|h4|h5|h6|hr|li|noscript|ol|p|pre|table|ul)$/i; +EnterParagraphs.prototype._pContainers=/^(body|del|div|fieldset|form|ins|map|noscript|object|td|th)$/i; +EnterParagraphs.prototype._pBreak=/^(address|pre|blockquote)$/i; +EnterParagraphs.prototype._permEmpty=/^(area|base|basefont|br|col|frame|hr|img|input|isindex|link|meta|param)$/i; +EnterParagraphs.prototype._elemSolid=/^(applet|br|button|hr|img|input|table)$/i; +EnterParagraphs.prototype._pifySibling=/^(address|blockquote|del|div|dl|fieldset|form|h1|h2|h3|h4|h5|h6|hr|ins|map|noscript|object|ol|p|pre|table|ul|)$/i; +EnterParagraphs.prototype._pifyForced=/^(ul|ol|dl|table)$/i; +EnterParagraphs.prototype._pifyParent=/^(dd|dt|li|td|th|tr)$/i; +function EnterParagraphs(_1){ +this.editor=_1; +if(Xinha.is_gecko){ +this.onKeyPress=this.__onKeyPress; +} +} +EnterParagraphs.prototype.name="EnterParagraphs"; +EnterParagraphs.prototype.insertAdjacentElement=function(_2,_3,el){ +if(_3=="BeforeBegin"){ +_2.parentNode.insertBefore(el,_2); +}else{ +if(_3=="AfterEnd"){ +_2.nextSibling?_2.parentNode.insertBefore(el,_2.nextSibling):_2.parentNode.appendChild(el); +}else{ +if(_3=="AfterBegin"&&_2.firstChild){ +_2.insertBefore(el,_2.firstChild); +}else{ +if(_3=="BeforeEnd"||_3=="AfterBegin"){ +_2.appendChild(el); +} +} +} +} +}; +EnterParagraphs.prototype.forEachNodeUnder=function(_5,_6,_7,_8){ +var _9,end; +if(_5.nodeType==11&&_5.firstChild){ +_9=_5.firstChild; +end=_5.lastChild; +}else{ +_9=end=_5; +} +while(end.lastChild){ +end=end.lastChild; +} +return this.forEachNode(_9,end,_6,_7,_8); +}; +EnterParagraphs.prototype.forEachNode=function(_a,_b,_c,_d,_e){ +var _f=function(_10,_11){ +return (_11=="ltr"?_10.nextSibling:_10.previousSibling); +}; +var _12=function(_13,_14){ +return (_14=="ltr"?_13.firstChild:_13.lastChild); +}; +var _15,lookup,fnReturnVal; +var _16=_e; +var _17=false; +while(_15!=_d=="ltr"?_b:_a){ +if(!_15){ +_15=_d=="ltr"?_a:_b; +}else{ +if(_12(_15,_d)){ +_15=_12(_15,_d); +}else{ +if(_f(_15,_d)){ +_15=_f(_15,_d); +}else{ +lookup=_15; +while(!_f(lookup,_d)&&lookup!=(_d=="ltr"?_b:_a)){ +lookup=lookup.parentNode; +} +_15=(_f(lookup,_d)?_f(lookup,_d):lookup); +} +} +} +_17=(_15==(_d=="ltr"?_b:_a)); +switch(_c){ +case "cullids": +fnReturnVal=this._fenCullIds(_15,_16); +break; +case "find_fill": +fnReturnVal=this._fenEmptySet(_15,_16,_c,_17); +break; +case "find_cursorpoint": +fnReturnVal=this._fenEmptySet(_15,_16,_c,_17); +break; +} +if(fnReturnVal[0]){ +return fnReturnVal[1]; +} +if(_17){ +break; +} +if(fnReturnVal[1]){ +_16=fnReturnVal[1]; +} +} +return false; +}; +EnterParagraphs.prototype._fenEmptySet=function(_18,_19,_1a,_1b){ +if(!_19&&!_18.firstChild){ +_19=_18; +} +if((_18.nodeType==1&&this._elemSolid.test(_18.nodeName))||(_18.nodeType==3&&!this._whiteSpace.test(_18.nodeValue))||(_18.nodeType!=1&&_18.nodeType!=3)){ +switch(_1a){ +case "find_fill": +return new Array(true,false); +break; +case "find_cursorpoint": +return new Array(true,_18); +break; +} +} +if(_1b){ +return new Array(true,_19); +} +return new Array(false,_19); +}; +EnterParagraphs.prototype._fenCullIds=function(_1c,_1d,_1e){ +if(_1d.id){ +_1e[_1d.id]?_1d.id="":_1e[_1d.id]=true; +} +return new Array(false,_1e); +}; +EnterParagraphs.prototype.processSide=function(rng,_20){ +var _21=function(_22,_23){ +return (_23=="left"?_22.previousSibling:_22.nextSibling); +}; +var _24=_20=="left"?rng.startContainer:rng.endContainer; +var _25=_20=="left"?rng.startOffset:rng.endOffset; +var _26,start=_24; +while(start.nodeType==1&&!this._permEmpty.test(start.nodeName)){ +start=(_25?start.lastChild:start.firstChild); +} +while(_26=_26?(_21(_26,_20)?_21(_26,_20):_26.parentNode):start){ +if(_21(_26,_20)){ +if(this._pExclusions.test(_21(_26,_20).nodeName)){ +return this.processRng(rng,_20,_26,_21(_26,_20),(_20=="left"?"AfterEnd":"BeforeBegin"),true,false); +} +}else{ +if(this._pContainers.test(_26.parentNode.nodeName)){ +return this.processRng(rng,_20,_26,_26.parentNode,(_20=="left"?"AfterBegin":"BeforeEnd"),true,false); +}else{ +if(this._pExclusions.test(_26.parentNode.nodeName)){ +if(this._pBreak.test(_26.parentNode.nodeName)){ +return this.processRng(rng,_20,_26,_26.parentNode,(_20=="left"?"AfterBegin":"BeforeEnd"),false,(_20=="left"?true:false)); +}else{ +return this.processRng(rng,_20,(_26=_26.parentNode),(_21(_26,_20)?_21(_26,_20):_26.parentNode),(_21(_26,_20)?(_20=="left"?"AfterEnd":"BeforeBegin"):(_20=="left"?"AfterBegin":"BeforeEnd")),false,false); +} +} +} +} +} +}; +EnterParagraphs.prototype.processRng=function(rng,_28,_29,_2a,_2b,_2c,_2d){ +var _2e=_28=="left"?rng.startContainer:rng.endContainer; +var _2f=_28=="left"?rng.startOffset:rng.endOffset; +var _30=this.editor; +var _31=_30._doc.createRange(); +_31.selectNode(_29); +if(_28=="left"){ +_31.setEnd(_2e,_2f); +rng.setStart(_31.startContainer,_31.startOffset); +}else{ +if(_28=="right"){ +_31.setStart(_2e,_2f); +rng.setEnd(_31.endContainer,_31.endOffset); +} +} +var cnt=_31.cloneContents(); +this.forEachNodeUnder(cnt,"cullids","ltr",this.takenIds,false,false); +var _33,pifyOffset,fill; +_33=_28=="left"?(_31.endContainer.nodeType==3?true:false):(_31.startContainer.nodeType==3?false:true); +pifyOffset=_33?_31.startOffset:_31.endOffset; +_33=_33?_31.startContainer:_31.endContainer; +if(this._pifyParent.test(_33.nodeName)&&_33.parentNode.childNodes.item(0)==_33){ +while(!this._pifySibling.test(_33.nodeName)){ +_33=_33.parentNode; +} +} +if(cnt.nodeType==11&&!cnt.firstChild){ +if(_33.nodeName!="BODY"||(_33.nodeName=="BODY"&&pifyOffset!=0)){ +cnt.appendChild(_30._doc.createElement(_33.nodeName)); +} +} +fill=this.forEachNodeUnder(cnt,"find_fill","ltr",false); +if(fill&&this._pifySibling.test(_33.nodeName)&&((pifyOffset==0)||(pifyOffset==1&&this._pifyForced.test(_33.nodeName)))){ +_29=_30._doc.createElement("p"); +_29.innerHTML=" "; +if((_28=="left")&&_33.previousSibling){ +return new Array(_33.previousSibling,"AfterEnd",_29); +}else{ +if((_28=="right")&&_33.nextSibling){ +return new Array(_33.nextSibling,"BeforeBegin",_29); +}else{ +return new Array(_33.parentNode,(_28=="left"?"AfterBegin":"BeforeEnd"),_29); +} +} +} +if(fill){ +if(fill.nodeType==3){ +fill=_30._doc.createDocumentFragment(); +} +if((fill.nodeType==1&&!this._elemSolid.test())||fill.nodeType==11){ +var _34=_30._doc.createElement("p"); +_34.innerHTML=" "; +fill.appendChild(_34); +}else{ +var _34=_30._doc.createElement("p"); +_34.innerHTML=" "; +fill.parentNode.insertBefore(parentNode,fill); +} +} +if(fill){ +_29=fill; +}else{ +_29=(_2c||(cnt.nodeType==11&&!cnt.firstChild))?_30._doc.createElement("p"):_30._doc.createDocumentFragment(); +_29.appendChild(cnt); +} +if(_2d){ +_29.appendChild(_30._doc.createElement("br")); +} +return new Array(_2a,_2b,_29); +}; +EnterParagraphs.prototype.isNormalListItem=function(rng){ +var _36,listNode; +_36=rng.startContainer; +if((typeof _36.nodeName!="undefined")&&(_36.nodeName.toLowerCase()=="li")){ +listNode=_36; +}else{ +if((typeof _36.parentNode!="undefined")&&(typeof _36.parentNode.nodeName!="undefined")&&(_36.parentNode.nodeName.toLowerCase()=="li")){ +listNode=_36.parentNode; +}else{ +return false; +} +} +if(!listNode.previousSibling){ +if(rng.startOffset==0){ +return false; +} +} +return true; +}; +EnterParagraphs.prototype.__onKeyPress=function(ev){ +if(ev.keyCode==13&&!ev.shiftKey&&this.editor._iframe.contentWindow.getSelection){ +return this.handleEnter(ev); +} +}; +EnterParagraphs.prototype.handleEnter=function(ev){ +var _39; +var sel=this.editor.getSelection(); +var rng=this.editor.createRange(sel); +if(this.isNormalListItem(rng)){ +return true; +} +this.takenIds=new Object(); +var _3c=this.processSide(rng,"left"); +var _3d=this.processSide(rng,"right"); +_39=_3d[2]; +sel.removeAllRanges(); +rng.deleteContents(); +var _3e=this.forEachNodeUnder(_39,"find_cursorpoint","ltr",false,true); +if(!_3e){ +alert("INTERNAL ERROR - could not find place to put cursor after ENTER"); +} +if(_3c){ +this.insertAdjacentElement(_3c[0],_3c[1],_3c[2]); +} +if(_3d&&_3d.nodeType!=1){ +this.insertAdjacentElement(_3d[0],_3d[1],_3d[2]); +} +if((_3e)&&(this._permEmpty.test(_3e.nodeName))){ +var _3f=0; +while(_3e.parentNode.childNodes.item(_3f)!=_3e){ +_3f++; +} +sel.collapse(_3e.parentNode,_3f); +}else{ +try{ +sel.collapse(_3e,0); +if(_3e.nodeType==3){ +_3e=_3e.parentNode; +} +this.editor.scrollToElement(_3e); +} +catch(e){ +} +} +this.editor.updateToolbar(); +Xinha._stopEvent(ev); +return true; +}; + diff --git a/xinha/modules/Gecko/paraHandlerDirty.js b/xinha/modules/Gecko/paraHandlerDirty.js new file mode 100644 index 0000000..aef5722 --- /dev/null +++ b/xinha/modules/Gecko/paraHandlerDirty.js @@ -0,0 +1,116 @@ +EnterParagraphs._pluginInfo={name:"EnterParagraphs",origin:"Xinha Core",version:"$LastChangedRevision: 688 $".replace(/^[^:]*: (.*) \$$/,"$1"),developer:"The Xinha Core Developer Team",developer_url:"$HeadURL: http://svn.xinha.python-hosting.com/trunk/modules/Gecko/paraHandlerDirty.js $".replace(/^[^:]*: (.*) \$$/,"$1"),sponsor:"",sponsor_url:"",license:"htmlArea"}; +function EnterParagraphs(_1){ +this.editor=_1; +} +EnterParagraphs.prototype.onKeyPress=function(ev){ +if(ev.keyCode==13&&!ev.shiftKey){ +this.dom_checkInsertP(); +Xinha._stopEvent(ev); +} +}; +EnterParagraphs.prototype.dom_checkInsertP=function(){ +var _3=this.editor; +var p,body; +var _5=_3.getSelection(); +var _6=_3.createRange(_5); +if(!_6.collapsed){ +_6.deleteContents(); +} +_3.deactivateEditor(); +var SC=_6.startContainer; +var SO=_6.startOffset; +var EC=_6.endContainer; +var EO=_6.endOffset; +if(SC==EC&&SC==body&&!SO&&!EO){ +p=_3._doc.createTextNode(" "); +body.insertBefore(p,body.firstChild); +_6.selectNodeContents(p); +SC=_6.startContainer; +SO=_6.startOffset; +EC=_6.endContainer; +EO=_6.endOffset; +} +p=_3.getAllAncestors(); +var _b=null; +body=_3._doc.body; +for(var i=0;i1){ +var nb=_3._doc.createElement("p"); +while(df.firstChild){ +var s=df.firstChild; +df.removeChild(s); +nb.appendChild(s); +} +df.appendChild(nb); +} +if(!(/\S/.test(_b.innerHTML))){ +_b.innerHTML=" "; +} +p=df.firstChild; +if(!(/\S/.test(p.innerHTML))){ +p.innerHTML="
    "; +} +if((/^\s*\s*$/.test(p.innerHTML))&&(/^h[1-6]$/i.test(p.tagName))){ +df.appendChild(_3.convertNode(p,"p")); +df.removeChild(p); +} +var _14=_b.parentNode.insertBefore(df.firstChild,_b.nextSibling); +_3.activateEditor(); +_5=_3.getSelection(); +_5.removeAllRanges(); +_5.collapse(_14,0); +_3.scrollToElement(_14); +}; + diff --git a/xinha/modules/GetHtml/DOMwalk.js b/xinha/modules/GetHtml/DOMwalk.js new file mode 100644 index 0000000..fea1e59 --- /dev/null +++ b/xinha/modules/GetHtml/DOMwalk.js @@ -0,0 +1,183 @@ +function GetHtmlImplementation(_1){ +this.editor=_1; +} +GetHtmlImplementation._pluginInfo={name:"GetHtmlImplementation DOMwalk",origin:"Xinha Core",version:"$LastChangedRevision: 821 $".replace(/^[^:]*: (.*) \$$/,"$1"),developer:"The Xinha Core Developer Team",developer_url:"$HeadURL: http://svn.xinha.python-hosting.com/trunk/modules/GetHtml/DOMwalk.js $".replace(/^[^:]*: (.*) \$$/,"$1"),sponsor:"",sponsor_url:"",license:"htmlArea"}; +Xinha.getHTML=function(_2,_3,_4){ +try{ +return Xinha.getHTMLWrapper(_2,_3,_4); +} +catch(ex){ +alert(Xinha._lc("Your Document is not well formed. Check JavaScript console for details.")); +return _4._iframe.contentWindow.document.body.innerHTML; +} +}; +Xinha.emptyAttributes=" checked disabled ismap readonly nowrap compact declare selected defer multiple noresize noshade "; +Xinha.elGetsNewLine=function(el){ +return (" br meta link title ".indexOf(" "+el.tagName.toLowerCase()+" ")!=-1); +}; +Xinha.getHTMLWrapper=function(_6,_7,_8,_9){ +var _a=""; +if(!_9){ +_9=""; +} +switch(_6.nodeType){ +case 10: +case 6: +case 12: +break; +case 2: +break; +case 4: +_a+=(Xinha.is_ie?("\n"+_9):"")+""; +break; +case 5: +_a+="&"+_6.nodeValue+";"; +break; +case 7: +_a+=(Xinha.is_ie?("\n"+_9):"")+"<"+"?"+_6.target+" "+_6.data+" ?>"; +break; +case 1: +case 11: +case 9: +var _b; +var i; +var _d=(_6.nodeType==1)?_6.tagName.toLowerCase():""; +if((_d=="script"||_d=="noscript")&&_8.config.stripScripts){ +break; +} +if(_7){ +_7=!(_8.config.htmlRemoveTags&&_8.config.htmlRemoveTags.test(_d)); +} +if(Xinha.is_ie&&_d=="head"){ +if(_7){ +_a+=(Xinha.is_ie?("\n"+_9):"")+""; +} +var _e=RegExp.multiline; +RegExp.multiline=true; +var _f=_6.innerHTML.replace(Xinha.RE_tagName,function(str,p1,p2){ +return p1+p2.toLowerCase(); +}).replace(/\s*=\s*(([^'"][^>\s]*)([>\s])|"([^"]+)"|'([^']+)')/g,"=\"$2$4$5\"$3").replace(/<(link|meta)((\s*\S*="[^"]*")*)>/g,"<$1$2 />"); +RegExp.multiline=_e; +_a+=_f+"\n"; +if(_7){ +_a+=(Xinha.is_ie?("\n"+_9):"")+""; +} +break; +}else{ +if(_7){ +_b=(!(_6.hasChildNodes()||Xinha.needsClosingTag(_6))); +_a+=((Xinha.isBlockElement(_6)||Xinha.elGetsNewLine(_6))?("\n"+_9):"")+"<"+_6.tagName.toLowerCase(); +var _13=_6.attributes; +for(i=0;i<_13.length;++i){ +var a=_13.item(i); +if(typeof a.nodeValue=="object"){ +continue; +} +if(_6.tagName.toLowerCase()=="input"&&_6.type.toLowerCase()=="checkbox"&&a.nodeName.toLowerCase()=="value"&&a.nodeValue.toLowerCase()=="on"){ +continue; +} +if(!a.specified&&!(_6.tagName.toLowerCase().match(/input|option/)&&a.nodeName=="value")&&!(_6.tagName.toLowerCase().match(/area/)&&a.nodeName.match(/shape|coords/i))){ +continue; +} +var _15=a.nodeName.toLowerCase(); +if(/_moz_editor_bogus_node/.test(_15)){ +_a=""; +break; +} +if(/(_moz)|(contenteditable)|(_msh)/.test(_15)){ +continue; +} +var _16; +if(Xinha.emptyAttributes.indexOf(" "+_15+" ")!=-1){ +_16=_15; +}else{ +if(_15!="style"){ +if(typeof _6[a.nodeName]!="undefined"&&_15!="href"&&_15!="src"&&!(/^on/.test(_15))){ +_16=_6[a.nodeName]; +}else{ +_16=a.nodeValue; +if(Xinha.is_ie&&(_15=="href"||_15=="src")){ +_16=_8.stripBaseURL(_16); +} +if(_8.config.only7BitPrintablesInURLs&&(_15=="href"||_15=="src")){ +_16=_16.replace(/([^!-~]+)/g,function(_17){ +return escape(_17); +}); +} +} +}else{ +if(!Xinha.is_ie){ +_16=_6.style.cssText.replace(/rgb\(.*?\)/ig,function(rgb){ +return Xinha._colorToRgb(rgb); +}); +} +} +} +if(/^(_moz)?$/.test(_16)){ +continue; +} +_a+=" "+_15+"=\""+Xinha.htmlEncode(_16)+"\""; +} +if(Xinha.is_ie&&_6.style.cssText){ +_a+=" style=\""+_6.style.cssText.toLowerCase()+"\""; +} +if(Xinha.is_ie&&_6.tagName.toLowerCase()=="option"&&_6.selected){ +_a+=" selected=\"selected\""; +} +if(_a!==""){ +if(_b&&_d=="p"){ +_a+="> 

    "; +}else{ +if(_b){ +_a+=" />"; +}else{ +_a+=">"; +} +} +} +} +} +var _19=false; +if(_d=="script"||_d=="noscript"){ +if(!_8.config.stripScripts){ +if(Xinha.is_ie){ +var _1a="\n"+_6.innerHTML.replace(/^[\n\r]*/,"").replace(/\s+$/,"")+"\n"+_9; +}else{ +var _1a=(_6.hasChildNodes())?_6.firstChild.nodeValue:""; +} +_a+=_1a+""+((Xinha.is_ie)?"\n":""); +} +}else{ +if(_d=="pre"){ +_a+=((Xinha.is_ie)?"\n":"")+_6.innerHTML.replace(/
    /g,"\n")+""; +}else{ +for(i=_6.firstChild;i;i=i.nextSibling){ +if(!_19&&i.nodeType==1&&Xinha.isBlockElement(i)){ +_19=true; +} +_a+=Xinha.getHTMLWrapper(i,true,_8,_9+" "); +} +if(_7&&!_b){ +_a+=(((Xinha.isBlockElement(_6)&&_19)||_d=="head"||_d=="html")?("\n"+_9):"")+""; +} +} +} +break; +case 3: +if(/^script|noscript|style$/i.test(_6.parentNode.tagName)){ +_a=_6.data; +}else{ +if(_6.data.trim()==""){ +_a=""; +}else{ +_a=Xinha.htmlEncode(_6.data); +} +} +break; +case 8: +_a=""; +break; +} +return _a; +}; + diff --git a/xinha/modules/GetHtml/TransformInnerHTML.js b/xinha/modules/GetHtml/TransformInnerHTML.js new file mode 100644 index 0000000..4043edb --- /dev/null +++ b/xinha/modules/GetHtml/TransformInnerHTML.js @@ -0,0 +1,143 @@ +function GetHtmlImplementation(_1){ +this.editor=_1; +} +GetHtmlImplementation._pluginInfo={name:"GetHtmlImplementation TransformInnerHTML",version:"1.0",developer:"Nelson Bright",developer_url:"http://www.brightworkweb.com/",sponsor:"",sponsor_url:"",license:"htmlArea"}; +HTMLArea.RegExpCache=[new RegExp().compile(/<\s*\/?([^\s\/>]+)[\s*\/>]/gi),new RegExp().compile(/(\s+)_moz[^=>]*=[^\s>]*/gi),new RegExp().compile(/\s*=\s*(([^'"][^>\s]*)([>\s])|"([^"]+)"|'([^']+)')/g),new RegExp().compile(/\/>/g),new RegExp().compile(/<(br|hr|img|input|link|meta|param|embed|area)((\s*\S*="[^"]*")*)>/g),new RegExp().compile(/(checked|compact|declare|defer|disabled|ismap|multiple|no(href|resize|shade|wrap)|readonly|selected)([\s>])/gi),new RegExp().compile(/(="[^']*)'([^'"]*")/),new RegExp().compile(/&(?=[^<]*>)/g),new RegExp().compile(/<\s+/g),new RegExp().compile(/\s+(\/)?>/g),new RegExp().compile(/\s{2,}/g),new RegExp().compile(/\s+([^=\s]+)((="[^"]+")|([\s>]))/g),new RegExp().compile(/\s+contenteditable(=[^>\s\/]*)?/gi),new RegExp().compile(/((href|src)=")([^\s]*)"/g),new RegExp().compile(/<\/?(div|p|h[1-6]|table|tr|td|th|ul|ol|li|blockquote|object|br|hr|img|embed|param|pre|script|html|head|body|meta|link|title|area|input|form|textarea|select|option)[^>]*>/g),new RegExp().compile(/<\/(div|p|h[1-6]|table|tr|ul|ol|blockquote|object|html|head|body|script|form|select)( [^>]*)?>/g),new RegExp().compile(/<(div|p|h[1-6]|table|tr|ul|ol|blockquote|object|html|head|body|script|form|select)( [^>]*)?>/g),new RegExp().compile(/<(td|th|li|option|br|hr|embed|param|pre|meta|link|title|area|input|textarea)[^>]*>/g),new RegExp().compile(/(^|<\/(pre|script)>)(\s|[^\s])*?(<(pre|script)[^>]*>|$)/g),new RegExp().compile(/(]*>)([\s\S])*?(<\/pre>)/g),new RegExp().compile(/(^|)([\s\S]*?)(?=|$)/g),new RegExp().compile(/\S*=""/g),new RegExp().compile(/|<\?[\s\S]*?\?>|<\/?\w[^>]*>/g),new RegExp().compile(/(^|<\/script>)[\s\S]*?(]*>|$)/g)]; +HTMLArea.prototype.cleanHTML=function(_2){ +var c=HTMLArea.RegExpCache; +_2=_2.replace(c[0],function(_4){ +return _4.toLowerCase(); +}).replace(c[1]," ").replace(c[12]," ").replace(c[2],"=\"$2$4$5\"$3").replace(c[21]," ").replace(c[11],function(_5,p1,p2){ +return " "+p1.toLowerCase()+p2; +}).replace(c[3],">").replace(c[9],"$1>").replace(c[5],"$1=\"$1\"$3").replace(c[4],"<$1$2 />").replace(c[6],"$1$2").replace(c[8],"<").replace(c[10]," "); +if(HTMLArea.is_ie&&c[13].test(_2)){ +_2=_2.replace(c[13],"$1"+this.stripBaseURL(RegExp.$3)+"\""); +} +if(this.config.only7BitPrintablesInURLs){ +if(HTMLArea.is_ie){ +c[13].test(_2); +} +if(c[13].test(_2)){ +try{ +_2=_2.replace(c[13],"$1"+decodeURIComponent(RegExp.$3).replace(/([^!-~]+)/g,function(_8){ +return escape(_8); +})+"\""); +} +catch(e){ +_2=_2.replace(c[13],"$1"+RegExp.$3.replace(/([^!-~]+)/g,function(_9){ +return escape(_9); +})+"\""); +} +} +} +return _2; +}; +HTMLArea.indent=function(s,_b){ +HTMLArea.__nindent=0; +HTMLArea.__sindent=""; +HTMLArea.__sindentChar=(typeof _b=="undefined")?" ":_b; +var c=HTMLArea.RegExpCache; +if(HTMLArea.is_gecko){ +s=s.replace(c[19],function(_d){ +return _d.replace(/
    /g,"\n"); +}); +} +s=s.replace(c[18],function(_e){ +_e=_e.replace(c[20],function(st,$1,$2){ +string=$2.replace(/[\n\r]/gi," ").replace(/\s+/gi," ").replace(c[14],function(str){ +if(str.match(c[16])){ +var s="\n"+HTMLArea.__sindent+str; +HTMLArea.__sindent+=HTMLArea.__sindentChar; +++HTMLArea.__nindent; +return s; +}else{ +if(str.match(c[15])){ +--HTMLArea.__nindent; +HTMLArea.__sindent=""; +for(var i=HTMLArea.__nindent;i>0;--i){ +HTMLArea.__sindent+=HTMLArea.__sindentChar; +} +return "\n"+HTMLArea.__sindent+str; +}else{ +if(str.match(c[17])){ +return "\n"+HTMLArea.__sindent+str; +} +} +} +return str; +}); +return $1+string; +}); +return _e; +}); +s=s.replace(/^\s*/,"").replace(/ +\n/g,"\n").replace(/[\r\n]+<\/script>/g,"\n"); +return s; +}; +HTMLArea.getHTML=function(_15,_16,_17){ +var _18=""; +var c=HTMLArea.RegExpCache; +if(_15.nodeType==11){ +var div=document.createElement("div"); +var _1b=_15.insertBefore(div,_15.firstChild); +for(j=_1b.nextSibling;j;j=j.nextSibling){ +_1b.appendChild(j.cloneNode(true)); +} +_18+=_1b.innerHTML.replace(c[23],function(_1c){ +_1c=_1c.replace(c[22],function(tag){ +if(/^<[!\?]/.test(tag)){ +return tag; +}else{ +return _17.cleanHTML(tag); +} +}); +return _1c; +}); +}else{ +var _1e=(_15.nodeType==1)?_15.tagName.toLowerCase():""; +if(_16){ +_18+="<"+_1e; +var _1f=_15.attributes; +for(i=0;i<_1f.length;++i){ +var a=_1f.item(i); +if(!a.specified){ +continue; +} +var _21=a.nodeName.toLowerCase(); +var _22=a.nodeValue; +_18+=" "+_21+"=\""+_22+"\""; +} +_18+=">"; +} +if(_1e=="html"){ +innerhtml=_17._doc.documentElement.innerHTML; +}else{ +innerhtml=_15.innerHTML; +} +_18+=innerhtml.replace(c[23],function(_23){ +_23=_23.replace(c[22],function(tag){ +if(/^<[!\?]/.test(tag)){ +return tag; +}else{ +if(!(_17.config.htmlRemoveTags&&_17.config.htmlRemoveTags.test(tag.replace(/<([^\s>\/]+)/,"$1")))){ +return _17.cleanHTML(tag); +}else{ +return ""; +} +} +}); +return _23; +}); +if(HTMLArea.is_ie){ +_18=_18.replace(/]*)?>/g,"").replace(/(<(ul|ol)[^>]*>)[\s\n]*<\/li>/g,"$1").replace(/<\/li>([\s\n]*<\/li>)+/g,""); +} +if(HTMLArea.is_gecko){ +_18=_18.replace(/
    \n$/,""); +} +if(_16){ +_18+=""; +} +_18=HTMLArea.indent(_18); +} +return _18; +}; + diff --git a/xinha/modules/InsertImage/insert_image.html b/xinha/modules/InsertImage/insert_image.html new file mode 100644 index 0000000..f4f81af --- /dev/null +++ b/xinha/modules/InsertImage/insert_image.html @@ -0,0 +1,174 @@ + + + Insert Image + + + + + + + + + + +
    Insert Image
    + +
    + + + + + + + + + + + + + + +
    Image URL: + +
    Alternate text:
    + +
    + +
    +Layout + +
    + +
    Alignment:
    + + +
    + +
    Border thickness:
    + + +
    + +
    + +
    +Spacing + +
    + +
    Horizontal:
    + + +
    + +
    Vertical:
    + + +
    + +
    +
    +
    +Image Preview:
    + +
    +
    + + +
    +
    + + \ No newline at end of file diff --git a/xinha/modules/InsertImage/insert_image.js b/xinha/modules/InsertImage/insert_image.js new file mode 100644 index 0000000..05da99f --- /dev/null +++ b/xinha/modules/InsertImage/insert_image.js @@ -0,0 +1,107 @@ +InsertImage._pluginInfo={name:"InsertImage",origin:"Xinha Core",version:"$LastChangedRevision: 733 $".replace(/^[^:]*: (.*) \$$/,"$1"),developer:"The Xinha Core Developer Team",developer_url:"$HeadURL: http://svn.xinha.python-hosting.com/trunk/modules/InsertImage/insert_image.js $".replace(/^[^:]*: (.*) \$$/,"$1"),sponsor:"",sponsor_url:"",license:"htmlArea"}; +function InsertImage(_1){ +} +Xinha.prototype._insertImage=function(_2){ +var _3=this; +var _4; +if(typeof _2=="undefined"){ +_2=this.getParentElement(); +if(_2&&_2.tagName.toLowerCase()!="img"){ +_2=null; +} +} +var _5; +if(typeof _3.config.baseHref!="undefined"&&_3.config.baseHref!==null){ +_5=_3.config.baseHref; +}else{ +var _6=window.location.toString().split("/"); +_6.pop(); +_5=_6.join("/"); +} +if(_2){ +_4={f_base:_5,f_url:Xinha.is_ie?_3.stripBaseURL(_2.src):_2.getAttribute("src"),f_alt:_2.alt,f_border:_2.border,f_align:_2.align,f_vert:(_2.vspace!=-1?_2.vspace:""),f_horiz:(_2.hspace!=-1?_2.hspace:""),f_width:_2.width,f_height:_2.height}; +}else{ +_4={f_base:_5,f_url:""}; +} +Dialog(_3.config.URIs.insert_image,function(_7){ +if(!_7){ +return false; +} +var _8=_2; +if(!_8){ +if(Xinha.is_ie){ +var _9=_3.getSelection(); +var _a=_3.createRange(_9); +_3._doc.execCommand("insertimage",false,_7.f_url); +_8=_a.parentElement(); +if(_8.tagName.toLowerCase()!="img"){ +_8=_8.previousSibling; +} +}else{ +_8=document.createElement("img"); +_8.src=_7.f_url; +_3.insertNodeAtSelection(_8); +if(!_8.tagName){ +_8=_a.startContainer.firstChild; +} +} +}else{ +_8.src=_7.f_url; +} +for(var _b in _7){ +var _c=_7[_b]; +switch(_b){ +case "f_alt": +if(_c){ +_8.alt=_c; +}else{ +_8.removeAttribute("alt"); +} +break; +case "f_border": +if(_c){ +_8.border=parseInt(_c||"0"); +}else{ +_8.removeAttribute("border"); +} +break; +case "f_align": +if(_c){ +_8.align=_c; +}else{ +_8.removeAttribute("align"); +} +break; +case "f_vert": +if(_c){ +_8.vspace=parseInt(_c||"0"); +}else{ +_8.removeAttribute("vspace"); +} +break; +case "f_horiz": +if(_c){ +_8.hspace=parseInt(_c||"0"); +}else{ +_8.removeAttribute("hspace"); +} +break; +case "f_width": +if(_c){ +_8.width=parseInt(_c||"0"); +}else{ +_8.removeAttribute("width"); +} +break; +case "f_height": +if(_c){ +_8.height=parseInt(_c||"0"); +}else{ +_8.removeAttribute("height"); +} +break; +} +} +},_4); +}; + diff --git a/xinha/modules/InsertTable/insert_table.html b/xinha/modules/InsertTable/insert_table.html new file mode 100644 index 0000000..351a0a2 --- /dev/null +++ b/xinha/modules/InsertTable/insert_table.html @@ -0,0 +1,157 @@ + + + + Insert Table + + + + + + + + + + +
    Insert Table
    + +
    + + + + + + + + + + + + + + + + + +
    Rows:Width:
    Cols:
    + +

    + +

    +Layout + +
    + +
    Alignment:
    + + +

    + +

    Border thickness:
    + + +
    + +
    + +
    +Spacing + +
    + +
    Cell spacing:
    + + +

    + +

    Cell padding:
    + + +
    + +
    + +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/xinha/modules/InsertTable/insert_table.js b/xinha/modules/InsertTable/insert_table.js new file mode 100644 index 0000000..74183b2 --- /dev/null +++ b/xinha/modules/InsertTable/insert_table.js @@ -0,0 +1,63 @@ +InsertTable._pluginInfo={name:"InsertTable",origin:"Xinha Core",version:"$LastChangedRevision: 688 $".replace(/^[^:]*: (.*) \$$/,"$1"),developer:"The Xinha Core Developer Team",developer_url:"$HeadURL: http://svn.xinha.python-hosting.com/trunk/modules/InsertTable/insert_table.js $".replace(/^[^:]*: (.*) \$$/,"$1"),sponsor:"",sponsor_url:"",license:"htmlArea"}; +function InsertTable(_1){ +} +Xinha.prototype._insertTable=function(){ +var _2=this.getSelection(); +var _3=this.createRange(_2); +var _4=this; +Dialog(_4.config.URIs.insert_table,function(_5){ +if(!_5){ +return false; +} +var _6=_4._doc; +var _7=_6.createElement("table"); +for(var _8 in _5){ +var _9=_5[_8]; +if(!_9){ +continue; +} +switch(_8){ +case "f_width": +_7.style.width=_9+_5.f_unit; +break; +case "f_align": +_7.align=_9; +break; +case "f_border": +_7.border=parseInt(_9,10); +break; +case "f_spacing": +_7.cellSpacing=parseInt(_9,10); +break; +case "f_padding": +_7.cellPadding=parseInt(_9,10); +break; +} +} +var _a=0; +if(_5.f_fixed){ +_a=Math.floor(100/parseInt(_5.f_cols,10)); +} +var _b=_6.createElement("tbody"); +_7.appendChild(_b); +for(var i=0;i<_5.f_rows;++i){ +var tr=_6.createElement("tr"); +_b.appendChild(tr); +for(var j=0;j<_5.f_cols;++j){ +var td=_6.createElement("td"); +if(_a){ +td.style.width=_a+"%"; +} +tr.appendChild(td); +td.appendChild(_6.createTextNode("\xa0")); +} +} +if(Xinha.is_ie){ +_3.pasteHTML(_7.outerHTML); +}else{ +_4.insertNodeAtSelection(_7); +} +return true; +},null); +}; + diff --git a/xinha/modules/InternetExplorer/InternetExplorer.js b/xinha/modules/InternetExplorer/InternetExplorer.js new file mode 100644 index 0000000..c7acbef --- /dev/null +++ b/xinha/modules/InternetExplorer/InternetExplorer.js @@ -0,0 +1,217 @@ +InternetExplorer._pluginInfo={name:"Internet Explorer",origin:"Xinha Core",version:"$LastChangedRevision: 816 $".replace(/^[^:]*: (.*) \$$/,"$1"),developer:"The Xinha Core Developer Team",developer_url:"$HeadURL: http://svn.xinha.python-hosting.com/trunk/modules/InternetExplorer/InternetExplorer.js $".replace(/^[^:]*: (.*) \$$/,"$1"),sponsor:"",sponsor_url:"",license:"htmlArea"}; +function InternetExplorer(_1){ +this.editor=_1; +_1.InternetExplorer=this; +} +InternetExplorer.prototype.onKeyPress=function(ev){ +if(this.editor.isShortCut(ev)){ +switch(this.editor.getKey(ev).toLowerCase()){ +case "n": +this.editor.execCommand("formatblock",false,"

    "); +Xinha._stopEvent(ev); +return true; +break; +case "1": +case "2": +case "3": +case "4": +case "5": +case "6": +this.editor.execCommand("formatblock",false,""); +Xinha._stopEvent(ev); +return true; +break; +} +} +switch(ev.keyCode){ +case 8: +case 46: +if(this.handleBackspace()){ +Xinha._stopEvent(ev); +return true; +} +break; +} +return false; +}; +InternetExplorer.prototype.handleBackspace=function(){ +var _3=this.editor; +var _4=_3.getSelection(); +if(_4.type=="Control"){ +var _5=_3.activeElement(_4); +Xinha.removeFromParent(_5); +return true; +} +var _6=_3.createRange(_4); +var r2=_6.duplicate(); +r2.moveStart("character",-1); +var a=r2.parentElement(); +if(a!=_6.parentElement()&&(/^a$/i.test(a.tagName))){ +r2.collapse(true); +r2.moveEnd("character",1); +r2.pasteHTML(""); +r2.select(); +return true; +} +}; +InternetExplorer.prototype.inwardHtml=function(_9){ +_9=_9.replace(/<(\/?)del(\s|>|\/)/ig,"<$1strike$2"); +_9=_9.replace(/( )?([\s\S]*?)(=1){ +return _1d.item(0).outerHTML; +} +} +return ""; +}; +Xinha.prototype.getSelection=function(){ +return this._doc.selection; +}; +Xinha.prototype.createRange=function(sel){ +return sel.createRange(); +}; +Xinha.prototype.isKeyEvent=function(_1f){ +return _1f.type=="keydown"; +}; +Xinha.prototype.getKey=function(_20){ +return String.fromCharCode(_20.keyCode); +}; +Xinha.getOuterHTML=function(_21){ +return _21.outerHTML; +}; +Xinha.prototype.cc=String.fromCharCode(8201); +Xinha.prototype.setCC=function(_22){ +if(_22=="textarea"){ +var ta=this._textArea; +var pos=document.selection.createRange(); +pos.collapse(); +pos.text=this.cc; +var _25=ta.value.indexOf(this.cc); +var _26=ta.value.substring(0,_25); +var _27=ta.value.substring(_25+this.cc.length,ta.value.length); +if(_27.match(/^[^<]*>/)){ +var _28=_27.indexOf(">")+1; +ta.value=_26+_27.substring(0,_28)+this.cc+_27.substring(_28,_27.length); +}else{ +ta.value=_26+this.cc+_27; +} +}else{ +var sel=this.getSelection(); +var r=sel.createRange(); +if(sel.type=="Control"){ +var _2b=r.item(0); +_2b.outerHTML+=this.cc; +}else{ +r.collapse(); +r.text=this.cc; +} +} +}; +Xinha.prototype.findCC=function(_2c){ +var _2d=(_2c=="textarea")?this._textArea:this._doc.body; +range=_2d.createTextRange(); +if(range.findText(escape(this.cc))){ +range.select(); +range.text=""; +} +if(range.findText(this.cc)){ +range.select(); +range.text=""; +} +if(_2c=="textarea"){ +this._textArea.focus(); +} +}; +Xinha.getDoctype=function(doc){ +return (doc.compatMode=="CSS1Compat")?"":""; +}; + diff --git a/xinha/plugins/CSS/css.js b/xinha/plugins/CSS/css.js new file mode 100644 index 0000000..c34442c --- /dev/null +++ b/xinha/plugins/CSS/css.js @@ -0,0 +1,74 @@ +HTMLArea.Config.prototype.cssPluginConfig={combos:[{label:"Syntax",options:{"None":"","Code":"code","String":"string","Comment":"comment","Variable name":"variable-name","Type":"type","Reference":"reference","Preprocessor":"preprocessor","Keyword":"keyword","Function name":"function-name","Html tag":"html-tag","Html italic":"html-helper-italic","Warning":"warning","Html bold":"html-helper-bold"},context:"pre"},{label:"Info",options:{"None":"","Quote":"quote","Highlight":"highlight","Deprecated":"deprecated"}}]}; +function CSS(_1,_2){ +this.editor=_1; +var _3=_1.config; +var _4=this; +var _5; +if(_2&&_2.length){ +_5=_2[0]; +}else{ +_5=_1.config.cssPluginConfig; +} +var _6=_5.combos; +for(var i=0;i<_6.length;i++){ +var _8=_6[i]; +var id="CSS-class"+i; +var _a={id:id,options:_8.options,action:function(_b){ +_4.onSelect(_b,this,_8.context,_8.updatecontextclass); +},refresh:function(_c){ +_4.updateValue(_c,this); +},context:_8.context}; +_3.registerDropdown(_a); +_3.addToolbarElement(["T["+_8.label+"]",id,"separator"],"formatblock",-1); +} +} +CSS._pluginInfo={name:"CSS",version:"1.0",developer:"Mihai Bazon",developer_url:"http://dynarch.com/mishoo/",c_owner:"Mihai Bazon",sponsor:"Miro International",sponsor_url:"http://www.miro.com.au",license:"htmlArea"}; +CSS.prototype.onSelect=function(_d,_e,_f,_10){ +var _11=_d._toolbarObjects[_e.id]; +var _12=_11.element.selectedIndex; +var _13=_11.element.value; +var _14=_d.getParentElement(); +var _15=true; +var _16=(_14&&_14.tagName.toLowerCase()=="span"); +var _17=(_f&&_10&&_14&&_14.tagName.toLowerCase()==_f); +if(_17){ +_14.className=_13; +_d.updateToolbar(); +return; +} +if(_16&&_12==0&&!/\S/.test(_14.style.cssText)){ +while(_14.firstChild){ +_14.parentNode.insertBefore(_14.firstChild,_14); +} +_14.parentNode.removeChild(_14); +_d.updateToolbar(); +return; +} +if(_16){ +if(_14.childNodes.length==1){ +_14.className=_13; +_15=false; +_d.updateToolbar(); +} +} +if(_15){ +_d.surroundHTML("",""); +} +}; +CSS.prototype.updateValue=function(_18,obj){ +var _1a=_18._toolbarObjects[obj.id].element; +var _1b=_18.getParentElement(); +if(typeof _1b.className!="undefined"&&/\S/.test(_1b.className)){ +var _1c=_1a.options; +var _1d=_1b.className; +for(var i=_1c.length;--i>=0;){ +var _1f=_1c[i]; +if(_1d==_1f.value){ +_1a.selectedIndex=i; +return; +} +} +} +_1a.selectedIndex=0; +}; + diff --git a/xinha/plugins/CharCounter/char-counter.js b/xinha/plugins/CharCounter/char-counter.js new file mode 100644 index 0000000..5b16445 --- /dev/null +++ b/xinha/plugins/CharCounter/char-counter.js @@ -0,0 +1,106 @@ +function CharCounter(_1){ +this.editor=_1; +this._Chars=0; +this._Words=0; +this._HTML=0; +this.onKeyPress=this.__onKeyPress; +} +HTMLArea.Config.prototype.CharCounter={"showChar":true,"showWord":true,"showHtml":true,"separator":" | ","maxHTML":-1}; +CharCounter._pluginInfo={name:"CharCounter",version:"1.31",developer:"Udo Schmal",developer_url:"http://www.schaffrath-neuemedien.de",sponsor:"L.N.Schaffrath NeueMedien",sponsor_url:"http://www.schaffrath-neuemedien.de",c_owner:"Udo Schmal & L.N.Schaffrath NeueMedien",license:"htmlArea"}; +CharCounter.prototype._lc=function(_2){ +return HTMLArea._lc(_2,"CharCounter"); +}; +CharCounter.prototype.onGenerateOnce=function(){ +var _3=this; +if(this.charCount==null){ +var _4=document.createElement("span"); +_4.style.padding="2px 5px"; +if(HTMLArea.is_ie){ +_4.style.styleFloat="right"; +}else{ +_4.style.cssFloat="right"; +} +var _5=document.createElement("div"); +_5.style.height=_5.style.width=_5.style.lineHeight=_5.style.fontSize="1px"; +_5.style.clear="both"; +if(HTMLArea.is_ie){ +this.editor._statusBarTree.style.styleFloat="left"; +}else{ +this.editor._statusBarTree.style.cssFloat="left"; +} +this.editor._statusBar.appendChild(_4); +this.editor._statusBar.appendChild(_5); +this.charCount=_4; +} +}; +CharCounter.prototype.__onKeyPress=function(ev){ +if((ev.keyCode!=8)&&(ev.keyCode!=46)){ +if(this.editor.config.CharCounter.maxHTML!=-1){ +var _7=this.editor.getHTML(); +if(_7.length>=this.editor.config.CharCounter.maxHTML){ +HTMLArea._stopEvent(ev); +return true; +} +} +} +}; +CharCounter.prototype._updateCharCount=function(){ +var _8=this.editor; +var _9=_8.config; +var _a=_8.getHTML(); +var _b=new Array(); +if(_9.CharCounter.showHtml){ +_b[_b.length]=this._lc("HTML")+": "+_a.length; +} +this._HTML=_a.length; +if(_9.CharCounter.showWord||_9.CharCounter.showChar){ +_a=_a.replace(/<\/?\s*!--[^-->]*-->/gi,""); +_a=_a.replace(/<(.+?)>/g,""); +_a=_a.replace(/ /gi," "); +_a=_a.replace(/([\n\r\t])/g," "); +_a=_a.replace(/( +)/g," "); +_a=_a.replace(/&(.*);/g," "); +_a=_a.replace(/^\s*|\s*$/g,""); +} +if(_9.CharCounter.showWord){ +this._Words=0; +for(var x=0;x<_a.length;x++){ +if(_a.charAt(x)==" "){ +this._Words++; +} +} +if(this._Words>=1){ +this._Words++; +} +_b[_b.length]=this._lc("Words")+": "+this._Words; +} +if(_9.CharCounter.showChar){ +_b[_b.length]=this._lc("Chars")+": "+_a.length; +this._Chars=_a.length; +} +this.charCount.innerHTML=_b.join(_9.CharCounter.separator); +}; +CharCounter.prototype.onUpdateToolbar=function(){ +this.charCount.innerHTML=this._lc("... in progress"); +if(this._timeoutID){ +window.clearTimeout(this._timeoutID); +} +var e=this; +this._timeoutID=window.setTimeout(function(){ +e._updateCharCount(); +},1000); +}; +CharCounter.prototype.onMode=function(_e){ +switch(_e){ +case "textmode": +this.charCount.style.display="none"; +break; +case "wysiwyg": +this.charCount.style.display=""; +break; +default: +alert("Mode <"+_e+"> not defined!"); +return false; +} +}; + diff --git a/xinha/plugins/CharCounter/lang/de.js b/xinha/plugins/CharCounter/lang/de.js new file mode 100644 index 0000000..74b6d22 --- /dev/null +++ b/xinha/plugins/CharCounter/lang/de.js @@ -0,0 +1,8 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// Author: Udo Schmal (gocher), http://www.schaffrath-neuemedien.de/, udo.schmal@t-online.de +{ + "Chars": "Zeichen", + "Words": "Worte", + "... in progress": "... in Bearbeitung" +}; diff --git a/xinha/plugins/CharCounter/lang/fr.js b/xinha/plugins/CharCounter/lang/fr.js new file mode 100644 index 0000000..0a4d9df --- /dev/null +++ b/xinha/plugins/CharCounter/lang/fr.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Chars": "Caractères", + "Words": "Mots" +}; \ No newline at end of file diff --git a/xinha/plugins/CharCounter/lang/ja.js b/xinha/plugins/CharCounter/lang/ja.js new file mode 100644 index 0000000..77aace2 --- /dev/null +++ b/xinha/plugins/CharCounter/lang/ja.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Chars": "文字数", + "Words": "単語数", + "... in progress": "... 処理中" +}; \ No newline at end of file diff --git a/xinha/plugins/CharCounter/lang/nb.js b/xinha/plugins/CharCounter/lang/nb.js new file mode 100644 index 0000000..1aa701b --- /dev/null +++ b/xinha/plugins/CharCounter/lang/nb.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Chars": "Tegn" +}; \ No newline at end of file diff --git a/xinha/plugins/CharacterMap/CharacterMap.css b/xinha/plugins/CharacterMap/CharacterMap.css new file mode 100644 index 0000000..faea58b --- /dev/null +++ b/xinha/plugins/CharacterMap/CharacterMap.css @@ -0,0 +1,41 @@ +.CharacterMap { } +.CharacterMap a.entity { + font-size:12px; + width:18px; + display:block; + float:left; + padding:2px; + text-decoration:none; + color:#000; + text-align:center; + +} +.CharacterMap a.light { + background-color:#ffffff; +} +.CharacterMap a.dark { + background-color:#f7f8fd; +} +.CharacterMap a.entity:hover { + background-color:#ffd760; + color:#000; +} +.popup td.character { + font-family:Verdana,Arial,Helvetica,sans-serif; + font-size:14px; + font-weight:bold; + text-align:center; + background:#fff; + padding:4px; +} +.popup td.character-hilite { + background:#ffd760; +} +.popup form { + text-align:center; +} +.popup table { + cursor:pointer; + background-color:#ADAD9C; + border:1px inset; +} \ No newline at end of file diff --git a/xinha/plugins/CharacterMap/character-map.js b/xinha/plugins/CharacterMap/character-map.js new file mode 100644 index 0000000..2d29cbd --- /dev/null +++ b/xinha/plugins/CharacterMap/character-map.js @@ -0,0 +1,68 @@ +HTMLArea.loadStyle("CharacterMap.css","CharacterMap"); +function CharacterMap(_1){ +this.editor=_1; +var _2=_1.config; +var _3=this; +_2.registerButton({id:"insertcharacter",tooltip:HTMLArea._lc("Insert special character","CharacterMap"),image:_1.imgURL("ed_charmap.gif","CharacterMap"),textMode:false,action:function(_4){ +_3.buttonPress(_4); +}}); +_2.addToolbarElement("insertcharacter","createlink",-1); +if(_2.CharacterMap.mode=="panel"){ +_1._CharacterMap=_1.addPanel("right"); +HTMLArea._addClass(_1._CharacterMap,"CharacterMap"); +_1.notifyOn("modechange",function(e,_6){ +if(_6.mode=="text"){ +_1.hidePanel(_1._CharacterMap); +} +}); +var _7=["Ÿ","š","@",""","¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","¯","°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿","×","Ø","÷","ø","ƒ","ˆ","˜","–","—","‘","’","‚","“","”","„","†","‡","•","…","‰","‹","›","€","™","À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ","Ò","Ó","Ô","Õ","Ö","®","×","Ù","Ú","Û","Ü","Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ","Œ","œ","Š"]; +for(var i=0;i<_7.length;i++){ +this.addEntity(_7[i],i); +} +_1.hidePanel(_1._CharacterMap); +} +} +HTMLArea.Config.prototype.CharacterMap={"mode":"popup"}; +CharacterMap._pluginInfo={name:"CharacterMap",version:"2.0",developer:"Laurent Vilday",developer_url:"http://www.mokhet.com/",c_owner:"Xinha community",sponsor:"",sponsor_url:"",license:"Creative Commons Attribution-ShareAlike License"}; +CharacterMap._isActive=false; +CharacterMap.prototype.buttonPress=function(_9){ +var _a=_9.config; +if(_a.CharacterMap.mode=="panel"){ +if(this._isActive){ +this._isActive=false; +_9.hidePanel(_9._CharacterMap); +}else{ +this._isActive=true; +_9.showPanel(_9._CharacterMap); +} +}else{ +_9._popupDialog("plugin://CharacterMap/select_character",function(_b){ +if(!_b){ +return false; +} +if(HTMLArea.is_ie){ +_9.focusEditor(); +} +_9.insertHTML(_b); +},null); +} +}; +CharacterMap.prototype.addEntity=function(_c,_d){ +var _e=this.editor; +var _f=this; +var a=document.createElement("a"); +HTMLArea._addClass(a,"entity"); +a.innerHTML=_c; +a.href="javascript:void(0)"; +HTMLArea._addClass(a,(_d%2)?"light":"dark"); +a.onclick=function(){ +if(HTMLArea.is_ie){ +_e.focusEditor(); +} +_e.insertHTML(_c); +return false; +}; +_e._CharacterMap.appendChild(a); +a=null; +}; + diff --git a/xinha/plugins/CharacterMap/img/ed_charmap.gif b/xinha/plugins/CharacterMap/img/ed_charmap.gif new file mode 100644 index 0000000..dc6d706 Binary files /dev/null and b/xinha/plugins/CharacterMap/img/ed_charmap.gif differ diff --git a/xinha/plugins/CharacterMap/lang/de.js b/xinha/plugins/CharacterMap/lang/de.js new file mode 100644 index 0000000..9057107 --- /dev/null +++ b/xinha/plugins/CharacterMap/lang/de.js @@ -0,0 +1,11 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// Sponsored by http://www.systemconcept.de +// Author: Holger Hees, +// (c) systemconcept.de 2004 +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). +{ + "Insert special character": "Sonderzeichen einfügen", + "Cancel": "Abbrechen" +} diff --git a/xinha/plugins/CharacterMap/lang/fr.js b/xinha/plugins/CharacterMap/lang/fr.js new file mode 100644 index 0000000..24851be --- /dev/null +++ b/xinha/plugins/CharacterMap/lang/fr.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Insert special character": "Insérer un caractère spécial", + "Cancel": "Annuler" +}; \ No newline at end of file diff --git a/xinha/plugins/CharacterMap/lang/it.js b/xinha/plugins/CharacterMap/lang/it.js new file mode 100644 index 0000000..2b3e1a0 --- /dev/null +++ b/xinha/plugins/CharacterMap/lang/it.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "it", ENCODING: UTF-8 +{ + "Insert special character": "Inserisca il carattere speciale", + "Cancel": "Annullamento" +}; diff --git a/xinha/plugins/CharacterMap/lang/ja.js b/xinha/plugins/CharacterMap/lang/ja.js new file mode 100644 index 0000000..68ec5fd --- /dev/null +++ b/xinha/plugins/CharacterMap/lang/ja.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Insert special character": "特殊文字を挿入", + "Cancel": "中止" +}; \ No newline at end of file diff --git a/xinha/plugins/CharacterMap/lang/nb.js b/xinha/plugins/CharacterMap/lang/nb.js new file mode 100644 index 0000000..744e6fc --- /dev/null +++ b/xinha/plugins/CharacterMap/lang/nb.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Insert special character": "Sett inn tegn", + "Cancel": "Avbryt" +}; \ No newline at end of file diff --git a/xinha/plugins/CharacterMap/lang/nl.js b/xinha/plugins/CharacterMap/lang/nl.js new file mode 100644 index 0000000..477446d --- /dev/null +++ b/xinha/plugins/CharacterMap/lang/nl.js @@ -0,0 +1,11 @@ +// I18N constants +// LANG: "nl", ENCODING: UTF-8 +// Sponsored by http://www.systemconcept.de +// Author: Holger Hees, +// (c) systemconcept.de 2004 +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). +{ + "Insert special character": "Speciaal character invoegen", + "Cancel": "Annuleer" +}; diff --git a/xinha/plugins/CharacterMap/lang/ru.js b/xinha/plugins/CharacterMap/lang/ru.js new file mode 100644 index 0000000..9111dd5 --- /dev/null +++ b/xinha/plugins/CharacterMap/lang/ru.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "ru", ENCODING: UTF-8 +// Author: Andrei Blagorazumov, a@fnr.ru +{ + "Insert special character": "Вставить специальный символ", + "Cancel": "Отменить" +}; \ No newline at end of file diff --git a/xinha/plugins/CharacterMap/lang/sv.js b/xinha/plugins/CharacterMap/lang/sv.js new file mode 100644 index 0000000..4e29804 --- /dev/null +++ b/xinha/plugins/CharacterMap/lang/sv.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "sv" (Swedish), ENCODING: UTF-8 +// translated: Erik Dalén +{ + "Insert special character": "Infoga tecken", + "Cancel": "Avbryt" +}; diff --git a/xinha/plugins/CharacterMap/popups/select_character.html b/xinha/plugins/CharacterMap/popups/select_character.html new file mode 100644 index 0000000..7fff2bf --- /dev/null +++ b/xinha/plugins/CharacterMap/popups/select_character.html @@ -0,0 +1,184 @@ + + + +Insert special character + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Ÿš@"¡¢£¤¥¦§¨©ª«¬
    ¯°±²³´µ·¸¹º»¼½¾
    ¿×Ø÷øƒˆ˜
    ÀÁÂÃÄÅÆ
    ÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ
    ®×ÙÚÛÜÝÞßàáâãäåæ
    çèéêëìíîïðñòóôõö
    ÷øùúûüýþÿŒœŠ 

    +

    + + \ No newline at end of file diff --git a/xinha/plugins/ContextMenu/1.pl b/xinha/plugins/ContextMenu/1.pl new file mode 100755 index 0000000..88645d9 --- /dev/null +++ b/xinha/plugins/ContextMenu/1.pl @@ -0,0 +1,38 @@ +#! /usr/bin/perl -w + +use strict; + +my $file = 'context-menu.js'; +my $outfile = $file.'-i18n'; +my $langfile = 'en.js'; + +open FILE, "<$file"; +#open OUTFILE, ">$outfile"; +#open LANGFILE, ">$langfile"; +my %texts = (); +while () { + if (/"(.*?)"/) { + my $inline = $_; + chomp $inline; + my $key = $1; + my $val = $1; + print "Key: [$key]: "; + my $line = ; + if (defined $line) { + chomp $line; + if ($line =~ /(\S+)/) { + $key = $1; + print "-- using $key\n"; + } + $texts{$val} = $key; + } else { + print " -- skipped...\n"; + } + } +} +#close LANGFILE; +#close OUTFILE; +close FILE; + +print "\n\n\n"; +print '"', join("\"\n\"", sort keys %texts), '"', "\n"; diff --git a/xinha/plugins/ContextMenu/context-menu.js b/xinha/plugins/ContextMenu/context-menu.js new file mode 100644 index 0000000..688e5e1 --- /dev/null +++ b/xinha/plugins/ContextMenu/context-menu.js @@ -0,0 +1,383 @@ +HTMLArea.loadStyle("menu.css","ContextMenu"); +function ContextMenu(_1){ +this.editor=_1; +} +ContextMenu._pluginInfo={name:"ContextMenu",version:"1.0",developer:"Mihai Bazon",developer_url:"http://dynarch.com/mishoo/",c_owner:"dynarch.com",sponsor:"American Bible Society",sponsor_url:"http://www.americanbible.org",license:"htmlArea"}; +ContextMenu.prototype.onGenerate=function(){ +var _2=this; +var _3=this.editordoc=this.editor._iframe.contentWindow.document; +HTMLArea._addEvents(_3,["contextmenu"],function(_4){ +return _2.popupMenu(HTMLArea.is_ie?_2.editor._iframe.contentWindow.event:_4); +}); +this.currentMenu=null; +}; +ContextMenu.prototype.getContextMenu=function(_5){ +var _6=this; +var _7=this.editor; +var _8=_7.config; +var _9=[]; +var _a=this.editor.plugins.TableOperations; +if(_a){ +_a=_a.instance; +} +var _b=_7.hasSelectedText(); +if(!HTMLArea.is_gecko){ +if(_b){ +_9.push([HTMLArea._lc("Cut","ContextMenu"),function(){ +_7.execCommand("cut"); +},null,_8.btnList["cut"][1]],[HTMLArea._lc("Copy","ContextMenu"),function(){ +_7.execCommand("copy"); +},null,_8.btnList["copy"][1]]); +_9.push([HTMLArea._lc("Paste","ContextMenu"),function(){ +_7.execCommand("paste"); +},null,_8.btnList["paste"][1]]); +} +} +var _c=_5; +var _d=[]; +var _e=null; +var _f=null; +var tr=null; +var td=null; +var img=null; +function tableOperation(_13){ +_a.buttonPress(_7,_13); +} +function insertPara(_14){ +var el=_c; +var par=el.parentNode; +var p=_7._doc.createElement("p"); +p.appendChild(_7._doc.createElement("br")); +par.insertBefore(p,_14?el.nextSibling:el); +var sel=_7._getSelection(); +var _19=_7._createRange(sel); +if(!HTMLArea.is_ie){ +sel.removeAllRanges(); +_19.selectNodeContents(p); +_19.collapse(true); +sel.addRange(_19); +}else{ +_19.moveToElementText(p); +_19.collapse(true); +_19.select(); +} +} +for(;_5;_5=_5.parentNode){ +var tag=_5.tagName; +if(!tag){ +continue; +} +tag=tag.toLowerCase(); +switch(tag){ +case "img": +img=_5; +_d.push(null,[HTMLArea._lc("_Image Properties...","ContextMenu"),function(){ +_7._insertImage(img); +},HTMLArea._lc("Show the image properties dialog","ContextMenu"),_8.btnList["insertimage"][1]]); +break; +case "a": +_e=_5; +_d.push(null,[HTMLArea._lc("_Modify Link...","ContextMenu"),function(){ +_7.config.btnList["createlink"][3](_7); +},HTMLArea._lc("Current URL is","ContextMenu")+": "+_e.href,_8.btnList["createlink"][1]],[HTMLArea._lc("Chec_k Link...","ContextMenu"),function(){ +window.open(_e.href); +},HTMLArea._lc("Opens this link in a new window","ContextMenu")],[HTMLArea._lc("_Remove Link...","ContextMenu"),function(){ +if(confirm(HTMLArea._lc("Please confirm that you want to unlink this element.","ContextMenu")+"\n"+HTMLArea._lc("Link points to:","ContextMenu")+" "+_e.href)){ +while(_e.firstChild){ +_e.parentNode.insertBefore(_e.firstChild,_e); +} +_e.parentNode.removeChild(_e); +} +},HTMLArea._lc("Unlink the current element","ContextMenu")]); +break; +case "td": +td=_5; +if(!_a){ +break; +} +_d.push(null,[HTMLArea._lc("C_ell Properties...","ContextMenu"),function(){ +tableOperation("TO-cell-prop"); +},HTMLArea._lc("Show the Table Cell Properties dialog","ContextMenu"),_8.btnList["TO-cell-prop"][1]],[HTMLArea._lc("Insert Cell After","ContextMenu"),function(){ +tableOperation("TO-cell-insert-after"); +},HTMLArea._lc("Insert Cell After","ContextMenu"),_8.btnList["TO-cell-insert-after"][1]],[HTMLArea._lc("Insert Cell Before","ContextMenu"),function(){ +tableOperation("TO-cell-insert-before"); +},HTMLArea._lc("Insert Cell After","ContextMenu"),_8.btnList["TO-cell-insert-before"][1]],[HTMLArea._lc("Delete Cell","ContextMenu"),function(){ +tableOperation("TO-cell-delete"); +},HTMLArea._lc("Delete Cell","ContextMenu"),_8.btnList["TO-cell-delete"][1]],[HTMLArea._lc("Merge Cells","ContextMenu"),function(){ +tableOperation("TO-cell-merge"); +},HTMLArea._lc("Merge Cells","ContextMenu"),_8.btnList["TO-cell-merge"][1]]); +break; +case "tr": +tr=_5; +if(!_a){ +break; +} +_d.push(null,[HTMLArea._lc("Ro_w Properties...","ContextMenu"),function(){ +tableOperation("TO-row-prop"); +},HTMLArea._lc("Show the Table Row Properties dialog","ContextMenu"),_8.btnList["TO-row-prop"][1]],[HTMLArea._lc("I_nsert Row Before","ContextMenu"),function(){ +tableOperation("TO-row-insert-above"); +},HTMLArea._lc("Insert a new row before the current one","ContextMenu"),_8.btnList["TO-row-insert-above"][1]],[HTMLArea._lc("In_sert Row After","ContextMenu"),function(){ +tableOperation("TO-row-insert-under"); +},HTMLArea._lc("Insert a new row after the current one","ContextMenu"),_8.btnList["TO-row-insert-under"][1]],[HTMLArea._lc("_Delete Row","ContextMenu"),function(){ +tableOperation("TO-row-delete"); +},HTMLArea._lc("Delete the current row","ContextMenu"),_8.btnList["TO-row-delete"][1]]); +break; +case "table": +_f=_5; +if(!_a){ +break; +} +_d.push(null,[HTMLArea._lc("_Table Properties...","ContextMenu"),function(){ +tableOperation("TO-table-prop"); +},HTMLArea._lc("Show the Table Properties dialog","ContextMenu"),_8.btnList["TO-table-prop"][1]],[HTMLArea._lc("Insert _Column Before","ContextMenu"),function(){ +tableOperation("TO-col-insert-before"); +},HTMLArea._lc("Insert a new column before the current one","ContextMenu"),_8.btnList["TO-col-insert-before"][1]],[HTMLArea._lc("Insert C_olumn After","ContextMenu"),function(){ +tableOperation("TO-col-insert-after"); +},HTMLArea._lc("Insert a new column after the current one","ContextMenu"),_8.btnList["TO-col-insert-after"][1]],[HTMLArea._lc("De_lete Column","ContextMenu"),function(){ +tableOperation("TO-col-delete"); +},HTMLArea._lc("Delete the current column","ContextMenu"),_8.btnList["TO-col-delete"][1]]); +break; +case "body": +_d.push(null,[HTMLArea._lc("Justify Left","ContextMenu"),function(){ +_7.execCommand("justifyleft"); +},null,_8.btnList["justifyleft"][1]],[HTMLArea._lc("Justify Center","ContextMenu"),function(){ +_7.execCommand("justifycenter"); +},null,_8.btnList["justifycenter"][1]],[HTMLArea._lc("Justify Right","ContextMenu"),function(){ +_7.execCommand("justifyright"); +},null,_8.btnList["justifyright"][1]],[HTMLArea._lc("Justify Full","ContextMenu"),function(){ +_7.execCommand("justifyfull"); +},null,_8.btnList["justifyfull"][1]]); +break; +} +} +if(_b&&!_e){ +_9.push(null,[HTMLArea._lc("Make lin_k...","ContextMenu"),function(){ +_7.config.btnList["createlink"][3](_7); +},HTMLArea._lc("Create a link","ContextMenu"),_8.btnList["createlink"][1]]); +} +for(var i=0;i<_d.length;++i){ +_9.push(_d[i]); +} +if(!/html|body/i.test(_c.tagName)){ +_9.push(null,[HTMLArea._lc({string:"Remove the $elem Element...",replace:{elem:"<"+_c.tagName+">"}},"ContextMenu"),function(){ +if(confirm(HTMLArea._lc("Please confirm that you want to remove this element:","ContextMenu")+" "+_c.tagName)){ +var el=_c; +var p=el.parentNode; +p.removeChild(el); +if(HTMLArea.is_gecko){ +if(p.tagName.toLowerCase()=="td"&&!p.hasChildNodes()){ +p.appendChild(_7._doc.createElement("br")); +} +_7.forceRedraw(); +_7.focusEditor(); +_7.updateToolbar(); +if(_f){ +var _1e=_f.style.borderCollapse; +_f.style.borderCollapse="collapse"; +_f.style.borderCollapse="separate"; +_f.style.borderCollapse=_1e; +} +} +} +},HTMLArea._lc("Remove this node from the document","ContextMenu")],[HTMLArea._lc("Insert paragraph before","ContextMenu"),function(){ +insertPara(false); +},HTMLArea._lc("Insert a paragraph before the current node","ContextMenu")],[HTMLArea._lc("Insert paragraph after","ContextMenu"),function(){ +insertPara(true); +},HTMLArea._lc("Insert a paragraph after the current node","ContextMenu")]); +} +if(!_9[0]){ +_9.shift(); +} +return _9; +}; +ContextMenu.prototype.popupMenu=function(ev){ +var _20=this; +if(this.currentMenu){ +this.closeMenu(); +} +function getPos(el){ +var r={x:el.offsetLeft,y:el.offsetTop}; +if(el.offsetParent){ +var tmp=getPos(el.offsetParent); +r.x+=tmp.x; +r.y+=tmp.y; +} +return r; +} +function documentClick(ev){ +ev||(ev=window.event); +if(!_20.currentMenu){ +alert(HTMLArea._lc("How did you get here? (Please report!)","ContextMenu")); +return false; +} +var el=HTMLArea.is_ie?ev.srcElement:ev.target; +for(;el!=null&&el!=_20.currentMenu;el=el.parentNode){ +} +if(el==null){ +_20.closeMenu(); +} +} +var _26=[]; +function keyPress(ev){ +ev||(ev=window.event); +HTMLArea._stopEvent(ev); +if(ev.keyCode==27){ +_20.closeMenu(); +return false; +} +var key=String.fromCharCode(HTMLArea.is_ie?ev.keyCode:ev.charCode).toLowerCase(); +for(var i=_26.length;--i>=0;){ +var k=_26[i]; +if(k[0].toLowerCase()==key){ +k[1].__msh.activate(); +} +} +} +_20.closeMenu=function(){ +_20.currentMenu.parentNode.removeChild(_20.currentMenu); +_20.currentMenu=null; +HTMLArea._removeEvent(document,"mousedown",documentClick); +HTMLArea._removeEvent(_20.editordoc,"mousedown",documentClick); +if(_26.length>0){ +HTMLArea._removeEvent(_20.editordoc,"keypress",keyPress); +} +if(HTMLArea.is_ie){ +_20.iePopup.hide(); +} +}; +var _2b=HTMLArea.is_ie?ev.srcElement:ev.target; +var _2c=getPos(_20.editor._htmlArea); +var x=ev.clientX+_2c.x; +var y=ev.clientY+_2c.y; +var div; +var doc; +if(!HTMLArea.is_ie){ +doc=document; +}else{ +var _31=this.iePopup=window.createPopup(); +doc=_31.document; +doc.open(); +doc.write(""); +doc.close(); +} +div=doc.createElement("div"); +if(HTMLArea.is_ie){ +div.unselectable="on"; +} +div.oncontextmenu=function(){ +return false; +}; +div.className="htmlarea-context-menu"; +if(!HTMLArea.is_ie){ +div.style.left=div.style.top="0px"; +} +doc.body.appendChild(div); +var _32=doc.createElement("table"); +div.appendChild(_32); +_32.cellSpacing=0; +_32.cellPadding=0; +var _33=doc.createElement("tbody"); +_32.appendChild(_33); +var _34=this.getContextMenu(_2b); +for(var i=0;i<_34.length;++i){ +var _36=_34[i]; +var _37=doc.createElement("tr"); +_33.appendChild(_37); +if(HTMLArea.is_ie){ +_37.unselectable="on"; +}else{ +_37.onmousedown=function(ev){ +HTMLArea._stopEvent(ev); +return false; +}; +} +if(!_36){ +_37.className="separator"; +var td=doc.createElement("td"); +td.className="icon"; +var _3a=">"; +if(HTMLArea.is_ie){ +td.unselectable="on"; +_3a=" unselectable='on' style='height=1px'> "; +} +td.innerHTML=""; +var td1=td.cloneNode(true); +td1.className="label"; +_37.appendChild(td); +_37.appendChild(td1); +}else{ +var _3c=_36[0]; +_37.className="item"; +_37.__msh={item:_37,label:_3c,action:_36[1],tooltip:_36[2]||null,icon:_36[3]||null,activate:function(){ +_20.closeMenu(); +_20.editor.focusEditor(); +this.action(); +}}; +_3c=_3c.replace(/_([a-zA-Z0-9])/,"$1"); +if(_3c!=_36[0]){ +_26.push([RegExp.$1,_37]); +} +_3c=_3c.replace(/__/,"_"); +var td1=doc.createElement("td"); +if(HTMLArea.is_ie){ +td1.unselectable="on"; +} +_37.appendChild(td1); +td1.className="icon"; +if(_37.__msh.icon){ +var t=HTMLArea.makeBtnImg(_37.__msh.icon,doc); +td1.appendChild(t); +} +var td2=doc.createElement("td"); +if(HTMLArea.is_ie){ +td2.unselectable="on"; +} +_37.appendChild(td2); +td2.className="label"; +td2.innerHTML=_3c; +_37.onmouseover=function(){ +this.className+=" hover"; +_20.editor._statusBarTree.innerHTML=this.__msh.tooltip||" "; +}; +_37.onmouseout=function(){ +this.className="item"; +}; +_37.oncontextmenu=function(ev){ +this.__msh.activate(); +if(!HTMLArea.is_ie){ +HTMLArea._stopEvent(ev); +} +return false; +}; +_37.onmouseup=function(ev){ +var _41=(new Date()).getTime(); +if(_41-_20.timeStamp>500){ +this.__msh.activate(); +} +if(!HTMLArea.is_ie){ +HTMLArea._stopEvent(ev); +} +return false; +}; +} +} +if(!HTMLArea.is_ie){ +div.style.left=x+"px"; +div.style.top=y+"px"; +}else{ +this.iePopup.show(ev.screenX,ev.screenY,300,50); +var w=div.offsetWidth; +var h=div.offsetHeight; +this.iePopup.show(ev.screenX,ev.screenY,w,h); +} +this.currentMenu=div; +this.timeStamp=(new Date()).getTime(); +HTMLArea._addEvent(document,"mousedown",documentClick); +HTMLArea._addEvent(this.editordoc,"mousedown",documentClick); +if(_26.length>0){ +HTMLArea._addEvent(this.editordoc,"keypress",keyPress); +} +HTMLArea._stopEvent(ev); +return false; +}; + diff --git a/xinha/plugins/ContextMenu/lang/de.js b/xinha/plugins/ContextMenu/lang/de.js new file mode 100644 index 0000000..d29eed8 --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/de.js @@ -0,0 +1,50 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Raimund Meyer xinha@ray-of-light.org +{ + "Cut": "Ausschneiden", + "Copy": "Kopieren", + "Paste": "Einfügen", + "_Image Properties...": "Eigenschaften", + "Show the image properties dialog": "Fenster für die Bildoptionen anzeigen", + "_Modify Link...": "Link ändern", + "Current URL is": "Aktuelle URL ist", + "Chec_k Link...": "Link testen", + "Opens this link in a new window": "Diesen Link in neuem Fenster öffnen", + "_Remove Link...": "Link entfernen", + "Please confirm that you want to unlink this element.": "Wollen sie diesen Link wirklich entfernen?", + "Link points to:": "Link zeigt auf:", + "Unlink the current element": "Link auf Element entfernen", + "C_ell Properties...": "Zellenoptionen", + "Show the Table Cell Properties dialog": "Zellenoptionen anzeigen", + "Ro_w Properties...": "Zeilenoptionen", + "Show the Table Row Properties dialog": "Zeilenoptionen anzeigen", + "I_nsert Row Before": "Zeile einfügen vor Position", + "Insert a new row before the current one": "Zeile einfügen vor der aktuellen Position", + "In_sert Row After": "Zeile einügen nach Position", + "Insert a new row after the current one": "Zeile einfügen nach der aktuellen Position", + "_Delete Row": "Zeile löschen", + "Delete the current row": "Zeile löschen", + "_Table Properties...": "Tabellenoptionen", + "Show the Table Properties dialog": "Tabellenoptionen anzeigen", + "Insert _Column Before": "Spalte einfügen vor Position", + "Insert a new column before the current one": "Spalte einfügen vor der aktuellen Position", + "Insert C_olumn After": "Spalte einfügen nach Position", + "Insert a new column after the current one": "Spalte einfügen nach der aktuellen Position", + "De_lete Column": "Spalte löschen", + "Delete the current column": "Spalte löschen", + "Justify Left": "Linksbündig", + "Justify Center": "Zentriert", + "Justify Right": "Rechtsbündig", + "Justify Full": "Blocksatz", + "Make lin_k...": "Link erstellen", + "Create a link": "Link erstellen", + "Remove the $elem Element...": "Element $elem entfernen...", + "Please confirm that you want to remove this element:": "Wollen sie dieses Element wirklich entfernen?", + "Remove this node from the document": "Dieses Element aus dem Dokument entfernen", + "Insert paragraph before": "Absatz einfügen vor Position", + "Insert a paragraph before the current node": "Absatz einfügen vor der aktuellen Position", + "Insert paragraph after": "Absatz einfügen hinter Position", + "Insert a paragraph after the current node": "Absatz einfügen hinter der aktuellen Position", + "How did you get here? (Please report!)": "Wie sind Sie denn hier hin gekommen? (Please report!)" +}; diff --git a/xinha/plugins/ContextMenu/lang/el.js b/xinha/plugins/ContextMenu/lang/el.js new file mode 100644 index 0000000..611bd8b --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/el.js @@ -0,0 +1,47 @@ +// I18N constants +// LANG: "el", ENCODING: UTF-8 +// Author: Dimitris Glezos, dimitris@glezos.com +{ + "Cut": "ΑποκοπΞ�", + "Copy": "ΑντιγραφΞ�", + "Paste": "Ξ•Ο€ΞΉΞΊΟŒΞ»Ξ»Ξ·ΟƒΞ·", + "_Image Properties...": "Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ Ξ•ΞΉΞΊΟŒΞ½Ξ±Ο‚...", + "_Modify Link...": "Ξ�ροποποίηση συνδέσμου...", + "Chec_k Link...": "ΞˆΞ»Ξ΅Ξ³Ο‡ΞΏΟ‚ συνδέσμων...", + "_Remove Link...": "ΔιαγραφΞ� συνδέσμου...", + "C_ell Properties...": "Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ κΡλιού...", + "Ro_w Properties...": "Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ γραμμΞ�Ο‚...", + "I_nsert Row Before": "ΕισαγωγΞ� γραμμΞ�Ο‚ πριν", + "In_sert Row After": "ΕισαγωγΞ� γραμμΞ�Ο‚ μΡτά", + "_Delete Row": "ΔιαγραφΞ� γραμμΞ�Ο‚", + "_Table Properties...": "Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ πίνακα...", + "Insert _Column Before": "ΕισαγωγΞ� στΞ�λης πριν", + "Insert C_olumn After": "ΕισαγωγΞ� στΞ�λης μΡτά", + "De_lete Column": "ΔιαγραφΞ� στΞ�λης", + "Justify Left": "Στοίχηση ΑριστΡρά", + "Justify Center": "Στοίχηση ΞšΞ­Ξ½Ο„ΟΞΏ", + "Justify Right": "Στοίχηση ΔΡξιά", + "Justify Full": "Ξ Ξ»Ξ�ρης Στοίχηση", + "Make lin_k...": "Δημιουργία συνδέσμου...", + "Remove the $elem Element...": "ΑφαίρΡση $elem στοιχΡίου...", + "Please confirm that you want to remove this element:": "ΕίστΡ Ξ²Ξ­Ξ²Ξ±ΞΉΞΏΟ‚ πως θέλΡτΡ Ξ½Ξ± αφαιρέσΡτΡ το στοιχΡίο ", + "Remove this node from the document": "ΑφαίρΡση αυτού του ΞΊΟŒΞΌΞ²ΞΏΟ… Ξ±Ο€ΟŒ το έγγραφο", + "How did you get here? (Please report!)": "Ξ ΟŽΟ‚ Ξ�ρθατΡ μέχρι Ρδώ; (ΠαρακαλούμΡ αναφέρΡτΡ το!)", + "Show the image properties dialog": "Εμφάνιση Ξ΄ΞΉΞ±Ξ»ΟŒΞ³ΞΏΟ… ΞΌΞ΅ τις Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ Ξ΅ΞΉΞΊΟŒΞ½Ξ±Ο‚", + "Modify URL": "Ξ�ροποποίηση URL", + "Current URL is": "Ξ�ΞΏ τρέχων URL Ρίναι", + "Opens this link in a new window": "ΑνοίγΡι Ξ±Ο…Ο„ΟŒ τον σύνδΡσμο σΡ Ξ­Ξ½Ξ± Ξ½Ξ­ΞΏ παράθυρο", + "Please confirm that you want to unlink this element.": "ΕίστΡ Ξ²Ξ­Ξ²Ξ±ΞΉΞΏΟ‚ πως θέλΡτΡ Ξ½Ξ± αφαιρέσΡτΡ τον σύνδΡσμο Ξ±Ο€ΟŒ Ξ±Ο…Ο„ΟŒ το στοιχΡίο:", + "Link points to:": "Ο σύνδΡμος οδηγΡί Ρδώ:", + "Unlink the current element": "ΑφαίρΡση συνδέσμου Ξ±Ο€ΟŒ το Ο€Ξ±ΟΟŽΞ½ στοιχΡίο", + "Show the Table Cell Properties dialog": "Εμφάνιση Ξ΄ΞΉΞ±Ξ»ΟŒΞ³ΞΏΟ… ΞΌΞ΅ τις Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ κΡλιού Ξ Ξ―Ξ½Ξ±ΞΊΞ±", + "Show the Table Row Properties dialog": "Εμφάνιση Ξ΄ΞΉΞ±Ξ»ΟŒΞ³ΞΏΟ… ΞΌΞ΅ τις Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ γραμμΞ�Ο‚ Ξ Ξ―Ξ½Ξ±ΞΊΞ±", + "Insert a new row before the current one": "ΕισαγωγΞ� ΞΌΞΉΞ±Ο‚ Ξ½Ξ­Ξ±Ο‚ γραμμΞ�Ο‚ πριν την ΡπιλΡγμένη", + "Insert a new row after the current one": "ΕισαγωγΞ� ΞΌΞΉΞ±Ο‚ Ξ½Ξ­Ξ±Ο‚ γραμμΞ�Ο‚ μΡτά την ΡπιλΡγμένη", + "Delete the current row": "ΔιαγραφΞ� ΡπιλΡγμένης γραμμΞ�Ο‚", + "Show the Table Properties dialog": "Εμφάνιση Ξ΄ΞΉΞ±Ξ»ΟŒΞ³ΞΏΟ… ΞΌΞ΅ τις Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ Ξ Ξ―Ξ½Ξ±ΞΊΞ±", + "Insert a new column before the current one": "ΕισαγωγΞ� Ξ½Ξ­Ξ±Ο‚ στΞ�λης πριν την ΡπιλΡγμένη", + "Insert a new column after the current one": "ΕισαγωγΞ� Ξ½Ξ­Ξ±Ο‚ στΞ�λης μΡτά την ΡπιλΡγμένη", + "Delete the current column": "ΔιαγραφΞ� ΡπιλΡγμένης στΞ�λης", + "Create a link": "Δημιουργία συνδέσμου" +}; diff --git a/xinha/plugins/ContextMenu/lang/fr.js b/xinha/plugins/ContextMenu/lang/fr.js new file mode 100644 index 0000000..baef2dc --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/fr.js @@ -0,0 +1,50 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Cut": "Couper", + "Copy": "Copier", + "Paste": "Coller", + "_Image Properties...": "_Propriétés de l'image...", + "_Modify Link...": "_Modifier le lien...", + "Chec_k Link...": "_Vérifier le lien...", + "_Remove Link...": "_Supprimer le lien...", + "C_ell Properties...": "P_ropriétés de la cellule...", + "Ro_w Properties...": "Pr_opriétés de la rangée...", + "I_nsert Row Before": "Insérer une rangée a_vant", + "In_sert Row After": "Insér_er une rangée après", + "_Delete Row": "Suppr_imer une rangée", + "_Table Properties...": "Proprié_tés de la table...", + "Insert _Column Before": "I_nsérer une colonne avant", + "Insert C_olumn After": "Insérer une colonne après", + "De_lete Column": "_Supprimer la colonne", + "Justify Left": "Aligner à gauche", + "Justify Center": "Aligner au centre", + "Justify Right": "Aligner à droite", + "Justify Full": "Justifier", + "Make lin_k...": "Convertir en lien...", + "Remove the $elem Element...": "Supprimer Élément $elem...", + "Insert paragraph before": "Insérer un paragraphe avant", + "Insert paragraph after": "Insérer un paragraphe après", + "Please confirm that you want to remove this element:": "Confirmer la suppression de cet élément:", + "Remove this node from the document": "Supprimer ce noeud du document", + "How did you get here? (Please report!)": "Comment êtes-vous arrivé ici ? (Reportez le bug SVP !)", + "Show the image properties dialog": "Afficher le dialogue des propriétés d'image", + "Modify URL": "Modifier l'URL", + "Current URL is": "L'URL courante est", + "Opens this link in a new window": "Ouvrir ce lien dans une nouvelle fenêtre", + "Please confirm that you want to unlink this element.": "Voulez-vous vraiment enlever le lien présent sur cet élément.", + "Link points to:": "Le lien pointe sur:", + "Unlink the current element": "Enlever le lien sur cet élément", + "Show the Table Cell Properties dialog": "Afficher la boite de propriété des cellules", + "Show the Table Row Properties dialog": "Afficher la boite de propriété des rangées", + "Insert a new row before the current one": "Insérer une nouvelle rangée avant celle-ci", + "Insert a new row after the current one": "Insérer une nouvelle rangée après celle-ci", + "Delete the current row": "Supprimer la rangée courante", + "Show the Table Properties dialog": "Afficher la boite de propriété de tableau", + "Insert a new column before the current one": "Insérer une nouvelle rangée avant celle-ci", + "Insert a new column after the current one": "Insérer une nouvelle colonne après celle-ci", + "Delete the current column": "Supprimer cette colonne", + "Create a link": "Créer un lien", + "Insert a paragraph before the current node": "Insérer un paragraphe avant le noeud courant", + "Insert a paragraph after the current node": "Insérer un paragraphe après le noeud courant" +}; \ No newline at end of file diff --git a/xinha/plugins/ContextMenu/lang/he.js b/xinha/plugins/ContextMenu/lang/he.js new file mode 100644 index 0000000..b95a5ac --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/he.js @@ -0,0 +1,47 @@ +// I18N constants +// LANG: "he", ENCODING: UTF-8 +// Author: Liron Newman, http://www.eesh.net, +{ + "Cut": "גזור", + "Copy": "העתק", + "Paste": "הדבק", + "_Image Properties...": "_מאפייני תמונה...", + "_Modify Link...": "_שנה קישור...", + "Chec_k Link...": "בדו_ק קישור...", + "_Remove Link...": "_הסר קישור...", + "C_ell Properties...": "מאפייני ת_א...", + "Ro_w Properties...": "מאפייני _טור...", + "I_nsert Row Before": "ה_כנס שורה לפני", + "In_sert Row After": "הכנ_ס שורה אחרי", + "_Delete Row": "_מחק שורה", + "_Table Properties...": "מאפייני ט_בלה...", + "Insert _Column Before": "הכנס _טור לפני", + "Insert C_olumn After": "הכנס ט_ור אחרי", + "De_lete Column": "מח_ק טור", + "Justify Left": "ישור לשמאל", + "Justify Center": "ישור למרכז", + "Justify Right": "ישור לימין", + "Justify Full": "ישור לשורה מלאה", + "Make lin_k...": "צור קי_שור...", + "Remove the $elem Element...": "הסר את אלמנט ה- $elem...", + "Please confirm that you want to remove this element:": "אנא אשר שברצונך להסיר את האלמנט הזה:", + "Remove this node from the document": "הסרה של node זה מהמסמך", + "How did you get here? (Please report!)": "איך הגעת הנה? (אנא דווח!)", + "Show the image properties dialog": "מציג את חלון הדו-שיח של מאפייני תמונה", + "Modify URL": "שינוי URL", + "Current URL is": "URL נוכחי הוא", + "Opens this link in a new window": "פתיחת קישור זה בחלון חדש", + "Please confirm that you want to unlink this element.": "אנא אשר שאתה רוצה לנתק את אלמנט זה.", + "Link points to:": "הקישור מצביע אל:", + "Unlink the current element": "ניתוק את האלמנט הנוכחי", + "Show the Table Cell Properties dialog": "מציג את חלון הדו-שיח של מאפייני תא בטבלה", + "Show the Table Row Properties dialog": "מציג את חלון הדו-שיח של מאפייני שורה בטבלה", + "Insert a new row before the current one": "הוספת שורה חדשה לפני הנוכחית", + "Insert a new row after the current one": "הוספת שורה חדשה אחרי הנוכחית", + "Delete the current row": "מחיקת את השורה הנוכחית", + "Show the Table Properties dialog": "מציג את חלון הדו-שיח של מאפייני טבלה", + "Insert a new column before the current one": "הוספת טור חדש לפני הנוכחי", + "Insert a new column after the current one": "הוספת טור חדש אחרי הנוכחי", + "Delete the current column": "מחיקת את הטור הנוכחי", + "Create a link": "יצירת קישור" +}; diff --git a/xinha/plugins/ContextMenu/lang/ja.js b/xinha/plugins/ContextMenu/lang/ja.js new file mode 100644 index 0000000..be591f3 --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/ja.js @@ -0,0 +1,53 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Cut": "切り取り", + "Copy": "コピー", + "Paste": "貼り付け", + "_Image Properties...": "画像のプロパティ(_I)...", + "Show the image properties dialog": "この画像のプロパティダイアログを表示します", + "_Modify Link...": "リンクの修正(_M)...", + "Current URL is": "現在のURL", + "Chec_k Link...": "リンクを確認(_K)...", + "Opens this link in a new window": "このリンクを新しいウィンドウで開きます", + "_Remove Link...": "リンクの削除(_R)", + "Please confirm that you want to unlink this element.": "この要素のリンクを削除します。よろしいですか。", + "Link points to:": "リンク先:", + "Unlink the current element": "この要素のリンクを解除", + "C_ell Properties...": "セルのプロパティ(_E)...", + "Ro_w Properties...": "行のプロパティ(_W)...", + "Show the Table Row Properties dialog": "テーブル行のプロパティダイアログを表示します", + "I_nsert Row Before": "上に行を挿入(_N)", + "Insert a new row before the current one": "選択中の行の上に一行挿入します", + "In_sert Row After": "下に行を挿入(_S)", + "Insert a new row after the current one": "選択中の行の下に一行挿入します", + "_Delete Row": "行の削除(_D)", + "Delete the current row": "選択中の行を削除します", + "_Table Properties...": "テーブルのプロパティ(_T)...", + "Show the Table Properties dialog": "テーブルのプロパティダイアログを表示します", + "Insert _Column Before": "左に列を挿入(_C)", + "Insert a new column before the current one": "選択中の列の左に一列挿入します", + "Insert C_olumn After": "右に列を挿入(_O)", + "Insert a new column after the current one": "選択中の列の右に一列挿入します", + "De_lete Column": "列の削除(_L)", + "Delete the current column": "選択中の列を削除します", + "Justify Left": "左寄せ", + "Justify Center": "中央寄せ", + "Justify Right": "右寄せ", + "Justify Full": "均等割付", + "Make lin_k...": "リンクの作成(_K)...", + "Create a link": "新たなリンクを作成します", + "Remove the $elem Element...": "$elem 要素を削除 ...", + "Please confirm that you want to remove this element:": "この要素を削除します。よろしいですか。:", + "Remove this node from the document": "ドキュメントからこのノードを削除します", + "Insert paragraph before": "前に段落を挿入", + "Insert a paragraph before the current node": "選択中のノードの手前に段落を挿入します", + "Insert paragraph after": "後に段落を挿入", + "Insert a paragraph after the current node": "選択中のノードの後に段落を挿入します", + "How did you get here? (Please report!)": "どうやってここに来ましたか?(どうか報告を!)", + "Show the Table Cell Properties dialog": "テーブルセルのプロパティダイアログを表示します", + "Insert Cell Before": "前にセルを挿入", + "Insert Cell After": "後にセルを挿入", + "Delete Cell": "セルの削除", + "Merge Cells": "セルの結合" +}; \ No newline at end of file diff --git a/xinha/plugins/ContextMenu/lang/nb.js b/xinha/plugins/ContextMenu/lang/nb.js new file mode 100644 index 0000000..cbe4451 --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/nb.js @@ -0,0 +1,53 @@ +// I18N constants +// LANG: "no", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +// Used key commands +// C,D,e, ,I, ,k,k,l,M, ,n,o,R, ,s,T, ,w : English +// H B j R m F v : Norwegian +{ + "Cut": "Klipp ut", + "Copy": "Kopier", + "Paste": "Lim inn", + "_Image Properties...": "_Bildeegenskaper...", + "Show the image properties dialog": "Vis bildeegenskaper", + "_Modify Link...": "_Rediger Link...", + "Current URL is": "Gjeldende URL er", + "Chec_k Link...": "Sje_kk Link...", + "Opens this link in a new window": "Åpner denne link i nytt vindu", + "_Remove Link...": "_Fjerne Link...", + "Please confirm that you want to unlink this element.": "Vennligst bekreft at du ønsker å fjerne link på elementet", + "Link points to:": "Link peker til:", + "Unlink the current element": "Fjerne link på gjeldende element", + "C_ell Properties...": "C_elleegenskaper...", + "Show the Table Cell Properties dialog": "Vis egenskaper for celle", + "Ro_w Properties...": "Rad Egenskaper... (_w)", + "Show the Table Row Properties dialog": "Vis egenskaper for rad", + "I_nsert Row Before": "Sett I_nn rad før", + "Insert a new row before the current one": "Sett inn ny rad før gjeldende", + "In_sert Row After": "_Sett inn rad etter", + "Insert a new row after the current one": "Sett inn ny rad etter gjeldende", + "_Delete Row": "Slett rad (_d)", + "Delete the current row": "Slett gjeldende rad", + "_Table Properties...": "_Tabellegenskaper...", + "Show the Table Properties dialog": "Vis egenskaper for tabellen", + "Insert _Column Before": "Sett inn kolonne etter (_c)", + "Insert a new column before the current one": "Sett inn kolonne før gjeldende", + "Insert C_olumn After": "Sett inn k_olonne etter", + "Insert a new column after the current one": "Sett inn kolonne etter gjeldende", + "De_lete Column": "S_lett kolonne", + "Delete the current column": "Slett gjeldende kolonne", + "Justify Left": "_Venstrejuster", + "Justify Center": "_Midtjuster", + "Justify Right": "_Høyrejuster", + "Justify Full": "Blokk_juster", + "Make lin_k...": "Lag len_ke...", + "Create a link": "Lag ny link", + "Remove the $elem Element...": "Fjerne $elem elementet...", + "Please confirm that you want to remove this element:": "Vennligst bekreft at du ønsker å fjerne elementet:", + "Remove this node from the document": "Fjerne denne node fra dokumentet", + "Insert paragraph before": "Sett inn paragraf før", + "Insert a paragraph before the current node": "Sett inn paragraf før gjeldende node", + "Insert paragraph after": "Sett inn paragraf etter", + "Insert a paragraph after the current node": "Sett inn paragraf etter gjeldende node", + "How did you get here? (Please report!)": "Hva skjedde? (Vennligst beskriv)" +}; \ No newline at end of file diff --git a/xinha/plugins/ContextMenu/lang/nl.js b/xinha/plugins/ContextMenu/lang/nl.js new file mode 100644 index 0000000..8697b36 --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/nl.js @@ -0,0 +1,47 @@ +// I18N constants +// LANG: "nl", ENCODING: UTF-8 +// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl +{ + "Cut": "Knippen", + "Copy": "Kopiëren", + "Paste": "Plakken", + "_Image Properties...": "Eigenschappen afbeelding...", + "_Modify Link...": "Hyperlin_k aanpassen...", + "Chec_k Link...": "Controleer hyperlin_k...", + "_Remove Link...": "Ve_rwijder hyperlink...", + "C_ell Properties...": "C_eleigenschappen...", + "Ro_w Properties...": "Rijeigenscha_ppen...", + "I_nsert Row Before": "Rij invoegen boven", + "In_sert Row After": "Rij invoegen onder", + "_Delete Row": "Rij _verwijderen", + "_Table Properties...": "_Tabeleigenschappen...", + "Insert _Column Before": "Kolom invoegen voor", + "Insert C_olumn After": "Kolom invoegen na", + "De_lete Column": "Kolom verwijderen", + "Justify Left": "Links uitlijnen", + "Justify Center": "Centreren", + "Justify Right": "Rechts uitlijnen", + "Justify Full": "Uitvullen", + "Make lin_k...": "Maak hyperlin_k...", + "Remove the $elem Element...": "Verwijder het $elem element...", + "Please confirm that you want to remove this element:": "Is het werkelijk de bedoeling dit element te verwijderen:", + "Remove this node from the document": "Verwijder dit punt van het document", + "How did you get here? (Please report!)": "Hoe kwam je hier? (A.U.B. doorgeven!)", + "Show the image properties dialog": "Laat het afbeeldingseigenschappen dialog zien", + "Modify URL": "Aanpassen URL", + "Current URL is": "Huidig URL is", + "Opens this link in a new window": "Opend deze hyperlink in een nieuw venster", + "Please confirm that you want to unlink this element.": "Is het werkelijk de bedoeling dit element te unlinken.", + "Link points to:": "Hyperlink verwijst naar:", + "Unlink the current element": "Unlink het huidige element", + "Show the Table Cell Properties dialog": "Laat de tabel celeigenschappen dialog zien", + "Show the Table Row Properties dialog": "Laat de tabel rijeigenschappen dialog zien", + "Insert a new row before the current one": "Voeg een nieuwe rij in boven de huidige", + "Insert a new row after the current one": "Voeg een nieuwe rij in onder de huidige", + "Delete the current row": "Verwijder de huidige rij", + "Show the Table Properties dialog": "Laat de tabel eigenschappen dialog zien", + "Insert a new column before the current one": "Voeg een nieuwe kolom in voor de huidige", + "Insert a new column after the current one": "Voeg een nieuwe kolom in na de huidige", + "Delete the current column": "Verwijder de huidige kolom", + "Create a link": "Maak een hyperlink" +}; diff --git a/xinha/plugins/ContextMenu/lang/pl.js b/xinha/plugins/ContextMenu/lang/pl.js new file mode 100644 index 0000000..42220a1 --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/pl.js @@ -0,0 +1,50 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz, http://www.eskot.krakow.pl/portfolio/, koto@webworkers.pl +{ + "Cut": "Wytnij", + "Copy": "Kopiuj", + "Paste": "Wklej", + "_Image Properties...": "Właściwości obrazka", + "Show the image properties dialog": "Pokaż okienko właściwości obrazka", + "_Modify Link...": "Zmień odnośnik", + "Current URL is": "Bieżący URL odnośnika", + "Chec_k Link...": "Sprawdź odnośnik", + "Opens this link in a new window": "Otwiera ten odnośnik w nowym oknie", + "_Remove Link...": "Usuń odnośnik", + "Please confirm that you want to unlink this element.": "Na pewno chcesz usunąć odnośnik?", + "Link points to:": "Odnośnik wskazuje na:", + "Unlink the current element": "Usuń odnośnik z zaznaczonego elementu", + "C_ell Properties...": "Właściwości komórki", + "Show the Table Cell Properties dialog": "Pokaż okno właściwości komórki", + "Ro_w Properties...": "Właściwości wiersza", + "Show the Table Row Properties dialog": "Pokaż okno właściwości wiersza", + "I_nsert Row Before": "Wstaw wiersz przed", + "Insert a new row before the current one": "Wstaw nowy wiersz przed bieżącym", + "In_sert Row After": "Wstaw wiersz po", + "Insert a new row after the current one": "Wstaw nowy wiersz po bieżącym", + "_Delete Row": "Usuń wiersz", + "Delete the current row": "Usuń bieżący wiersz", + "_Table Properties...": "Właściwości tabeli", + "Show the Table Properties dialog": "Pokaż okienko właściwości tabeli", + "Insert _Column Before": "Wstaw kolumnę przed", + "Insert a new column before the current one": "Wstaw nową kolumnę przed bieżącą", + "Insert C_olumn After": "Wstaw kolumnę po", + "Insert a new column after the current one": "Wstaw nową kolumnę po bieżącej", + "De_lete Column": "Usuń kolumnę", + "Delete the current column": "Usuwa bieżącą kolumnę", + "Justify Left": "Wyrównaj do lewej", + "Justify Center": "Wycentruj", + "Justify Right": "Wyrównaj do prawej", + "Justify Full": "Wyjustuj", + "Make lin_k...": "Utwórz odnośnik", + "Create a link": "Utwórz odnośnik", + "Remove the $elem Element...": "Usuń $elem...", + "Please confirm that you want to remove this element:": "Na pewno chcesz usunąć ten element?", + "Remove this node from the document": "Usuń ten element z dokumentu", + "Insert paragraph before": "Wstaw akapit przed", + "Insert a paragraph before the current node": "Wstaw akapit przed bieżącym elementem", + "Insert paragraph after": "Wstaw akapit po", + "Insert a paragraph after the current node": "Wstaw akapit po bieżącym elemencie", + "How did you get here? (Please report!)": "Jak tu trafiłeś (Proszę, podaj okoliczności!)" +} diff --git a/xinha/plugins/ContextMenu/lang/sv.js b/xinha/plugins/ContextMenu/lang/sv.js new file mode 100644 index 0000000..139c262 --- /dev/null +++ b/xinha/plugins/ContextMenu/lang/sv.js @@ -0,0 +1,54 @@ +// I18N constants +// LANG: "sv", ENCODING: UTF-8 +// Swedish version for rev. 477 (Mar 2006) by Thomas Loo + +// TODO: Proper keybindings +// C,D,e, ,I, ,k,k,l,M, ,n,o,R, ,s,T, ,w : English +// H B j R m F v : Swedish +{ + "Cut": "Klipp ut", + "Copy": "Kopiera", + "Paste": "Klistra in", + "_Image Properties...": "_Bildegenskaper...", + "Show the image properties dialog": "Visa bildegenskaper", + "_Modify Link...": "_Redigera Länk...", + "Current URL is": "Aktuellt URL är", + "Chec_k Link...": "Kontrollera länk...", + "Opens this link in a new window": "Öppna länk i nytt fönster", + "_Remove Link...": "_Ta bort länk...", + "Please confirm that you want to unlink this element.": "Bekräfta borttagning av länk", + "Link points to:": "Länken pekar mot:", + "Unlink the current element": "Ta bort länk kopplad till elementet", + "C_ell Properties...": "C_ellegenskaper...", + "Show the Table Cell Properties dialog": "Visa egenskaper for cellen", + "Ro_w Properties...": "Radegenskaper... (_w)", + "Show the Table Row Properties dialog": "Visa egenskaper för rad", + "I_nsert Row Before": "I_nfoga rad före", + "Insert a new row before the current one": "Infoga ny rad före aktuell", + "In_sert Row After": "Infoga rad efter aktuell rad", + "Insert a new row after the current one": "Infoga ny rad efter aktuell", + "_Delete Row": "Radera rad (_d)", + "Delete the current row": "T bort aktuell rad", + "_Table Properties...": "_Tabellegenskaper...", + "Show the Table Properties dialog": "Visa tabellegenskaper", + "Insert _Column Before": "Infoga kolumn efter (_c)", + "Insert a new column before the current one": "Infoga kolumn före aktuell", + "Insert C_olumn After": "Infoga k_olumn efter", + "Insert a new column after the current one": "Infoga kolumn efter aktuell", + "De_lete Column": "_Radera kolumn", + "Delete the current column": "Radera aktuell kolumn", + "Justify Left": "_Vänsterjustera", + "Justify Center": "_Centerjustera", + "Justify Right": "_Högerjustera", + "Justify Full": "Block_justera", + "Make lin_k...": "Skapa län_k...", + "Create a link": "SKapa ny länk", + "Remove the $elem Element...": "Radera elementet $elem...", + "Please confirm that you want to remove this element:": "Bekräfta borttagning av element:", + "Remove this node from the document": "Radera nod från dokumentet", + "Insert paragraph before": "Infoga paragraf före", + "Insert a paragraph before the current node": "Infoga paragraf före aktuell nod", + "Insert paragraph after": "Infoga paragraf efter", + "Insert a paragraph after the current node": "Infoga paragraf efter aktuell nod", + "How did you get here? (Please report!)": "Hur hamnade du här? (Beskriv förloppet)" +}; \ No newline at end of file diff --git a/xinha/plugins/ContextMenu/menu.css b/xinha/plugins/ContextMenu/menu.css new file mode 100644 index 0000000..34c64b5 --- /dev/null +++ b/xinha/plugins/ContextMenu/menu.css @@ -0,0 +1,67 @@ +/* styles for the ContextMenu /HTMLArea */ +/* The ContextMenu plugin is (c) dynarch.com 2003. */ +/* Distributed under the same terms as HTMLArea itself */ + +div.htmlarea-context-menu { + position: absolute; + border: 1px solid #aca899; + padding: 2px; + background-color: #fff; + color: #000; + cursor: default; + z-index: 1000; +} + +div.htmlarea-context-menu table { + font: 11px tahoma,verdana,sans-serif; + border-collapse: collapse; +} + +div.htmlarea-context-menu tr.item td.icon img { +/* taken care of by xinha.makeBtnImg() */ +/* width: 18px; */ +/* height: 18px; */ +} + +div.htmlarea-context-menu tr.item td.icon { + padding: 0px 3px; + width: 18px; + height: 18px; + background-color: #cdf; +} + +div.htmlarea-context-menu tr.item td.label { + padding: 1px 10px 1px 3px; +} + +div.htmlarea-context-menu tr.separator td { + padding: 2px 0px; +} + +div.htmlarea-context-menu tr.separator td div { + border-top: 1px solid #aca899; + overflow: hidden; + position: relative; +} + +div.htmlarea-context-menu tr.separator td.icon { + background-color: #cdf; +} + +div.htmlarea-context-menu tr.separator td.icon div { +/* margin-left: 3px; */ + border-color: #fff; +} + +div.htmlarea-context-menu tr.separator td.label div { + margin-right: 3px; +} + +div.htmlarea-context-menu tr.item.hover { + background-color: #316ac5; + color: #fff; +} + +div.htmlarea-context-menu tr.item.hover td.icon { + background-color: #619af5; +} diff --git a/xinha/plugins/DoubleClick/double-click.js b/xinha/plugins/DoubleClick/double-click.js new file mode 100644 index 0000000..cf59b43 --- /dev/null +++ b/xinha/plugins/DoubleClick/double-click.js @@ -0,0 +1,66 @@ +// Double Click Plugin for HTMLArea-3.0 +// Implementation by Marijn Kampf http://www.marijn.org +// Sponsored by http://www.smiling-faces.com +// +// (c) Marijn Kampf 2004. +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). +// +// Cut-n-paste version of double click plugin. +// Almost no original code used. Based on +// Luis HTMLarea and Mihai Bazon Context Menu +// +// +// + +DoubleClick._pluginInfo = { + name : "DoubleClick", + version : "1.0", + developer : "Marijn Kampf", + developer_url : "http://www.marijn.org", + c_owner : "Marijn Kampf", + sponsor : "smiling-faces.com", + sponsor_url : "http://www.smiling-faces.com", + license : "htmlArea" +}; + +function DoubleClick(editor) { + this.editor = editor; + + // ADDING CUSTOM DOUBLE CLICK ACTIONS + // format of the dblClickList elements is "TAGNAME: [ ACTION ]" + // - TAGNAME: tagname of the tag that is double clicked + // - ACTION: function that gets called when the button is clicked. + // it has the following prototype: + // function(editor, event) + // - editor is the HTMLArea object that triggered the call + // - target is the selected object + this.editor.dblClickList = { + // Edit Link dialog + a: [ function(e) {e.config.btnList['createlink'][3](e); } ], + // Follow link + //a: [ function(editor, target) { window.location = target.href; properties(target); } ], + + img: [ function(e) {e.execCommand("insertimage");} ], + td: [ function(e) {e.execCommand("inserttable");} ] + }; +} + +DoubleClick.prototype.onGenerate = function() { + var self = this; + var doc = this.editordoc = this.editor._iframe.contentWindow.document; + HTMLArea._addEvents(doc, ["dblclick"], + function (event) { + return self.onDoubleClick(HTMLArea.is_ie ? self.editor._iframe.contentWindow.event : event); + }); + this.currentClick = null; +}; + +DoubleClick.prototype.onDoubleClick = function(ev) { + var target = HTMLArea.is_ie ? ev.srcElement : ev.target; + var tagName = target.tagName.toLowerCase(); + + if (this.editor.dblClickList[tagName] != undefined) { + this.editor.dblClickList[tagName][0](this.editor, target); + } +}; \ No newline at end of file diff --git a/xinha/plugins/DynamicCSS/dynamiccss.js b/xinha/plugins/DynamicCSS/dynamiccss.js new file mode 100644 index 0000000..366e313 --- /dev/null +++ b/xinha/plugins/DynamicCSS/dynamiccss.js @@ -0,0 +1,199 @@ +function DynamicCSS(_1,_2){ +this.editor=_1; +var _3=_1.config; +var _4=this; +var _5=null; +var _6=null; +var _7={id:"DynamicCSS-class",tooltip:this._lc("Choose stylesheet"),options:{"":""},action:function(_8){ +_4.onSelect(_8,this); +},refresh:function(_9){ +_4.updateValue(_9,this); +}}; +_3.registerDropdown(_7); +_3.addToolbarElement(["T[CSS]","DynamicCSS-class","separator"],"formatblock",-1); +} +DynamicCSS.parseStyleSheet=function(_a){ +iframe=_a._iframe.contentWindow.document; +cssArray=DynamicCSS.cssArray; +if(!cssArray){ +cssArray=new Array(); +} +for(i=0;i"; +} +}else{ +className="none"; +if(tagName=="all"){ +cssName=HTMLArea._lc("Default","DynamicCSS"); +}else{ +cssName="<"+HTMLArea._lc("Default","DynamicCSS")+">"; +} +} +_c[tagName][className]=cssName; +DynamicCSS.cssLength++; +} +} +}else{ +if(_b[rule].styleSheet){ +_c=DynamicCSS.applyCSSRule(_b[rule].styleSheet.cssRules,_c); +} +} +} +return _c; +}; +DynamicCSS._pluginInfo={name:"DynamicCSS",version:"1.5.2",developer:"Holger Hees",developer_url:"http://www.systemconcept.de/",c_owner:"Holger Hees",sponsor:"System Concept GmbH",sponsor_url:"http://www.systemconcept.de/",license:"htmlArea"}; +DynamicCSS.prototype._lc=function(_d){ +return HTMLArea._lc(_d,"DynamicCSS"); +}; +DynamicCSS.prototype.onSelect=function(_e,_f){ +var _10=_e._toolbarObjects[_f.id]; +var _11=_10.element.selectedIndex; +var _12=_10.element.value; +var _13=_e.getParentElement(); +if(_12!="none"){ +_13.className=_12; +DynamicCSS.lastClass=_12; +}else{ +if(HTMLArea.is_gecko){ +_13.removeAttribute("class"); +}else{ +_13.removeAttribute("className"); +} +} +_e.updateToolbar(); +}; +DynamicCSS.prototype.reparseTimer=function(_14,obj,_16){ +if(DynamicCSS.parseCount<9){ +setTimeout(function(){ +DynamicCSS.cssLength=0; +DynamicCSS.parseStyleSheet(_14); +if(DynamicCSS.cssOldLength!=DynamicCSS.cssLength){ +DynamicCSS.cssOldLength=DynamicCSS.cssLength; +DynamicCSS.lastClass=null; +_16.updateValue(_14,obj); +} +_16.reparseTimer(_14,obj,_16); +},DynamicCSS.parseCount*1000); +DynamicCSS.parseCount=DynamicCSS.parseCount*2; +} +}; +DynamicCSS.prototype.updateValue=function(_17,obj){ +cssArray=DynamicCSS.cssArray; +if(!cssArray){ +DynamicCSS.cssLength=0; +DynamicCSS.parseStyleSheet(_17); +cssArray=DynamicCSS.cssArray; +DynamicCSS.cssOldLength=DynamicCSS.cssLength; +DynamicCSS.parseCount=1; +this.reparseTimer(_17,obj,this); +} +var _19=_17.getParentElement(); +var _1a=_19.tagName.toLowerCase(); +var _1b=_19.className; +if(this.lastTag!=_1a||this.lastClass!=_1b){ +this.lastTag=_1a; +this.lastClass=_1b; +var _1c=_17._toolbarObjects[obj.id].element; +while(_1c.length>0){ +_1c.options[_1c.length-1]=null; +} +_1c.options[0]=new Option(this._lc("Default"),"none"); +if(cssArray){ +if(_1a!="body"||_17.config.fullPage){ +if(cssArray[_1a]){ +for(cssClass in cssArray[_1a]){ +if(typeof cssArray[_1a][cssClass]!="string"){ +continue; +} +if(cssClass=="none"){ +_1c.options[0]=new Option(cssArray[_1a][cssClass],cssClass); +}else{ +_1c.options[_1c.length]=new Option(cssArray[_1a][cssClass],cssClass); +} +} +} +if(cssArray["all"]){ +for(cssClass in cssArray["all"]){ +if(typeof cssArray["all"][cssClass]!="string"){ +continue; +} +_1c.options[_1c.length]=new Option(cssArray["all"][cssClass],cssClass); +} +} +}else{ +if(cssArray[_1a]&&cssArray[_1a]["none"]){ +_1c.options[0]=new Option(cssArray[_1a]["none"],"none"); +} +} +} +_1c.selectedIndex=0; +if(typeof _1b!="undefined"&&/\S/.test(_1b)){ +var _1d=_1c.options; +for(var i=_1d.length;--i>=0;){ +var _1f=_1d[i]; +if(_1b==_1f.value){ +_1c.selectedIndex=i; +break; +} +} +if(_1c.selectedIndex==0){ +_1c.options[_1c.length]=new Option(this._lc("Undefined"),_1b); +_1c.selectedIndex=_1c.length-1; +} +} +if(_1c.length>1){ +_1c.disabled=false; +}else{ +_1c.disabled=true; +} +} +}; + diff --git a/xinha/plugins/DynamicCSS/lang/de.js b/xinha/plugins/DynamicCSS/lang/de.js new file mode 100644 index 0000000..3cead02 --- /dev/null +++ b/xinha/plugins/DynamicCSS/lang/de.js @@ -0,0 +1,12 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// Sponsored by http://www.systemconcept.de +// Author: Holger Hees, +// (c) systemconcept.de 2004 +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). +{ + "Default": "Standard", + "Undefined": "Nicht definiert", + "Choose stylesheet": "Wählen Sie einen StyleSheet aus" +}; diff --git a/xinha/plugins/DynamicCSS/lang/fr.js b/xinha/plugins/DynamicCSS/lang/fr.js new file mode 100644 index 0000000..72a813d --- /dev/null +++ b/xinha/plugins/DynamicCSS/lang/fr.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Default": "Défaut", + "Undefined": "Non défini", + "Choose stylesheet": "Choisir feuille de style" +}; \ No newline at end of file diff --git a/xinha/plugins/DynamicCSS/lang/ja.js b/xinha/plugins/DynamicCSS/lang/ja.js new file mode 100644 index 0000000..005d204 --- /dev/null +++ b/xinha/plugins/DynamicCSS/lang/ja.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Default": "なし", + "Undefined": "未定義", + "Choose stylesheet": "スタイルシートの選択" +}; \ No newline at end of file diff --git a/xinha/plugins/DynamicCSS/lang/nb.js b/xinha/plugins/DynamicCSS/lang/nb.js new file mode 100644 index 0000000..24e8e8a --- /dev/null +++ b/xinha/plugins/DynamicCSS/lang/nb.js @@ -0,0 +1,8 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Default": "Standard", + "Undefined": "Udefinert", + "Choose stylesheet": "Velg stilsett" +}; \ No newline at end of file diff --git a/xinha/plugins/DynamicCSS/lang/nl.js b/xinha/plugins/DynamicCSS/lang/nl.js new file mode 100644 index 0000000..ead62eb --- /dev/null +++ b/xinha/plugins/DynamicCSS/lang/nl.js @@ -0,0 +1,12 @@ +// I18N constants +// LANG: "nl", ENCODING: UTF-8 +// Sponsored by http://www.systemconcept.de +// Author: Holger Hees, +// (c) systemconcept.de 2004 +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). +{ + "Default": "Default", + "Undefined": "Ungedefinieerd", + "Choose stylesheet": "Kies stylesheet" +}; diff --git a/xinha/plugins/FindReplace/find-replace.js b/xinha/plugins/FindReplace/find-replace.js new file mode 100644 index 0000000..7757e47 --- /dev/null +++ b/xinha/plugins/FindReplace/find-replace.js @@ -0,0 +1,42 @@ +/*---------------------------------------*\ + Find and Replace Plugin for HTMLArea-3.0 + ----------------------------------------- + author: Cau guanabara + e-mail: caugb@ibest.com.br +\*---------------------------------------*/ + +function FindReplace(editor) { +this.editor = editor; +var cfg = editor.config; +var self = this; +cfg.registerButton("FR-findreplace", this._lc("Find and Replace"), + editor.imgURL("ed_find.gif", "FindReplace"), false, + function(editor) { self.buttonPress(editor); }); +cfg.addToolbarElement(["FR-findreplace","separator"], ["formatblock","fontsize","fontname"], -1); +} + +FindReplace.prototype.buttonPress = function(editor) { +FindReplace.editor = editor; +var sel = editor.getSelectedHTML(); + if(/\w/.test(sel)) { + sel = sel.replace(/<[^>]*>/g,""); + sel = sel.replace(/ /g,""); + } +var param = /\w/.test(sel) ? {fr_pattern: sel} : null; +editor._popupDialog("plugin://FindReplace/find_replace", null, param); +}; + +FindReplace._pluginInfo = { + name : "FindReplace", + version : "1.0 - beta", + developer : "Cau Guanabara", + developer_url : "mailto:caugb@ibest.com.br", + c_owner : "Cau Guanabara", + sponsor : "Independent production", + sponsor_url : "http://www.netflash.com.br/gb/HA3-rc1/examples/find-replace.html", + license : "htmlArea" +}; + +FindReplace.prototype._lc = function(string) { + return HTMLArea._lc(string, 'FindReplace'); +}; \ No newline at end of file diff --git a/xinha/plugins/FindReplace/fr_engine.js b/xinha/plugins/FindReplace/fr_engine.js new file mode 100644 index 0000000..d2e5caf --- /dev/null +++ b/xinha/plugins/FindReplace/fr_engine.js @@ -0,0 +1,144 @@ +var FindReplace=window.opener.FindReplace; +var editor=FindReplace.editor; +var is_mo=window.opener.HTMLArea.is_gecko; +var tosearch=""; +var pater=null; +var buffer=null; +var matches=0; +var replaces=0; +var fr_spans=new Array(); +function _lc(_1){ +return (window.opener.HTMLArea._lc(_1,"FindReplace")); +} +function execSearch(_2){ +var _3=editor._doc.body.innerHTML; +if(buffer==null){ +buffer=_3; +} +if(_2["fr_pattern"]!=tosearch){ +if(tosearch!=""){ +clearDoc(); +} +tosearch=_2["fr_pattern"]; +} +if(matches==0){ +er=_2["fr_words"]?"/(?!<[^>]*)(\\b"+_2["fr_pattern"]+"\\b)(?![^<]*>)/g":"/(?!<[^>]*)("+_2["fr_pattern"]+")(?![^<]*>)/g"; +if(!_2["fr_matchcase"]){ +er+="i"; +} +pater=eval(er); +var _4=""; +var _5=""; +var _6=_3.replace(pater,_4+"$1"+_5); +editor.setHTML(_6); +var _7=editor._doc.body.getElementsByTagName("span"); +for(var i=0;i<_7.length;i++){ +if(/^frmark/.test(_7[i].id)){ +fr_spans.push(_7[i]); +} +} +} +spanWalker(_2["fr_pattern"],_2["fr_replacement"],_2["fr_replaceall"]); +} +function spanWalker(_9,_a,_b){ +var _c=false; +clearMarks(); +for(var i=matches;i=fr_spans.length-1); +if(_f||!_c){ +var _10=_lc("Done")+":\n\n"; +if(matches>0){ +if(matches==1){ +_10+=matches+" "+_lc("found item"); +}else{ +_10+=matches+" "+_lc("found items"); +} +if(replaces>0){ +if(replaces==1){ +_10+=",\n"+replaces+" "+_lc("replaced item"); +}else{ +_10+=",\n"+replaces+" "+_lc("replaced items"); +} +} +hiliteAll(); +disab("fr_hiliteall",false); +}else{ +_10+="\""+_9+"\" "+_lc("not found"); +} +alert(_10+"."); +} +} +function clearDoc(){ +var doc=editor._doc.body.innerHTML; +var er=/(]*id=.?frmark[^>]*>)([^<>]*)(<\/span>)/gi; +editor._doc.body.innerHTML=doc.replace(er,"$2"); +pater=null; +tosearch=""; +fr_spans=new Array(); +matches=0; +replaces=0; +disab("fr_hiliteall,fr_clear",true); +} +function clearMarks(){ +var _13=editor._doc.body.getElementsByTagName("span"); +for(var i=0;i<_13.length;i++){ +var elm=_13[i]; +if(/^frmark/.test(elm.id)){ +var _16=editor._doc.getElementById(elm.id).style; +_16.backgroundColor=""; +_16.color=""; +_16.fontWeight=""; +} +} +} +function hiliteAll(){ +var _17=editor._doc.body.getElementsByTagName("span"); +for(var i=0;i<_17.length;i++){ +var elm=_17[i]; +if(/^frmark/.test(elm.id)){ +var _1a=editor._doc.getElementById(elm.id).style; +_1a.backgroundColor="highlight"; +_1a.color="white"; +_1a.fontWeight="bold"; +} +} +} +function resetContents(){ +if(buffer==null){ +return; +} +var _1b=editor._doc.body.innerHTML; +editor._doc.body.innerHTML=buffer; +buffer=_1b; +} +function disab(_1c,_1d){ +var _1e=_1c.split(/[,; ]+/); +for(var i=0;i<_1e.length;i++){ +document.getElementById(_1e[i]).disabled=_1d; +} +} + diff --git a/xinha/plugins/FindReplace/img/ed_find.gif b/xinha/plugins/FindReplace/img/ed_find.gif new file mode 100644 index 0000000..11877d4 Binary files /dev/null and b/xinha/plugins/FindReplace/img/ed_find.gif differ diff --git a/xinha/plugins/FindReplace/lang/de.js b/xinha/plugins/FindReplace/lang/de.js new file mode 100644 index 0000000..2c775b9 --- /dev/null +++ b/xinha/plugins/FindReplace/lang/de.js @@ -0,0 +1,27 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Udo Schmal (gocher), http://www.schaffrath-neuemedien.de/, udo.schmal@t-online.de +{ + // messages + "Substitute this occurrence?": "Treffer ersetzen?", + "Enter the text you want to find": "Geben Sie einen Text ein den Sie finden möchten", + "Inform a replacement word": "Geben sie einen Text zum ersetzen ein", + "found items": "alle Treffer", + "replaced items": "ersetzte Treffer", + "found item": "Treffer", + "replaced item": "ersetzter Treffer", + "not found": "kein Teffer", + // window + "Find and Replace": "Suchen und ersetzen", + "Search for:": "Suchen nach:", + "Replace with:": "Ersetzen durch:", + "Options": "Optionen", + "Whole words only": "Ganze Wörter", + "Case sensitive search": "Groß-/Kleinschreibung", + "Substitute all occurrences": "alle Treffer ersetzen", + "Clear": "Nächstes ersetzen", + "Highlight": "Hervorheben", + "Undo": "Rückgängig", + "Next": "Nächster", + "Done": "Fertig" +}; \ No newline at end of file diff --git a/xinha/plugins/FindReplace/lang/fr.js b/xinha/plugins/FindReplace/lang/fr.js new file mode 100644 index 0000000..4869e76 --- /dev/null +++ b/xinha/plugins/FindReplace/lang/fr.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + // messages + "Substitute this occurrence?": "Remplacer cette occurrence ?", + "Enter the text you want to find": "Texte à trouver", + "Inform a replacement word": "Indiquez un mot de remplacement", + "found items": "éléments trouvés", + "replaced items": "éléments remplacés", + "found item": "élément trouvé", + "replaced item": "élément remplacé", + "not found": "non trouvé", + // window + "Find and Replace": "Chercher et Remplacer", + "Search for:": "Chercher", + "Replace with:": "Remplacer par", + "Options": "Options", + "Whole words only": "Mots entiers seulement", + "Case sensitive search": "Recherche sensible à la casse", + "Substitute all occurrences": "Remplacer toutes les occurences", + "Clear": "Effacer", + "Highlight": "Surligner", + "Undo": "Annuler", + "Next": "Suivant", + "Done": "Fin" +}; \ No newline at end of file diff --git a/xinha/plugins/FindReplace/lang/ja.js b/xinha/plugins/FindReplace/lang/ja.js new file mode 100644 index 0000000..3fc68e5 --- /dev/null +++ b/xinha/plugins/FindReplace/lang/ja.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + // messages + "Substitute this occurrence?": "置換しますか?", + "Enter the text you want to find": "検索したいテキストを入力します", + "Inform a replacement word": "単語の置換を知らせる", + "found items": "件が検索されました", + "replaced items": "件が置換されました", + "found item": "件が検索されました", + "replaced item": "件が置換されました", + "not found": "はありません", + // window + "Find and Replace": "検索/置換", + "Search for:": "検索:", + "Replace with:": "置換:", + "Options": "設定", + "Whole words only": "完全一致のみ", + "Case sensitive search": "大文字/小文字区別", + "Substitute all occurrences": "すべて置換", + "Clear": "通常表示", + "Highlight": "強調表示", + "Undo": "元に戻す", + "Next": "次を検索", + "Done": "終了" +}; \ No newline at end of file diff --git a/xinha/plugins/FindReplace/lang/nb.js b/xinha/plugins/FindReplace/lang/nb.js new file mode 100644 index 0000000..fed5bf4 --- /dev/null +++ b/xinha/plugins/FindReplace/lang/nb.js @@ -0,0 +1,27 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + // messages + "Substitute this occurrence?": "Vennligst bekreft at du vil erstatte?", + "Enter the text you want to find": "Skriv inn teksten du ønsker å finne", + "Inform a replacement word": "Vennligst skriv inn et erstatningsord / setning", + "found items": "forekomster funnet i søket", + "replaced items": "forekomster erstattet", + "found item": "Treff", + "replaced item": "erstattet treff", + "not found": "ikke funnet", + // window + "Find and Replace": "Søk og erstatt", + "Search for:": "Søk etter:", + "Replace with:": "Erstatt med:", + "Options": "Valg", + "Whole words only": "Bare hele ord", + "Case sensitive search": "Skille mellom store og små bokstaver", + "Substitute all occurrences": "Erstatt alle treff", + "Clear": "Tøm", + "Highlight": "Uthev", + "Undo": "Tilbake", + "Next": "Neste", + "Done": "Ferdig" +}; \ No newline at end of file diff --git a/xinha/plugins/FindReplace/lang/pl.js b/xinha/plugins/FindReplace/lang/pl.js new file mode 100644 index 0000000..bc446c7 --- /dev/null +++ b/xinha/plugins/FindReplace/lang/pl.js @@ -0,0 +1,27 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz, koto1sa@o2.pl, http://www.eskot.krakow.pl/portfolio +{ + // messages + "Substitute this occurrence?": "Zamienić to wystąpienie?", + "Enter the text you want to find": "Podaj tekst, jaki chcesz wyszukać", + "Inform a replacement word": "Podaj tekst do zamiany", + "found items": "znalezionych", + "replaced items": "zamienionych", + "found item": "znaleziony", + "replaced item": "zamieniony", + "not found": "nie znaleziony", + // window + "Find and Replace": "Znajdź i zamień", + "Search for:": "Szukaj:", + "Replace with:": "Zamień na:", + "Options": "Opcje", + "Whole words only": "Całe słowa", + "Case sensitive search": "Wg wielkości liter", + "Substitute all occurrences": "Zamień wszystkie wystąpienia", + "Clear": "Wyczyść", + "Highlight": "Podświetl", + "Undo": "Cofnij", + "Next": "Następny", + "Done": "Gotowe" +}; \ No newline at end of file diff --git a/xinha/plugins/FindReplace/lang/pt_br.js b/xinha/plugins/FindReplace/lang/pt_br.js new file mode 100644 index 0000000..017332f --- /dev/null +++ b/xinha/plugins/FindReplace/lang/pt_br.js @@ -0,0 +1,27 @@ +// I18N constants +// LANG: "pt-br" +// Author: Cau guanabara (independent developer), caugb@ibest.com.br +{ + // mensagens + "Substitute this occurrence?": "Substituir?", + "Enter the text you want to find": "Digite um termo para a busca", + "Inform a replacement word": "Informe um termo para a substituição", + "found items": "itens localizados", + "replaced items": "itens substituídos", + "found item": "item localizado", + "replaced item": "item substituído", + "not found": "não encontrado", + // janela + "Find and Replace": "Localizar e Substituir", + "Search for:": "Localizar:", + "Replace with:": "Substituir por:", + "Options": "Opções", + "Whole words only": "Apenas palavras inteiras", + "Case sensitive search": "Diferenciar caixa alta/baixa", + "Substitute all occurrences": "Substituir todas", + "Highlight": "Remarcar", + "Clear": "Limpar", + "Undo": "Desfazer", + "Next": "Próxima", + "Done": "Concluído" +}; diff --git a/xinha/plugins/FindReplace/lang/ru.js b/xinha/plugins/FindReplace/lang/ru.js new file mode 100644 index 0000000..c5b8c25 --- /dev/null +++ b/xinha/plugins/FindReplace/lang/ru.js @@ -0,0 +1,28 @@ +// I18N constants +// LANG: "ru", ENCODING: UTF-8 +// Author: Andrei Blagorazumov, a@fnr.ru + +{ + // messages + "Substitute this occurrence?": "Заменить это вхождение?", + "Enter the text you want to find": "Введите текст, который вы хотите найти", + "Inform a replacement word": "Показать замещающее слово", + "found items": "найти", + "replaced items": "замененные", + "found item": "найти", + "replaced item": "замененная", + "not found": "не найдено", + // window + "Find and Replace": "Найти и заменить", + "Search for:": "Найти", + "Replace with:": "Заменить с", + "Options": "Опции", + "Whole words only": "Только слова целиком", + "Case sensitive search": "Поиск с учетом регистра", + "Substitute all occurrences": "Заменить все вхождения", + "Clear": "Очистить", + "Highlight": "Выделить", + "Undo": "Отменить", + "Next": "След.", + "Done": "OK" +}; \ No newline at end of file diff --git a/xinha/plugins/FindReplace/lang/sv.js b/xinha/plugins/FindReplace/lang/sv.js new file mode 100644 index 0000000..60c8432 --- /dev/null +++ b/xinha/plugins/FindReplace/lang/sv.js @@ -0,0 +1,27 @@ +// I18N constants +// LANG: "sv" (Swedish), ENCODING: UTF-8 +// translated: Erik Dalén, +{ + // messages + "Substitute this occurrence?": "Ersätt denna?", + "Enter the text you want to find": "Skriv in text du vill söka", + "Inform a replacement word": "Skriv in ett ersättningsord", + "found items": "förekomster funna i sökningen", + "replaced items": "förekomster erstatta", + "found item": "Träff", + "replaced item": "erstatt träff", + "not found": "inte funnet", + // window + "Find and Replace": "Sök och ersätt", + "Search for:": "Sök efter:", + "Replace with:": "Ersätt med:", + "Options": "Välj", + "Whole words only": "Bara hela ord", + "Case sensitive search": "Skilj mellan stora och små bokstäver", + "Substitute all occurrences": "Erstatt alla träffar", + "Clear": "Töm", + "Highlight": "Markera", + "Undo": "Tillbaka", + "Next": "Nästa", + "Done": "Färdig" +}; diff --git a/xinha/plugins/FindReplace/popups/find_replace.html b/xinha/plugins/FindReplace/popups/find_replace.html new file mode 100644 index 0000000..0759c25 --- /dev/null +++ b/xinha/plugins/FindReplace/popups/find_replace.html @@ -0,0 +1,162 @@ + + + Find and Replace + + + + + + + + + + +
    Find and Replace
    +
    + + + + + + + + + + + + + + +
    Search for: + +
    Replace with: + +
    + + + + +
    +
    + Options + + + Whole words only
    + + + Case sensitive search
    + + + Substitute all occurrences +
    + +
    + +
    + +
    +
    + +
    +
    + + \ No newline at end of file diff --git a/xinha/plugins/Forms/forms.css b/xinha/plugins/Forms/forms.css new file mode 100644 index 0000000..ba0fca6 --- /dev/null +++ b/xinha/plugins/Forms/forms.css @@ -0,0 +1,3 @@ +form { + border: 1px dotted red; +} diff --git a/xinha/plugins/Forms/forms.js b/xinha/plugins/Forms/forms.js new file mode 100644 index 0000000..436b0e1 --- /dev/null +++ b/xinha/plugins/Forms/forms.js @@ -0,0 +1,354 @@ +function Forms(_1){ +this.editor=_1; +var _2=_1.config; +var bl=Forms.btnList; +var _4=this; +var _5=["linebreak"]; +for(var i=0;i"); +} +} +},_15); +}else{ +var _1c=""; +if(typeof _12=="undefined"){ +_12=_10.getParentElement(); +var tag=_12.tagName.toLowerCase(); +if(_12&&(tag=="legend")){ +_12=_12.parentElement; +tag=_12.tagName.toLowerCase(); +} +if(_12&&!(tag=="textarea"||tag=="select"||tag=="input"||tag=="label"||tag=="fieldset")){ +_12=null; +} +} +if(_12){ +_16=_12.tagName.toLowerCase(); +_15.f_name=_12.name; +_1c=_12.tagName; +if(_16=="input"){ +_15.f_type=_12.type; +_16=_12.type; +} +switch(_16){ +case "textarea": +_15.f_cols=_12.cols; +_15.f_rows=_12.rows; +_15.f_text=_12.innerHTML; +_15.f_wrap=_12.getAttribute("wrap"); +_15.f_readOnly=_12.getAttribute("readOnly"); +_15.f_disabled=_12.getAttribute("disabled"); +_15.f_tabindex=_12.getAttribute("tabindex"); +_15.f_accesskey=_12.getAttribute("accesskey"); +break; +case "select": +_15.f_size=parseInt(_12.size); +_15.f_multiple=_12.getAttribute("multiple"); +_15.f_disabled=_12.getAttribute("disabled"); +_15.f_tabindex=_12.getAttribute("tabindex"); +var _1e=new Array(); +for(var i=0;i<=_12.options.length-1;i++){ +_1e[i]=new optionValues(_12.options[i].text,_12.options[i].value); +} +_15.f_options=_1e; +break; +case "text": +case "password": +_15.f_value=_12.value; +_15.f_size=_12.size; +_15.f_maxLength=_12.maxLength; +_15.f_readOnly=_12.getAttribute("readOnly"); +_15.f_disabled=_12.getAttribute("disabled"); +_15.f_tabindex=_12.getAttribute("tabindex"); +_15.f_accesskey=_12.getAttribute("accesskey"); +break; +case "hidden": +_15.f_value=_12.value; +break; +case "submit": +case "reset": +_15.f_value=_12.value; +_15.f_disabled=_12.getAttribute("disabled"); +_15.f_tabindex=_12.getAttribute("tabindex"); +_15.f_accesskey=_12.getAttribute("accesskey"); +break; +case "checkbox": +case "radio": +_15.f_value=_12.value; +_15.f_checked=_12.checked; +_15.f_disabled=_12.getAttribute("disabled"); +_15.f_tabindex=_12.getAttribute("tabindex"); +_15.f_accesskey=_12.getAttribute("accesskey"); +break; +case "button": +_15.f_value=_12.value; +_15.f_onclick=_12.getAttribute("onclick"); +_15.f_disabled=_12.getAttribute("disabled"); +_15.f_tabindex=_12.getAttribute("tabindex"); +_15.f_accesskey=_12.getAttribute("accesskey"); +break; +case "image": +_15.f_value=_12.value; +_15.f_src=_12.src; +_15.f_disabled=_12.getAttribute("disabled"); +_15.f_tabindex=_12.getAttribute("tabindex"); +_15.f_accesskey=_12.getAttribute("accesskey"); +break; +case "file": +_15.f_disabled=_12.getAttribute("disabled"); +_15.f_tabindex=_12.getAttribute("tabindex"); +_15.f_accesskey=_12.getAttribute("accesskey"); +break; +case "label": +_15.f_text=_12.innerHTML; +_15.f_for=_12.getAttribute("for"); +_15.f_accesskey=_12.getAttribute("accesskey"); +break; +case "fieldset": +if(_12.firstChild.tagName.toLowerCase()=="legend"){ +_15.f_text=_12.firstChild.innerHTML; +}else{ +_15.f_text=""; +} +break; +} +}else{ +_15.f_name=""; +switch(_11){ +case "textarea": +case "select": +case "label": +case "fieldset": +_1c=_11; +break; +default: +_1c="input"; +_15.f_type=_11; +break; +} +_15.f_options=""; +_15.f_cols="20"; +_15.f_rows="4"; +_15.f_multiple="false"; +_15.f_value=""; +_15.f_size=""; +_15.f_maxLength=""; +_15.f_checked=""; +_15.f_src=""; +_15.f_onclick=""; +_15.f_wrap=""; +_15.f_readOnly="false"; +_15.f_disabled="false"; +_15.f_tabindex=""; +_15.f_accesskey=""; +_15.f_for=""; +_15.f_text=""; +_15.f_legend=""; +} +_10._popupDialog("plugin://Forms/"+_1c+".html",function(_20){ +if(_20){ +if(_20["f_cols"]){ +if(isNaN(parseInt(_20["f_cols"],10))||parseInt(_20["f_cols"],10)<=0){ +_20["f_cols"]=""; +} +} +if(_20["f_rows"]){ +if(isNaN(parseInt(_20["f_rows"],10))||parseInt(_20["f_rows"],10)<=0){ +_20["f_rows"]=""; +} +} +if(_20["f_size"]){ +if(isNaN(parseInt(_20["f_size"],10))||parseInt(_20["f_size"],10)<=0){ +_20["f_size"]=""; +} +} +if(_20["f_maxlength"]){ +if(isNaN(parseInt(_20["f_maxLength"],10))||parseInt(_20["f_maxLength"],10)<=0){ +_20["f_maxLength"]=""; +} +} +if(_12){ +for(field in _20){ +if((field=="f_text")||(field=="f_options")||(field=="f_onclick")||(field=="f_checked")){ +continue; +} +if(_20[field]!=""){ +_12.setAttribute(field.substring(2,20),_20[field]); +}else{ +_12.removeAttribute(field.substring(2,20)); +} +} +if(_16=="textarea"){ +_12.innerHTML=_20["f_text"]; +}else{ +if(_16=="select"){ +_12.options.length=0; +var _21=_20["f_options"]; +for(i=0;i<=_21.length-1;i++){ +_12.options[i]=new Option(_21[i].text,_21[i].value); +} +}else{ +if(_16=="label"){ +_12.innerHTML=_20["f_text"]; +}else{ +if(_16=="fieldset"){ +if(_15.f_text!=""){ +if(_12.firstChild.tagName.toLowerCase()=="legend"){ +_12.firstChild.innerHTML=_20["f_text"]; +} +}else{ +} +}else{ +if((_16=="checkbox")||(_16=="radio")){ +if(_20["f_checked"]!=""){ +_12.checked=true; +}else{ +_12.checked=false; +} +}else{ +if(_20["f_onclick"]){ +_12.onclick=""; +if(_20["f_onclick"]!=""){ +_12.onclick=_20["f_onclick"]; +} +} +} +} +} +} +} +}else{ +var _22=""; +for(field in _20){ +if(!_20[field]){ +continue; +} +if((_20[field]=="")||(field=="f_text")||(field=="f_options")){ +continue; +} +_22+=" "+field.substring(2,20)+"=\""+_20[field]+"\""; +} +if(_16=="textarea"){ +_22=""+_20["f_text"]+""; +}else{ +if(_16=="select"){ +_22=""; +var _21=_20["f_options"]; +for(i=0;i<=_21.length-1;i++){ +_22+=""; +} +_22+=""; +}else{ +if(_16=="label"){ +_22=""+_20["f_text"]+""; +}else{ +if(_16=="fieldset"){ +_22=""; +if(_20["f_legend"]!=""){ +_22+=""+_20["f_text"]+""; +} +_22+=""; +}else{ +_22=""; +} +} +} +} +_10.insertHTML(_22); +} +} +},_15); +} +}; + diff --git a/xinha/plugins/Forms/img/ed_button.gif b/xinha/plugins/Forms/img/ed_button.gif new file mode 100644 index 0000000..cfa4e7d Binary files /dev/null and b/xinha/plugins/Forms/img/ed_button.gif differ diff --git a/xinha/plugins/Forms/img/ed_checkbox.gif b/xinha/plugins/Forms/img/ed_checkbox.gif new file mode 100644 index 0000000..ea7affa Binary files /dev/null and b/xinha/plugins/Forms/img/ed_checkbox.gif differ diff --git a/xinha/plugins/Forms/img/ed_fieldset.gif b/xinha/plugins/Forms/img/ed_fieldset.gif new file mode 100644 index 0000000..af358e5 Binary files /dev/null and b/xinha/plugins/Forms/img/ed_fieldset.gif differ diff --git a/xinha/plugins/Forms/img/ed_file.gif b/xinha/plugins/Forms/img/ed_file.gif new file mode 100644 index 0000000..7f61ce1 Binary files /dev/null and b/xinha/plugins/Forms/img/ed_file.gif differ diff --git a/xinha/plugins/Forms/img/ed_form.gif b/xinha/plugins/Forms/img/ed_form.gif new file mode 100644 index 0000000..a2c293e Binary files /dev/null and b/xinha/plugins/Forms/img/ed_form.gif differ diff --git a/xinha/plugins/Forms/img/ed_hidden.gif b/xinha/plugins/Forms/img/ed_hidden.gif new file mode 100644 index 0000000..26b325d Binary files /dev/null and b/xinha/plugins/Forms/img/ed_hidden.gif differ diff --git a/xinha/plugins/Forms/img/ed_image.gif b/xinha/plugins/Forms/img/ed_image.gif new file mode 100644 index 0000000..3c8c88e Binary files /dev/null and b/xinha/plugins/Forms/img/ed_image.gif differ diff --git a/xinha/plugins/Forms/img/ed_label.gif b/xinha/plugins/Forms/img/ed_label.gif new file mode 100644 index 0000000..f93fce7 Binary files /dev/null and b/xinha/plugins/Forms/img/ed_label.gif differ diff --git a/xinha/plugins/Forms/img/ed_password.gif b/xinha/plugins/Forms/img/ed_password.gif new file mode 100644 index 0000000..a799218 Binary files /dev/null and b/xinha/plugins/Forms/img/ed_password.gif differ diff --git a/xinha/plugins/Forms/img/ed_radio.gif b/xinha/plugins/Forms/img/ed_radio.gif new file mode 100644 index 0000000..5b72ef6 Binary files /dev/null and b/xinha/plugins/Forms/img/ed_radio.gif differ diff --git a/xinha/plugins/Forms/img/ed_reset.gif b/xinha/plugins/Forms/img/ed_reset.gif new file mode 100644 index 0000000..68fee8e Binary files /dev/null and b/xinha/plugins/Forms/img/ed_reset.gif differ diff --git a/xinha/plugins/Forms/img/ed_select.gif b/xinha/plugins/Forms/img/ed_select.gif new file mode 100644 index 0000000..3ea59f5 Binary files /dev/null and b/xinha/plugins/Forms/img/ed_select.gif differ diff --git a/xinha/plugins/Forms/img/ed_submit.gif b/xinha/plugins/Forms/img/ed_submit.gif new file mode 100644 index 0000000..0b12a19 Binary files /dev/null and b/xinha/plugins/Forms/img/ed_submit.gif differ diff --git a/xinha/plugins/Forms/img/ed_text.gif b/xinha/plugins/Forms/img/ed_text.gif new file mode 100644 index 0000000..fb8159c Binary files /dev/null and b/xinha/plugins/Forms/img/ed_text.gif differ diff --git a/xinha/plugins/Forms/img/ed_textarea.gif b/xinha/plugins/Forms/img/ed_textarea.gif new file mode 100644 index 0000000..c2c874a Binary files /dev/null and b/xinha/plugins/Forms/img/ed_textarea.gif differ diff --git a/xinha/plugins/Forms/lang/ja.js b/xinha/plugins/Forms/lang/ja.js new file mode 100644 index 0000000..05409f3 --- /dev/null +++ b/xinha/plugins/Forms/lang/ja.js @@ -0,0 +1,86 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Form": "フォーム", + "Textarea": "テキストエリア", + "Selection Field": "選択肢フィールド", + "Checkbox": "チェックボックス", + "Radio Button": "ラジオボタン", + "Text Field": "テキストフィールド", + "Password Field": "パスワードフィールド", + "File Field": "ファイルフィールド", + "Submit Button": "送信ボタン", + "Reset Button": "リセットボタン", + "Image Button": "画像ボタン", + "Button": "ボタン", + "Hidden Field": "非表示フィールド", + "Label": "ラベル", + "Field Set": "フィールドセット", + "Form Element: INPUT": "フォーム要素: INPUT", + "Form Element: SELECT": "フォーム要素: SELECT", + "Form Element: TEXTAREA": "フォーム要素: TEXTAREA", + "Form Element: LABEL": "フォーム要素: LABEL", + "Form Element: FIELDSET": "フォーム要素: FIELDSET", + "Form Name:": "フォーム名:", + "Form handler script": "フォーム処理スクリプト", + "Action URL:": "アクションURL:", + "Method:": "メソッド:", + "Post": "POST", + "Get": "GET", + "Encoding:": "エンコード:", + "HTML-Form to CGI (default)": "HTMLフォームからCGIへ(デフォルト)", + "multipart Form Data (File-Upload)": "マルチパート(ファイルアップロード用)", + "Target Frame:": "ターゲット:", + "Name/ID:": "名前/ID:", + "Value:": "値:", + "Disabled": "無効", + "Checked": "チェック済み", + "Tab Index:": "タブ順序:", + "Access Key:": "アクセスキー:", + "Read Only": "読み取り専用", + "Dimensions": "大きさ", + "Size:": "サイズ:", + "Max length:": "最大長:", + "Button Script": "ボタンスクリプト", + "'onClick'=": "'onClick'=", + "Image source": "画像ソース", + "Image URL:": "画像URL:", + "Multiple Select": "複数選択", + "Options": "選択肢", + "Lable:": "ラベル:", + "Move Up": "上へ", + "Move Down": "下へ", + "Delete": "削除", + "Add": "追加", + "Columns:": "列数:", + "Rows:": "行数:", + "Wrap Mode:": "折り返し:", + "Off": "オフ", + "Soft": "ソフト", + "Hard": "ハード", + "Physical": "物理的", + "Virtual": "仮想", + "normal": "標準", + "nowrap": "折り返しなし", + "pre": "フォーマット済み", + "Initial Text:": "初期テキスト:", + "Text:": "テキスト:", + "For Control:": "制御対象:", + "Legend:": "グループ名:", + "Cancel": "中止", + "Name": "名前", + "Name of the form input": "フォーム入力の名前", + "Value of the form input": "フォーム入力の値", + "Size of text box in characters": "文字数によるテキストボックスの大きさ", + "Maximum number of characters accepted": "入力可能な最大文字数", + "Javascript for button click": "ボタンクリック時のJavaScritp", + "URL of image": "画像のURL", + "Name of the form select": "", + "name of the textarea": "テキストエリアの名前", + "Width in number of characters": "文字数による幅", + "Height in number of rows": "行数による高さ", + "Default text (optional)": "テキスト初期値(オプション)", + "You must enter the form name": "フォーム名が必要です", + "You must enter a Name": "名前が必要です", + "Please enter a Label": "ラベルを入力してください" +}; diff --git a/xinha/plugins/Forms/popups/fieldset.html b/xinha/plugins/Forms/popups/fieldset.html new file mode 100644 index 0000000..fd155f4 --- /dev/null +++ b/xinha/plugins/Forms/popups/fieldset.html @@ -0,0 +1,46 @@ + + + + Insert/Edit Form Element FIELDSET + + + + + + + +
    Form Element: FIELDSET
    +
    +
    Legend:
    + +

    +

    + + +
    +
    + + \ No newline at end of file diff --git a/xinha/plugins/Forms/popups/form.html b/xinha/plugins/Forms/popups/form.html new file mode 100644 index 0000000..894f811 --- /dev/null +++ b/xinha/plugins/Forms/popups/form.html @@ -0,0 +1,90 @@ + + + + Insert/Edit Form + + + + + + + +
    Form
    +
    +
    Form Name:
    + +

    + +

    + Form handler script +
    +
    Action URL:
    + +

    +

    Method:
    + +
    +
    Encoding:
    + +

    +

    Target Frame:
    + +

    +

    + +
    + + +
    +
    + + + \ No newline at end of file diff --git a/xinha/plugins/Forms/popups/input.html b/xinha/plugins/Forms/popups/input.html new file mode 100644 index 0000000..2fd7048 --- /dev/null +++ b/xinha/plugins/Forms/popups/input.html @@ -0,0 +1,179 @@ + + + + Insert/Edit Form Element INPUT + + + + + + + + +
    +
    +
    Name/ID:
    + +

    +

    Value:
    + +

    +

    Disabled
    + +

    + +

    +
    Checked
    + +

    +

    + +
    Tab Index:
    + +

    +

    Access Key:
    + +

    + +

    +
    Read Only
    + +

    + +

    + Dimensions +
    +
    Size:
    + +
    +
    Max length:
    + +
    +
    +
    +
    +
    + Button Script +
    +
    'onClick'=
    + +
    +
    +
    +
    +
    + Image source +
    +
    Image URL:
    + +
    +
    +
    +
    + + +
    +
    + + + \ No newline at end of file diff --git a/xinha/plugins/Forms/popups/label.html b/xinha/plugins/Forms/popups/label.html new file mode 100644 index 0000000..f54df02 --- /dev/null +++ b/xinha/plugins/Forms/popups/label.html @@ -0,0 +1,59 @@ + + + + Insert/Edit Form Element LABEL + + + + + + + +
    Form Element: LABEL
    +
    +
    Text:
    + +

    +

    For Control:
    + +

    +

    Access Key:
    + +

    +

    + + +
    +
    + + \ No newline at end of file diff --git a/xinha/plugins/Forms/popups/select.html b/xinha/plugins/Forms/popups/select.html new file mode 100644 index 0000000..fcfee43 --- /dev/null +++ b/xinha/plugins/Forms/popups/select.html @@ -0,0 +1,209 @@ + + + + Insert/Edit Form Element SELECT + + + + + + + +
    Form Element: SELECT
    +
    +
    Name/ID:
    + +

    +

    Size:
    + +

    +

    Multiple Select
    + +

    +

    Disabled
    + +

    +

    Tab Index:
    + +

    +

    +
    + Options + + + + + +
    + + +
    +
    + +
    +
    + + + + + + + + +
    Lable:Value:
    +
    +
    + + +
    +
    + + \ No newline at end of file diff --git a/xinha/plugins/Forms/popups/textarea.html b/xinha/plugins/Forms/popups/textarea.html new file mode 100644 index 0000000..802826b --- /dev/null +++ b/xinha/plugins/Forms/popups/textarea.html @@ -0,0 +1,113 @@ + + + + Insert/Edit Form Element TEXTAREA + + + + + + + +
    Form Element: TEXTAREA
    +
    +
    Name/ID:
    + +

    +

    + Dimensions +
    Columns:
    + +

    +

    Rows:
    + +

    +

    +
    +
    Wrap Mode:
    + +

    +

    Read Only
    + +

    +

    Disabled
    + +

    +

    Tab Index:
    + +

    +

    Access Key:
    + +

    + +

    Initial Text:
    + +
    + + +
    +
    + + + \ No newline at end of file diff --git a/xinha/plugins/FullPage/full-page.js b/xinha/plugins/FullPage/full-page.js new file mode 100644 index 0000000..6e344f8 --- /dev/null +++ b/xinha/plugins/FullPage/full-page.js @@ -0,0 +1,200 @@ +function FullPage(_1){ +this.editor=_1; +var _2=_1.config; +_2.fullPage=true; +var _3=this; +_2.registerButton("FP-docprop",this._lc("Document properties"),_1.imgURL("docprop.gif","FullPage"),false,function(_4,id){ +_3.buttonPress(_4,id); +}); +_2.addToolbarElement(["separator","FP-docprop"],"separator",-1); +} +FullPage._pluginInfo={name:"FullPage",version:"1.0",developer:"Mihai Bazon",developer_url:"http://dynarch.com/mishoo/",c_owner:"Mihai Bazon",sponsor:"Thycotic Software Ltd.",sponsor_url:"http://thycotic.com",license:"htmlArea"}; +FullPage.prototype._lc=function(_6){ +return HTMLArea._lc(_6,"FullPage"); +}; +FullPage.prototype.buttonPress=function(_7,id){ +var _9=this; +switch(id){ +case "FP-docprop": +var _a=_7._doc; +var _b=_a.getElementsByTagName("link"); +var _c=""; +var _d=""; +var _e=""; +var _f=""; +var _10=""; +for(var i=_b.length;--i>=0;){ +var _12=_b[i]; +if(/stylesheet/i.test(_12.rel)){ +if(/alternate/i.test(_12.rel)){ +_d=_12.href; +}else{ +_c=_12.href; +} +} +} +var _13=_a.getElementsByTagName("meta"); +for(var i=_13.length;--i>=0;){ +var _14=_13[i]; +if(/content-type/i.test(_14.httpEquiv)){ +r=/^text\/html; *charset=(.*)$/i.exec(_14.content); +_10=r[1]; +}else{ +if((/keywords/i.test(_14.name))||(/keywords/i.test(_14.id))){ +_e=_14.content; +}else{ +if((/description/i.test(_14.name))||(/description/i.test(_14.id))){ +_f=_14.content; +} +} +} +} +var _15=_a.getElementsByTagName("title")[0]; +_15=_15?_15.innerHTML:""; +var _16={f_doctype:_7.doctype,f_title:_15,f_body_bgcolor:HTMLArea._colorToRgb(_a.body.style.backgroundColor),f_body_fgcolor:HTMLArea._colorToRgb(_a.body.style.color),f_base_style:_c,f_alt_style:_d,f_charset:_10,f_keywords:_e,f_description:_f,editor:_7}; +_7._popupDialog("plugin://FullPage/docprop",function(_17){ +_9.setDocProp(_17); +},_16); +break; +} +}; +FullPage.prototype.setDocProp=function(_18){ +var txt=""; +var doc=this.editor._doc; +var _1b=doc.getElementsByTagName("head")[0]; +var _1c=doc.getElementsByTagName("link"); +var _1d=doc.getElementsByTagName("meta"); +var _1e=null; +var _1f=null; +var _20=null; +var _21=null; +var _22=null; +var _23=null; +for(var i=_1c.length;--i>=0;){ +var _25=_1c[i]; +if(/stylesheet/i.test(_25.rel)){ +if(/alternate/i.test(_25.rel)){ +_1f=_25; +}else{ +_1e=_25; +} +} +} +for(var i=_1d.length;--i>=0;){ +var _26=_1d[i]; +if(/content-type/i.test(_26.httpEquiv)){ +r=/^text\/html; *charset=(.*)$/i.exec(_26.content); +_20=r[1]; +_21=_26; +}else{ +if((/keywords/i.test(_26.name))||(/keywords/i.test(_26.id))){ +_22=_26; +}else{ +if((/description/i.test(_26.name))||(/description/i.test(_26.id))){ +_23=_26; +} +} +} +} +function createLink(alt){ +var _28=doc.createElement("link"); +_28.rel=alt?"alternate stylesheet":"stylesheet"; +_1b.appendChild(_28); +return _28; +} +function createMeta(_29,_2a,_2b){ +var _2c=doc.createElement("meta"); +if(_29!=""){ +_2c.httpEquiv=_29; +} +if(_2a!=""){ +_2c.name=_2a; +} +if(_2a!=""){ +_2c.id=_2a; +} +_2c.content=_2b; +_1b.appendChild(_2c); +return _2c; +} +if(!_1e&&_18.f_base_style){ +_1e=createLink(false); +} +if(_18.f_base_style){ +_1e.href=_18.f_base_style; +}else{ +if(_1e){ +_1b.removeChild(_1e); +} +} +if(!_1f&&_18.f_alt_style){ +_1f=createLink(true); +} +if(_18.f_alt_style){ +_1f.href=_18.f_alt_style; +}else{ +if(_1f){ +_1b.removeChild(_1f); +} +} +if(_21){ +_1b.removeChild(_21); +_21=null; +} +if(!_21&&_18.f_charset){ +_21=createMeta("Content-Type","","text/html; charset="+_18.f_charset); +} +if(!_22&&_18.f_keywords){ +_22=createMeta("","keywords",_18.f_keywords); +}else{ +if(_18.f_keywords){ +_22.content=_18.f_keywords; +}else{ +if(_22){ +_1b.removeChild(_22); +} +} +} +if(!_23&&_18.f_description){ +_23=createMeta("","description",_18.f_description); +}else{ +if(_18.f_description){ +_23.content=_18.f_description; +}else{ +if(_23){ +_1b.removeChild(_23); +} +} +} +for(var i in _18){ +var val=_18[i]; +switch(i){ +case "f_title": +var _2e=doc.getElementsByTagName("title")[0]; +if(!_2e){ +_2e=doc.createElement("title"); +_1b.appendChild(_2e); +}else{ +while(node=_2e.lastChild){ +_2e.removeChild(node); +} +} +if(!HTMLArea.is_ie){ +_2e.appendChild(doc.createTextNode(val)); +}else{ +doc.title=val; +} +break; +case "f_doctype": +this.editor.setDoctype(val); +break; +case "f_body_bgcolor": +doc.body.style.backgroundColor=val; +break; +case "f_body_fgcolor": +doc.body.style.color=val; +break; +} +} +}; + diff --git a/xinha/plugins/FullPage/img/docprop.gif b/xinha/plugins/FullPage/img/docprop.gif new file mode 100644 index 0000000..fd00889 Binary files /dev/null and b/xinha/plugins/FullPage/img/docprop.gif differ diff --git a/xinha/plugins/FullPage/lang/de.js b/xinha/plugins/FullPage/lang/de.js new file mode 100644 index 0000000..12ef461 --- /dev/null +++ b/xinha/plugins/FullPage/lang/de.js @@ -0,0 +1,18 @@ +// I18N for the FullPage plugin +// LANG: "de", ENCODING: UTF-8 +// Author: Holger Hees, http://www.systemconcept.de +{ + "Alternate style-sheet:": "Alternativer Stylesheet:", + "Background color:": "Hintergrundfarbe:", + "Cancel": "Abbrechen", + "DOCTYPE:": "DOCTYPE:", + "Document properties": "Dokumenteigenschaften", + "Document title:": "Dokumenttitel:", + "OK": "OK", + "Primary style-sheet:": "Stylesheet:", + "Text color:": "Textfarbe:", + "Character set:": "Zeichensatz", + "Description:": "Beschreibung", + "Keywords:": "Schlüsselworte", + "UTF-8 (recommended)": "UTF-8 (empfohlen)" +} diff --git a/xinha/plugins/FullPage/lang/fr.js b/xinha/plugins/FullPage/lang/fr.js new file mode 100644 index 0000000..7727a84 --- /dev/null +++ b/xinha/plugins/FullPage/lang/fr.js @@ -0,0 +1,17 @@ +// I18N for the FullPage plugin +// LANG: "fr", ENCODING: UTF-8 +{ + "Alternate style-sheet:": "Feuille CSS alternative", + "Background color:": "Couleur d'arrière plan", + "Cancel": "Annuler", + "DOCTYPE:": "DOCTYPE", + "Document properties": "Propriétés du document", + "Document title:": "Titre du document", + "OK": "OK", + "Primary style-sheet:": "Feuille CSS primaire", + "Text color:": "Couleur de texte", + "Character set:": "Jeu de caractères", + "Description:": "Description", + "Keywords:": "Mots clés", + "UTF-8 (recommended)": "UTF-8 (recommandé)" +}; \ No newline at end of file diff --git a/xinha/plugins/FullPage/lang/he.js b/xinha/plugins/FullPage/lang/he.js new file mode 100644 index 0000000..137a265 --- /dev/null +++ b/xinha/plugins/FullPage/lang/he.js @@ -0,0 +1,14 @@ +// I18N for the FullPage plugin +// LANG: "he", ENCODING: UTF-8 +// Author: Liron Newman, http://www.eesh.net, +{ + "Alternate style-sheet:": "גיליון סגנון אחר:", + "Background color:": "צבע רקע:", + "Cancel": "ביטול", + "DOCTYPE:": "DOCTYPE:", + "Document properties": "מאפייני מסמך", + "Document title:": "כותרת מסמך:", + "OK": "אישור", + "Primary style-sheet:": "גיליון סגנון ראשי:", + "Text color:": "צבע טקסט:" +}; diff --git a/xinha/plugins/FullPage/lang/ja.js b/xinha/plugins/FullPage/lang/ja.js new file mode 100644 index 0000000..34f51ff --- /dev/null +++ b/xinha/plugins/FullPage/lang/ja.js @@ -0,0 +1,17 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Alternate style-sheet:": "代替スタイルシート:", + "Background color:": "背景色:", + "Cancel": "中止", + "DOCTYPE:": "DOCTYPE:", + "Document properties": "文書のプロパティ", + "Document title:": "文書の表題:", + "OK": "OK", + "Primary style-sheet:": "優先スタイルシート:", + "Text color:": "文字色:", + "Character set:": "文字セット:", + "Description:": "説明:", + "Keywords:": "キーワード:", + "UTF-8 (recommended)": "UTF-8 (推奨)" +}; \ No newline at end of file diff --git a/xinha/plugins/FullPage/lang/nb.js b/xinha/plugins/FullPage/lang/nb.js new file mode 100644 index 0000000..cda95b8 --- /dev/null +++ b/xinha/plugins/FullPage/lang/nb.js @@ -0,0 +1,17 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Alternate style-sheet:": "Alternativt stilsett:", + "Background color:": "Bakgrunnsfarge:", + "Cancel": "Avbryt", + "DOCTYPE:": "DOCTYPE:", + "Keywords:": "Nøkkelord", + "Description:": "Beskrivelse", + "Character set:": "Tegnsett", + "Document properties": "Egenskaper for dokument", + "Document title:": "Tittel på dokument:", + "OK": "OK", + "Primary style-sheet:": "Stilsett:", + "Text color:": "Tekstfarge:" +}; \ No newline at end of file diff --git a/xinha/plugins/FullPage/lang/nl.js b/xinha/plugins/FullPage/lang/nl.js new file mode 100644 index 0000000..5c27857 --- /dev/null +++ b/xinha/plugins/FullPage/lang/nl.js @@ -0,0 +1,13 @@ +// I18N for the FullPage plugin +// LANG: "nl", ENCODING: UTF-8 +{ + "Alternate style-sheet:": "Wisselen van style-sheet:", + "Background color:": "Achtergrondkleur:", + "Cancel": "Annuleren", + "DOCTYPE:": "DOCTYPE:", + "Document properties": "Documenteigenschappen", + "Document title:": "Documenttitel:", + "OK": "OK", + "Primary style-sheet:": "Primaire style-sheet:", + "Text color:": "Tekstkleur:" +}; \ No newline at end of file diff --git a/xinha/plugins/FullPage/lang/pl.js b/xinha/plugins/FullPage/lang/pl.js new file mode 100644 index 0000000..3c5188e --- /dev/null +++ b/xinha/plugins/FullPage/lang/pl.js @@ -0,0 +1,18 @@ +// I18N for the FullPage plugin +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz, koto1sa@o2.pl, http://www.eskot.krakow.pl/portfolio +{ + "Alternate style-sheet:": "Alternatywny arkusz stylów:", + "Background color:": "Kolor tła:", + "Cancel": "Anuluj", + "DOCTYPE:": "DOCTYPE:", + "Document properties": "Właściwości dokumentu", + "Document title:": "Tytuł dokumentu:", + "OK": "OK", + "Primary style-sheet:": "Arkusz stylów:", + "Text color:": "Kolor tekstu:", + "Character set:": "Zestaw znaków", + "Description:": "Opis", + "Keywords:": "Słowa kluczowe", + "UTF-8 (recommended)": "UTF-8 (zalecany)" +}; diff --git a/xinha/plugins/FullPage/lang/ro.js b/xinha/plugins/FullPage/lang/ro.js new file mode 100644 index 0000000..d2b85e6 --- /dev/null +++ b/xinha/plugins/FullPage/lang/ro.js @@ -0,0 +1,14 @@ +// I18N for the FullPage plugin +// LANG: "en", ENCODING: UTF-8 +// Author: Mihai Bazon, http://dynarch.com/mishoo +{ + "Alternate style-sheet:": "Template CSS alternativ:", + "Background color:": "Culoare de fundal:", + "Cancel": "Renunţă", + "DOCTYPE:": "DOCTYPE:", + "Document properties": "Proprietăţile documentului", + "Document title:": "Titlul documentului:", + "OK": "Acceptă", + "Primary style-sheet:": "Template CSS principal:", + "Text color:": "Culoare text:" +}; diff --git a/xinha/plugins/FullPage/popups/docprop.html b/xinha/plugins/FullPage/popups/docprop.html new file mode 100644 index 0000000..0049e54 --- /dev/null +++ b/xinha/plugins/FullPage/popups/docprop.html @@ -0,0 +1,142 @@ + + +Document properties + + + + + + + + + +
    Document properties
    + +
    + + +
    +
    + + +
    +
    + + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + + +
    +
    + + + +
    + +
    + + + +
    + + + \ No newline at end of file diff --git a/xinha/plugins/FullScreen/full-screen.js b/xinha/plugins/FullScreen/full-screen.js new file mode 100644 index 0000000..4af22a5 --- /dev/null +++ b/xinha/plugins/FullScreen/full-screen.js @@ -0,0 +1,203 @@ +function FullScreen(editor, args) +{ + this.editor = editor; + editor._superclean_on = false; + cfg = editor.config; + + cfg.registerButton + ( 'fullscreen', + this._lc("Maximize/Minimize Editor"), + [_editor_url + cfg.imgURL + 'ed_buttons_main.gif',8,0], true, + function(e, objname, obj) + { + e._fullScreen(); + if(e._isFullScreen) + { + obj.swapImage([_editor_url + cfg.imgURL + 'ed_buttons_main.gif',9,0]); + } + else + { + obj.swapImage([_editor_url + cfg.imgURL + 'ed_buttons_main.gif',8,0]); + } + } + ); + + // See if we can find 'popupeditor' and replace it with fullscreen + cfg.addToolbarElement("fullscreen", "popupeditor", 0); +} + +FullScreen._pluginInfo = +{ + name : "FullScreen", + version : "1.0", + developer: "James Sleeman", + developer_url: "http://www.gogo.co.nz/", + c_owner : "Gogo Internet Services", + license : "htmlArea", + sponsor : "Gogo Internet Services", + sponsor_url : "http://www.gogo.co.nz/" +}; + +FullScreen.prototype._lc = function(string) { + return HTMLArea._lc(string, 'FullScreen'); +}; + +/** fullScreen makes an editor take up the full window space (and resizes when the browser is resized) + * the principle is the same as the "popupwindow" functionality in the original htmlArea, except + * this one doesn't popup a window (it just uses to positioning hackery) so it's much more reliable + * and much faster to switch between + */ + +HTMLArea.prototype._fullScreen = function() +{ + var e = this; + function sizeItUp() + { + if(!e._isFullScreen || e._sizing) return false; + e._sizing = true; + // Width & Height of window + var x,y; + if (window.innerHeight) // all except Explorer + { + x = window.innerWidth; + y = window.innerHeight; + } + else if (document.documentElement && document.documentElement.clientHeight) + // Explorer 6 Strict Mode + { + x = document.documentElement.clientWidth; + y = document.documentElement.clientHeight; + } + else if (document.body) // other Explorers + { + x = document.body.clientWidth; + y = document.body.clientHeight; + } + + e.sizeEditor(x + 'px',y + 'px',true,true); + e._sizing = false; + } + + function sizeItDown() + { + if(e._isFullScreen || e._sizing) return false; + e._sizing = true; + e.initSize(); + e._sizing = false; + } + + /** It's not possible to reliably get scroll events, particularly when we are hiding the scrollbars + * so we just reset the scroll ever so often while in fullscreen mode + */ + function resetScroll() + { + if(e._isFullScreen) + { + window.scroll(0,0); + window.setTimeout(resetScroll,150); + } + } + + if(typeof this._isFullScreen == 'undefined') + { + this._isFullScreen = false; + if(e.target != e._iframe) + { + HTMLArea._addEvent(window, 'resize', sizeItUp); + } + } + + // Gecko has a bug where if you change position/display on a + // designMode iframe that designMode dies. + if(HTMLArea.is_gecko) + { + this.deactivateEditor(); + } + + if(this._isFullScreen) + { + // Unmaximize + this._htmlArea.style.position = ''; + try + { + if(HTMLArea.is_ie) + { + var bod = document.getElementsByTagName('html'); + } + else + { + var bod = document.getElementsByTagName('body'); + } + bod[0].style.overflow=''; + } + catch(e) + { + // Nutthin + } + this._isFullScreen = false; + sizeItDown(); + + // Restore all ancestor positions + var ancestor = this._htmlArea; + while((ancestor = ancestor.parentNode) && ancestor.style) + { + ancestor.style.position = ancestor._xinha_fullScreenOldPosition; + ancestor._xinha_fullScreenOldPosition = null; + } + + window.scroll(this._unScroll.x, this._unScroll.y); + } + else + { + + // Get the current Scroll Positions + this._unScroll = + { + x:(window.pageXOffset)?(window.pageXOffset):(document.documentElement)?document.documentElement.scrollLeft:document.body.scrollLeft, + y:(window.pageYOffset)?(window.pageYOffset):(document.documentElement)?document.documentElement.scrollTop:document.body.scrollTop + }; + + + // Make all ancestors position = static + var ancestor = this._htmlArea; + while((ancestor = ancestor.parentNode) && ancestor.style) + { + ancestor._xinha_fullScreenOldPosition = ancestor.style.position; + ancestor.style.position = 'static'; + } + + // Maximize + window.scroll(0,0); + this._htmlArea.style.position = 'absolute'; + this._htmlArea.style.zIndex = 999; + this._htmlArea.style.left = 0; + this._htmlArea.style.top = 0; + this._isFullScreen = true; + resetScroll(); + + try + { + if(HTMLArea.is_ie) + { + var bod = document.getElementsByTagName('html'); + } + else + { + var bod = document.getElementsByTagName('body'); + } + bod[0].style.overflow='hidden'; + } + catch(e) + { + // Nutthin + } + + sizeItUp(); + } + + if(HTMLArea.is_gecko) + { + this.activateEditor(); + } + this.focusEditor(); +}; \ No newline at end of file diff --git a/xinha/plugins/FullScreen/lang/de.js b/xinha/plugins/FullScreen/lang/de.js new file mode 100644 index 0000000..72ff5a3 --- /dev/null +++ b/xinha/plugins/FullScreen/lang/de.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Raimund Meyer xinha@ray-of-light.org +{ + "Maximize/Minimize Editor": "Editor maximieren/verkleinern" +}; diff --git a/xinha/plugins/FullScreen/lang/fr.js b/xinha/plugins/FullScreen/lang/fr.js new file mode 100644 index 0000000..af4b014 --- /dev/null +++ b/xinha/plugins/FullScreen/lang/fr.js @@ -0,0 +1,5 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Maximize/Minimize Editor": "Agrandir/Réduire l'éditeur" +}; \ No newline at end of file diff --git a/xinha/plugins/FullScreen/lang/no.js b/xinha/plugins/FullScreen/lang/no.js new file mode 100644 index 0000000..9e4fdda --- /dev/null +++ b/xinha/plugins/FullScreen/lang/no.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "no", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Maximize/Minimize Editor": "Maksimer/Minimer WYSIWYG vindu" +}; \ No newline at end of file diff --git a/xinha/plugins/FullScreen/lang/pl.js b/xinha/plugins/FullScreen/lang/pl.js new file mode 100644 index 0000000..0c639bb --- /dev/null +++ b/xinha/plugins/FullScreen/lang/pl.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz, koto1sa@o2.pl, http://www.eskot.krakow.pl/portfolio +{ + "Maximize/Minimize Editor": "Maksymalizuj/minimalizuj edytor" +}; diff --git a/xinha/plugins/HtmlTidy/README b/xinha/plugins/HtmlTidy/README new file mode 100644 index 0000000..a3e19f2 --- /dev/null +++ b/xinha/plugins/HtmlTidy/README @@ -0,0 +1,104 @@ +// Plugin for htmlArea to run code through the server's HTML Tidy +// By Adam Wright, for The University of Western Australia +// +// Email: zeno@ucc.gu.uwa.edu.au +// Homepage: http://blog.hipikat.org/ +// +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). +// +// Version: 0.5 +// Released to the outside world: 04/03/04 + + +HtmlTidy is a plugin for the popular cross-browser TTY WYSIWYG editor, +htmlArea (http://www.interactivetools.com/products/htmlarea/). HtmlTidy +basically queries HTML Tidy (http://tidy.sourceforge.net/) on the +server side, getting it to make-html-nice, instead of relying on masses +of javascript, which the client would have to download. + +Hi, this is a quick explanation of how to install HtmlTidy. Much better +documentation is probably required, and you're welcome to write it :) + + +* The HtmlTidy directory you should have found this file in should + include the following: + + - README + This file, providing help installing the plugin. + + - html-tidy-config.cfg + This file contains the configuration options HTML Tidy uses to + clean html, and can be modified to suit your organizations + requirements. + + - html-tidy-logic.php + This is the php script, which is queried with dirty html and is + responsible for invoking HTML Tidy, getting nice new html and + returning it to the client. + + - html-tidy.js + The main htmlArea plugin, providing functionality to tidy html + through the htmlArea interface. + + - htmlarea.js.onmode_event.diff + At the time of publishing, an extra event handler was required + inside the main htmlarea.js file. htmlarea.js may be patched + against this file to make the changes reuquired, but be aware + that the event handler may either now be in the core or + htmlarea.js may have changed enough to invalidate the patch. + + UPDATE: now it exists in the official htmlarea.js; applying + this patch is thus no longer necessary. + + - img/html-tidy.gif + The HtmlTidy icon, for the htmlArea toolbar. Created by Dan + Petty for The University of Western Australia. + + - lang/en.js + English language file. Add your own language files here and + please contribute back into the htmlArea community! + + The HtmlArea directory should be extracted to your htmlarea/plugins/ + directory. + + +* Make sure the onMode event handler mentioned above, regarding + htmlarea.js.onmode_event.diff, exists in your htmlarea.js + + +* html-tidy-logic.php should be executable, and your web server should + be configured to execute php scripts in the directory + html-tidy-logic.php exists in. + + +* HTML Tidy needs to be installed on your server, and 'tidy' should be + an alias to it, lying in the PATH known to the user executing such + web scripts. + + +* In your htmlArea configuration, do something like this: + + HTMLArea.loadPlugin("HtmlTidy"); + + editor = new HTMLArea("doc"); + editor.registerPlugin("HtmlTidy"); + + +* Then, in your htmlArea toolbar configuration, use: + + - "HT-html-tidy" + This will create the 'tidy broom' icon on the toolbar, which + will attempt to tidy html source when clicked, and; + + - "HT-auto-tidy" + This will create an "Auto Tidy" / "Don't Tidy" dropdown, to + select whether the source should be tidied automatically when + entering source view. On by default, if you'd like it otherwise + you can do so programatically after generating the toolbar :) + (Or just hack it to be otherwise...) + + +Thank you. + +Any bugs you find can be emailed to zeno@ucc.gu.uwa.edu.au diff --git a/xinha/plugins/HtmlTidy/html-tidy-config.cfg b/xinha/plugins/HtmlTidy/html-tidy-config.cfg new file mode 100644 index 0000000..7616992 --- /dev/null +++ b/xinha/plugins/HtmlTidy/html-tidy-config.cfg @@ -0,0 +1,29 @@ +// Default configuration file for the htmlArea, HtmlTidy plugin +// By Adam Wright, for The University of Western Australia +// +// Evertything you always wanted to know about HTML Tidy * +// can be found at http://tidy.sourceforge.net/, and a +// quick reference to the configuration options exists at +// http://tidy.sourceforge.net/docs/quickref.html +// +// * But were afraid to ask +// +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). + +word-2000: yes +clean: yes +drop-font-tags: no +doctype: auto +drop-empty-paras: yes +drop-proprietary-attributes: yes +enclose-block-text: yes +enclose-text: yes +escape-cdata: yes +logical-emphasis: yes +indent: auto +indent-spaces: 2 +break-before-br: yes +output-xhtml: yes + +force-output: yes diff --git a/xinha/plugins/HtmlTidy/html-tidy-logic.php b/xinha/plugins/HtmlTidy/html-tidy-logic.php new file mode 100755 index 0000000..f572c94 --- /dev/null +++ b/xinha/plugins/HtmlTidy/html-tidy-logic.php @@ -0,0 +1,79 @@ + array("pipe", "r"), + 1 => array("pipe", "w") + ); + $process = @proc_open("tidy -utf8 -config {$cwd}html-tidy-config.cfg", $descriptorspec, $pipes); + + + // Make sure the program started and we got the hooks... + // Either way, get some source code into $source + if (is_resource($process)) { + + // Feed untidy source into the stdin + fwrite($pipes[0], $source); + fclose($pipes[0]); + + // Read clean source out to the browser + while (!feof($pipes[1])) { + //echo fgets($pipes[1], 1024); + $newsrc .= fgets($pipes[1], 1024); + } + fclose($pipes[1]); + + // Clean up after ourselves + proc_close($process); + + } else { + /* Use tidy if it's available from PECL */ + if( function_exists('tidy_parse_string') ) + { + $tempsrc = tidy_parse_string($source); + tidy_clean_repair(); + $newsrc = tidy_get_output(); + } + else + { + // Better give them back what they came with, so they don't lose it all... + $newsrc = "\n" .$source. "\n"; + } + } + + // Split our source into an array by lines + $srcLines = preg_split("/\n/",$newsrc,-1,PREG_SPLIT_NO_EMPTY); + + // Get only the lines between the body tags + $startLn = 0; + while ( strpos( $srcLines[$startLn++], ' +var ns=""; + +editor.setHTML(ns); + \ No newline at end of file diff --git a/xinha/plugins/HtmlTidy/html-tidy.js b/xinha/plugins/HtmlTidy/html-tidy.js new file mode 100644 index 0000000..5362c9b --- /dev/null +++ b/xinha/plugins/HtmlTidy/html-tidy.js @@ -0,0 +1,105 @@ +// Plugin for htmlArea to run code through the server's HTML Tidy +// By Adam Wright, for The University of Western Australia +// +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). + +function HtmlTidy(editor) { + this.editor = editor; + + var cfg = editor.config; + var bl = HtmlTidy.btnList; + var self = this; + + this.onMode = this.__onMode; + + // register the toolbar buttons provided by this plugin + var toolbar = []; + for (var i = 0; i < bl.length; ++i) { + var btn = bl[i]; + if (btn == "html-tidy") { + var id = "HT-html-tidy"; + cfg.registerButton(id, this._lc("HTML Tidy"), editor.imgURL(btn[0] + ".gif", "HtmlTidy"), true, + function(editor, id) { + // dispatch button press event + self.buttonPress(editor, id); + }, btn[1]); + toolbar.push(id); + } else if (btn == "html-auto-tidy") { + var btnTxt = [this._lc("Auto-Tidy"), this._lc("Don't Tidy")]; + var optionItems = new Object(); + optionItems[btnTxt[0]] = "auto"; + optionItems[btnTxt[1]] = "noauto"; + var ht_class = { + id : "HT-auto-tidy", + options : optionItems, + action : function (editor) { self.__onSelect(editor, this); }, + refresh : function (editor) { }, + context : "body" + }; + cfg.registerDropdown(ht_class); + } + } + + for (var i in toolbar) { + cfg.toolbar[0].push(toolbar[i]); + } +} + +HtmlTidy._pluginInfo = { + name : "HtmlTidy", + version : "1.0", + developer : "Adam Wright", + developer_url : "http://blog.hipikat.org/", + sponsor : "The University of Western Australia", + sponsor_url : "http://www.uwa.edu.au/", + license : "htmlArea" +}; + +HtmlTidy.prototype._lc = function(string) { + return HTMLArea._lc(string, 'HtmlTidy'); +}; + +HtmlTidy.prototype.__onSelect = function(editor, obj) { + // Get the toolbar element object + var elem = editor._toolbarObjects[obj.id].element; + + // Set our onMode event appropriately + if (elem.value == "auto") + this.onMode = this.__onMode; + else + this.onMode = null; +}; + +HtmlTidy.prototype.__onMode = function(mode) { + if ( mode == "textmode" ) { + this.buttonPress(this.editor, "HT-html-tidy"); + } +}; + +HtmlTidy.btnList = [ + null, // separator + ["html-tidy"], + ["html-auto-tidy"] +]; + +HtmlTidy.prototype.buttonPress = function(editor, id) { + + switch (id) + { + case "HT-html-tidy": + { + var oldhtml = editor.getHTML(); + if(oldhtml=="") break; //don't clean empty text + // Ask the server for some nice new html, based on the old... + HTMLArea._postback(_editor_url + 'plugins/HtmlTidy/html-tidy-logic.php', {'htisource_name' : oldhtml}, + function(javascriptResponse) { eval(javascriptResponse) }); + } + break; + } +}; + +HtmlTidy.prototype.processTidied = function(newSrc) { + editor = this.editor; + editor.setHTML(newSrc); +}; \ No newline at end of file diff --git a/xinha/plugins/HtmlTidy/img/html-tidy.gif b/xinha/plugins/HtmlTidy/img/html-tidy.gif new file mode 100644 index 0000000..50cc6a7 Binary files /dev/null and b/xinha/plugins/HtmlTidy/img/html-tidy.gif differ diff --git a/xinha/plugins/HtmlTidy/lang/de.js b/xinha/plugins/HtmlTidy/lang/de.js new file mode 100644 index 0000000..ce69fc2 --- /dev/null +++ b/xinha/plugins/HtmlTidy/lang/de.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// Author: Raimund Meyer ray@ray-of-light.org +{ + "HTML Tidy": "HTML Tidy", + "Tidy failed. Check your HTML for syntax errors.": "Tidy fehlgeschlagen. Prüfen Sie den HTML Code nach Syntax-Fehlern." +}; diff --git a/xinha/plugins/HtmlTidy/lang/fr.js b/xinha/plugins/HtmlTidy/lang/fr.js new file mode 100644 index 0000000..5312a08 --- /dev/null +++ b/xinha/plugins/HtmlTidy/lang/fr.js @@ -0,0 +1,8 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "HTML Tidy": "HTML Tidy", + "Auto-Tidy": "Tidy automatique", + "Don't Tidy": "Tidy non utilisé", + "Tidy failed. Check your HTML for syntax errors.": "Tidy a échoué. Vérifiez votre HTML for des erreurs de syntaxe" +}; \ No newline at end of file diff --git a/xinha/plugins/HtmlTidy/lang/ja.js b/xinha/plugins/HtmlTidy/lang/ja.js new file mode 100644 index 0000000..539e0dd --- /dev/null +++ b/xinha/plugins/HtmlTidy/lang/ja.js @@ -0,0 +1,8 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "HTML Tidy": "HTML Tidy", + "Auto-Tidy": "自動適正化", + "Don't Tidy": "適正化しない", + "Tidy failed. Check your HTML for syntax errors.":"適正化に失敗しました。HTMLの文法エラーを確認してください。" +}; \ No newline at end of file diff --git a/xinha/plugins/HtmlTidy/lang/nb.js b/xinha/plugins/HtmlTidy/lang/nb.js new file mode 100644 index 0000000..d94d44f --- /dev/null +++ b/xinha/plugins/HtmlTidy/lang/nb.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "HTML Tidy": "HTML Tidy", + "Tidy failed. Check your HTML for syntax errors.": "Tidy feilet. Sjekk HTML koden for syntaksfeil." +}; \ No newline at end of file diff --git a/xinha/plugins/HtmlTidy/lang/nl.js b/xinha/plugins/HtmlTidy/lang/nl.js new file mode 100644 index 0000000..bc2f718 --- /dev/null +++ b/xinha/plugins/HtmlTidy/lang/nl.js @@ -0,0 +1,5 @@ +// I18N constants +// LANG: "nl", ENCODING: UTF-8 +{ + "HT-html-tidy": "HTML opschonen" +}; \ No newline at end of file diff --git a/xinha/plugins/InsertAnchor/img/insert-anchor.gif b/xinha/plugins/InsertAnchor/img/insert-anchor.gif new file mode 100755 index 0000000..9da891b Binary files /dev/null and b/xinha/plugins/InsertAnchor/img/insert-anchor.gif differ diff --git a/xinha/plugins/InsertAnchor/img/placeholder.gif b/xinha/plugins/InsertAnchor/img/placeholder.gif new file mode 100755 index 0000000..2c34277 Binary files /dev/null and b/xinha/plugins/InsertAnchor/img/placeholder.gif differ diff --git a/xinha/plugins/InsertAnchor/insert-anchor.css b/xinha/plugins/InsertAnchor/insert-anchor.css new file mode 100755 index 0000000..097d511 --- /dev/null +++ b/xinha/plugins/InsertAnchor/insert-anchor.css @@ -0,0 +1,9 @@ +a.anchor { + width: 18px; + height: 18px; + background-image: url(img/insert-anchor.gif); + background-repeat: no-repeat; + background-position: left top; + padding-left: 19px; + border: 1px dotted blue; +} diff --git a/xinha/plugins/InsertAnchor/insert-anchor.js b/xinha/plugins/InsertAnchor/insert-anchor.js new file mode 100755 index 0000000..70679f4 --- /dev/null +++ b/xinha/plugins/InsertAnchor/insert-anchor.js @@ -0,0 +1,76 @@ +function InsertAnchor(_1){ +this.editor=_1; +var _2=_1.config; +var _3=this; +_2.registerButton({id:"insert-anchor",tooltip:this._lc("Insert Anchor"),image:_1.imgURL("insert-anchor.gif","InsertAnchor"),textMode:false,action:function(_4){ +_3.buttonPress(_4); +}}); +_2.addToolbarElement("insert-anchor","createlink",1); +} +InsertAnchor._pluginInfo={name:"InsertAnchor",origin:"version: 1.0, by Andre Rabold, MR Printware GmbH, http://www.mr-printware.de",version:"2.0",developer:"Udo Schmal",developer_url:"http://www.schaffrath-neuemedien.de",c_owner:"Udo Schmal",sponsor:"L.N.Schaffrath NeueMedien",sponsor_url:"http://www.schaffrath-neuemedien.de",license:"htmlArea"}; +InsertAnchor.prototype._lc=function(_5){ +return HTMLArea._lc(_5,"InsertAnchor"); +}; +InsertAnchor.prototype.onGenerate=function(){ +var _6="IA-style"; +var _7=this.editor._doc.getElementById(_6); +if(_7==null){ +_7=this.editor._doc.createElement("link"); +_7.id=_6; +_7.rel="stylesheet"; +_7.href=_editor_url+"plugins/InsertAnchor/insert-anchor.css"; +this.editor._doc.getElementsByTagName("HEAD")[0].appendChild(_7); +} +}; +InsertAnchor.prototype.buttonPress=function(_8){ +var _9=null; +var _a=_8.getSelectedHTML(); +var _b=_8._getSelection(); +var _c=_8._createRange(_b); +var a=_8._activeElement(_b); +if(!(a!=null&&a.tagName.toLowerCase()=="a")){ +a=_8._getFirstAncestor(_b,"a"); +} +if(a!=null&&a.tagName.toLowerCase()=="a"){ +_9={name:a.id}; +}else{ +_9={name:""}; +} +_8._popupDialog("plugin://InsertAnchor/insert_anchor",function(_e){ +if(_e){ +var _f=_e["name"]; +if(_f==""||_f==null){ +if(a){ +var _10=a.innerHTML; +a.parentNode.removeChild(a); +_8.insertHTML(_10); +} +return; +} +try{ +var doc=_8._doc; +if(!a){ +a=doc.createElement("a"); +a.id=_f; +a.name=_f; +a.title=_f; +a.className="anchor"; +a.innerHTML=_a; +if(HTMLArea.is_ie){ +_c.pasteHTML(a.outerHTML); +}else{ +_8.insertNodeAtSelection(a); +} +}else{ +a.id=_f; +a.name=_f; +a.title=_f; +a.className="anchor"; +} +} +catch(e){ +} +} +},_9); +}; + diff --git a/xinha/plugins/InsertAnchor/lang/de.js b/xinha/plugins/InsertAnchor/lang/de.js new file mode 100755 index 0000000..1b10785 --- /dev/null +++ b/xinha/plugins/InsertAnchor/lang/de.js @@ -0,0 +1,8 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Raimund Meyer xinha@ray-of-light.org +{ + "Insert Anchor": "Anker einfügen", + "Anchor name": "Name (ID)", + "Delete": "Löschen" +}; diff --git a/xinha/plugins/InsertAnchor/lang/fr.js b/xinha/plugins/InsertAnchor/lang/fr.js new file mode 100644 index 0000000..17d76b6 --- /dev/null +++ b/xinha/plugins/InsertAnchor/lang/fr.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Insert Anchor": "Insérer une ancre", + "Anchor name": "Nom de l'ancre", + "Delete": "Supprimer" +}; \ No newline at end of file diff --git a/xinha/plugins/InsertAnchor/lang/ja.js b/xinha/plugins/InsertAnchor/lang/ja.js new file mode 100644 index 0000000..347fb00 --- /dev/null +++ b/xinha/plugins/InsertAnchor/lang/ja.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Insert Anchor": "アンカーの挿入", + "Anchor name": "アンカーの名前", + "Delete": "削除" +}; \ No newline at end of file diff --git a/xinha/plugins/InsertAnchor/lang/nb.js b/xinha/plugins/InsertAnchor/lang/nb.js new file mode 100644 index 0000000..25ca29a --- /dev/null +++ b/xinha/plugins/InsertAnchor/lang/nb.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Insert Anchor": "Sett inn anker", + "Anchor name": "Ankernavn (ID)" +}; \ No newline at end of file diff --git a/xinha/plugins/InsertAnchor/lang/nl.js b/xinha/plugins/InsertAnchor/lang/nl.js new file mode 100644 index 0000000..7751dea --- /dev/null +++ b/xinha/plugins/InsertAnchor/lang/nl.js @@ -0,0 +1,8 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Raimund Meyer xinha@ray-of-light.org +{ + "Insert Anchor": "Anker invoegen", + "Anchor name": "Naam (ID)", + "Delete": "Verwijderen" +}; diff --git a/xinha/plugins/InsertAnchor/lang/pl.js b/xinha/plugins/InsertAnchor/lang/pl.js new file mode 100644 index 0000000..cb938b6 --- /dev/null +++ b/xinha/plugins/InsertAnchor/lang/pl.js @@ -0,0 +1,8 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz koto@webworkers.pl +{ + "Insert Anchor": "Wstaw kotwicę", + "Anchor name": "Nazwa kotwicy", + "Delete": "Usuń" +}; diff --git a/xinha/plugins/InsertAnchor/popups/insert_anchor.html b/xinha/plugins/InsertAnchor/popups/insert_anchor.html new file mode 100644 index 0000000..33e5f47 --- /dev/null +++ b/xinha/plugins/InsertAnchor/popups/insert_anchor.html @@ -0,0 +1,59 @@ + + + Insert Anchor + + + + + + +
    Insert Anchor
    +
    + + + + + +
    Anchor name
    + +
    + + + +
    +
    + + \ No newline at end of file diff --git a/xinha/plugins/InsertPicture/InsertPicture.php b/xinha/plugins/InsertPicture/InsertPicture.php new file mode 100644 index 0000000..5de94e4 --- /dev/null +++ b/xinha/plugins/InsertPicture/InsertPicture.php @@ -0,0 +1,301 @@ += 1024 && $size < 1024*1024) + return sprintf('%01.2f',$size/1024.0).' Kb'; + else + return sprintf('%01.2f',$size/(1024.0*1024)).' Mb'; + } + $DestFileName = ""; + if (isset($_FILES['file'])) { + $file = $_FILES['file']; + $ext = strrchr($file['name'],'.'); + if (!in_array($ext,$limitedext)) + $message = "The file you are uploading doesn't have the correct extension."; + else if (file_exists($LocalPicturePath.$file['name'])) + $message = "The file you are uploading already exists."; + else if ($file['size'] > $limitedsize) + $message = "The file you are uploading is to big. The max Filesize is ".formatSize($limitedsize)."."; + else + copy($file['tmp_name'], $LocalPicturePath.$file['name']); + $DestFileName = $file['name']; + } +?> + + + Insert Image + + + + + + +
    Insert Image
    + + + + + + + +
    Images on the Server:
    + + +
    + + +
    +
    + +
    + +
    + Image Preview: +
    + +
    + +
    + + + + + + + + + + + + + + + +
    Image URL: + +
    Alternate text:
    + +

    + +

    +Layout + +
    + +
    Alignment:
    + + +

    + +

    Border thickness:
    + +
    + +
    + +
    +Size + +
    + +
    Width:
    + +

    + +

    Height:
    + +
    + +
    + +
    +Spacing + +
    + +
    Horizontal:
    + +

    + +

    Vertical:
    + + +
    + +
    +
    + +
    + + +
    +
    + + \ No newline at end of file diff --git a/xinha/plugins/InsertPicture/img/btn_open.gif b/xinha/plugins/InsertPicture/img/btn_open.gif new file mode 100644 index 0000000..2056f2c Binary files /dev/null and b/xinha/plugins/InsertPicture/img/btn_open.gif differ diff --git a/xinha/plugins/InsertPicture/img/nopic.gif b/xinha/plugins/InsertPicture/img/nopic.gif new file mode 100644 index 0000000..d4e8a78 Binary files /dev/null and b/xinha/plugins/InsertPicture/img/nopic.gif differ diff --git a/xinha/plugins/InsertPicture/insert-picture.js b/xinha/plugins/InsertPicture/insert-picture.js new file mode 100644 index 0000000..02f6c12 --- /dev/null +++ b/xinha/plugins/InsertPicture/insert-picture.js @@ -0,0 +1,25 @@ +// Insert Image plugin for Xinha +// Original Author - Udo Schmal +// +// (c) www.Schaffrath-NeueMedien.de 2004 +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). + +function InsertPicture(editor) { + if ( typeof _editor_picturePath !== "string" ) + _editor_picturePath = _editor_url + "plugins/InsertPicture/demo_pictures/"; + InsertPicture.Scripting = "php"; //else "asp" + editor.config.URIs.insert_image = '../plugins/InsertPicture/InsertPicture.' + InsertPicture.Scripting + '?picturepath=' + _editor_picturePath; +} + +InsertPicture._pluginInfo = { + name : "InsertPicture", + version : "1.0.2", + developer : "Udo Schmal", + developer_url : "http://www.Schaffrath-NeueMedien.de/", + sponsor : "L.N.Schaffrath NeueMedien", + sponsor_url : "http://www.schaffrath-neuemedien.de/", + c_owner : "Udo Schmal", + license : "htmlArea" +}; + diff --git a/xinha/plugins/InsertPicture/lang/de.js b/xinha/plugins/InsertPicture/lang/de.js new file mode 100644 index 0000000..83bc5e5 --- /dev/null +++ b/xinha/plugins/InsertPicture/lang/de.js @@ -0,0 +1,15 @@ +// LANG: "de", ENCODING: UTF-8 | ISO-8859-1 +// Sponsored by http://www.schaffrath-neuemedien.de +// Author: Udo Schmal (gocher), http://www.schaffrath-neuemedien.de/, udo.schmal@t-online.de +{ + "The file you are uploading doesn't have the correct extension.": "Die hochgeladene Datei ist im falschen Format.", + "The file you are uploading already exists.": "Eine Datei mit diesem Namen existiert schon.", + "The file you are uploading is to big. The max Filesize is": "Die hochgeladene Datei ist zu groß. Die maximakle Dateigröße beträgt", + "Images on the Server:": "Bilder auf dem Server:", + "Please select a file to upload.": "Wählen Sie eine Datei zum hochladen aus.", + "Upload file": "Datei hochladen", + "Open file in new window": "Datei in neuen Fenster anzeigen", + "Size": "Größe", + "Width:": "Breite", + "Height:": "Höhe" +}; \ No newline at end of file diff --git a/xinha/plugins/InsertPicture/lang/fr.js b/xinha/plugins/InsertPicture/lang/fr.js new file mode 100644 index 0000000..a1bfb2c --- /dev/null +++ b/xinha/plugins/InsertPicture/lang/fr.js @@ -0,0 +1,22 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Insert Image": "Insérer une image", + "Image Preview:": "Prévisualisation", + "Image URL:": "URL", + "Preview": "Prévisualisation", + "Alternate text:": "Texte alternatif", + "Layout": "Layout", + "Alignment:": "Alignement", + "Border thickness:": "Epaisseur bordure", + "Spacing": "Espacement", + "Horizontal:": "Horizontal", + "Vertical:": "Vertical", + "The file you are uploading doesn't have the correct extension.": "Le fichier que vous téléchargez ne possède pas la bonne extension.", + "The file you are uploading already exists.": "Le fichier que vous téléchargez existe déjà.", + "The file you are uploading is to big. The max Filesize is": "Le fichier que vous uploadez est trop gros. La taille maximum est", + "Images on the Server:": "Images sur le serveur", + "Please select a file to upload.": "Veuillez sélectionner un fichier a télécharger", + "Upload file": "Télécharger", + "Open file in new window": "Ouvrir le fichier dans une nouvelle fenêtre" +}; \ No newline at end of file diff --git a/xinha/plugins/InsertPicture/lang/ja.js b/xinha/plugins/InsertPicture/lang/ja.js new file mode 100644 index 0000000..4093743 --- /dev/null +++ b/xinha/plugins/InsertPicture/lang/ja.js @@ -0,0 +1,25 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Insert Image": "画像の挿入", + "Image Preview:": "画像プレビュー:", + "Image URL:": "画像URL:", + "Preview": "表示", + "Alternate text:": "代替テキスト:", + "Layout": "レイアウト", + "Alignment:": "行揃え:", + "Border thickness:": "境界線の幅:", + "Spacing": "間隔", + "Horizontal:": "水平:", + "Vertical:": "垂直:", + "The file you are uploading doesn't have the correct extension.": "アップロード対象ファイルに正しい拡張子がありません。", + "The file you are uploading already exists.": "アップロード対象ファイルはすでに存在します。", + "The file you are uploading is to big. The max Filesize is": "アップロード対象ファイルは大きすぎます。ファイルサイズの上限:", + "Images on the Server:": "サーバ上の画像:", + "Please select a file to upload.": "アップロードするファイルを選択してください。", + "Upload file": "UPLOAD FILE", + "Open file in new window": "新しいウィンドウでファイルを開く", + "Size": "サイズ", + "Width:": "幅:", + "Height:": "高さ:" +}; \ No newline at end of file diff --git a/xinha/plugins/InsertPicture/lang/nb.js b/xinha/plugins/InsertPicture/lang/nb.js new file mode 100644 index 0000000..e4598aa --- /dev/null +++ b/xinha/plugins/InsertPicture/lang/nb.js @@ -0,0 +1,22 @@ +// LANG: "nb", ENCODING: UTF-8 | ISO-8859-1 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Insert Image": "Sett inn bilde", + "Image Preview:": "Forhåndsvisning:", + "Image URL:": "Bildets URL:", + "Preview": "Forhåndsvisning", + "Alternate text:": "Alternativ tekst", + "Layout": "Oppsett", + "Alignment:": "Plassering", + "Border thickness:": "Rammetykkelse:", + "Spacing": "Luft rundt bildet", + "Horizontal:": "Horisontal:", + "Vertical:": "Vertikal:", + "The file you are uploading doesn't have the correct extension.": "Bildet du laster opp har et ugyldig format, opplastning avbrutt", + "The file you are uploading already exists.": "Bildet du prøver å laste opp eksisterer allerede på serveren", + "The file you are uploading is to big. The max Filesize is": "Bildet du laster opp er for stort, maks tillatt størrelse er", + "Images on the Server:": "Bilder på serveren:", + "Please select a file to upload.": "Velg bilde du skal laste opp", + "Upload file": "Last opp bilde", + "Open file in new window": "Åpne bilde i nytt vindu" +}; \ No newline at end of file diff --git a/xinha/plugins/InsertPicture/lang/sv.js b/xinha/plugins/InsertPicture/lang/sv.js new file mode 100644 index 0000000..6218489 --- /dev/null +++ b/xinha/plugins/InsertPicture/lang/sv.js @@ -0,0 +1,35 @@ +// I18N constants +// LANG: "sv", ENCODING: UTF-8 +// Swedish version for rev. 477 (Mar 2006) by Thomas Loo + +{ + "Insert Image": "Infoga bild", + "Image Preview:": "Förhandsgranskning:", + "Image URL:": "Bildens URL:", + "Preview": "Förhandsgranska", + "Alternate text:": "Alternativ text:", + "Layout": "Layout", + "Alignment:": "Placering:", + "Border thickness:": "Ramtjocklek:", + "Spacing": "Marginal", + "Horizontal:": "Horisontell:", + "Vertical:": "Vertikal:", + "The file you are uploading doesn't have the correct extension.": "Uppladdat bild har en ogiltig filändelse, uppladdning avbruten", + "The file you are uploading already exists.": "En fil med detta namn finns redan", + "The file you are uploading is to big. The max Filesize is": "Filen är för stor, maximal filstorlek är", + "Images on the Server:": "Bilder på servern:", + "Please select a file to upload.": "Välj bild att ladda upp", + "Upload file": "Ladda upp bild", + "Size": "Storlek", + "Width:": "Bredd:", + "Height:": "Höjd:", + // tooltips + "Enter the image URL here":"Bildens sökväg (URL)", + "Preview the image in a new window": "Öppna bild i nytt fönster", + "For browsers that don't support images":"Beskrivande text för webläsare som inte stödjer inbäddade bilder", + "Positioning of this image": "Bildens positionering", + "Leave empty for no border": "Lämna tomt för att undvika ram", + "Leave empty for not defined": "Lämna tomt för att låta webläsaren bestämma", + "Horizontal padding": "Horizontellt indrag på bild", + "Vertical padding": "Vertikalt indrag på bild" +}; diff --git a/xinha/plugins/InsertPicture/viewpicture.html b/xinha/plugins/InsertPicture/viewpicture.html new file mode 100644 index 0000000..00823bf --- /dev/null +++ b/xinha/plugins/InsertPicture/viewpicture.html @@ -0,0 +1,46 @@ + + + + Preview + + + + + + + + \ No newline at end of file diff --git a/xinha/plugins/InsertWords/insert-words.js b/xinha/plugins/InsertWords/insert-words.js new file mode 100755 index 0000000..907fc56 --- /dev/null +++ b/xinha/plugins/InsertWords/insert-words.js @@ -0,0 +1,70 @@ +// Plugin for htmlArea to insert keywords, when a type of +// keyword is selected from a dropdown list +// By Adam Wright, for The University of Western Australia +// +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). + +function InsertWords(editor, params) { + this.editor = editor; + var cfg = editor.config; + var self = this; + + if(params[0] && params[0].combos) { + //if arguments where passed with registerPlugin use these + var combos = params[0].combos; + } else if (cfg.InsertWords && cfg.InsertWords.combos) { + //if combos is found in config use these + var combos = cfg.InsertWords.combos; + } else { + //no combos found + var combos = []; + } + + // register the toolbar with the keywords dropdown + var first = true; + var toolbar = []; + + for (var i = combos.length; --i >= 0;) { + var combo = combos[i]; + var id = "IW-id" + i; + var iw_class = { + id : id, + options : combo.options, + action : function (editor) { self.onSelect(editor, this, combo.context); }, + refresh : function (editor) { }, + context : combo.context + }; + cfg.registerDropdown(iw_class); + + if (combo.label) + toolbar.push("T[" + combo.label + "]"); + toolbar.push(id); + toolbar.push(first ? "separator" : "space"); + } + + cfg.addToolbarElement(toolbar, "linebreak", 1); + +} + +InsertWords._pluginInfo = { + name : "InsertWords", + version : "1.0", + developer : "Adam Wright", + developer_url : "http://blog.hipikat.org/", + sponsor : "The University of Western Australia", + sponsor_url : "http://www.uwa.edu.au/", + license : "htmlArea" +}; + +InsertWords.prototype.onSelect = function(editor, obj, context) { + + // Get the toolbar object element + var elem = editor._toolbarObjects[obj.id].element; + + // Insert the keyword value blindly at the selection + editor.insertHTML(elem.value); + + // Reset the dropdown to it's label + elem.selectedIndex = 0; +}; \ No newline at end of file diff --git a/xinha/plugins/Linker/dTree/api.html b/xinha/plugins/Linker/dTree/api.html new file mode 100644 index 0000000..465861b --- /dev/null +++ b/xinha/plugins/Linker/dTree/api.html @@ -0,0 +1,252 @@ + + + + + + Destroydrop » Javascripts » Tree » Api + + + + + + + + +
    + +
    + + + + +
    + +
    + + +

    Overview

    +
    +
    + + + +
    + + +

    Functions

    +
    +
    + + +

    add()

    +

    Adds a node to the tree.
    Can only be called before the tree is drawn.

    +

    id, pid and name are required.

    + +

    Parameters

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    idNumberUnique identity number.
    pidNumberNumber refering to the parent node. The value for the root node has to be -1.
    nameStringText label for the node.
    urlStringUrl for the node.
    titleStringTitle for the node.
    targetStringTarget for the node.
    iconStringImage file to use as the icon. Uses default if not specified.
    iconOpenStringImage file to use as the open icon. Uses default if not specified.
    openBooleanIs the node open.
    +
    + + +

    Example

    +

    mytree.add(1, 0, 'My node', 'node.html', 'node title', 'mainframe', 'img/musicfolder.gif');

    +
    + + +

    openAll()

    +

    Opens all the nodes.
    Can be called before and after the tree is drawn.

    +

    Example

    +

    mytree.openAll();

    +
    + + + +

    closeAll()

    +

    Closes all the nodes.
    Can be called before and after the tree is drawn.

    +

    Example

    +

    mytree.closeAll();

    +
    + + + +

    openTo()

    +

    Opens the tree to a certain node and can also select the node.
    + Can only be called after the tree is drawn.

    + +

    Parameters

    + + + + + + + + + + + + + + + + +
    NameTypeDescription
    idNumberIdentity number for the node.
    selectBooleanShould the node be selected.
    + +

    Example

    +

    mytree.openTo(4, true);

    + +
    + + +

    Configuration

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    VariableTypeDefaultDescription
    targetStringtrueTarget for all the nodes.
    folderLinksBooleantrueShould folders be links.
    useSelectionBooleantrueNodes can be selected(highlighted).
    useCookiesBooleantrueThe tree uses cookies to rember it's state.
    useLinesBooleantrueTree is drawn with lines.
    useIconsBooleantrueTree is drawn with icons.
    useStatusTextBooleanfalseDisplays node names in the statusbar instead of the url.
    closeSameLevelBooleanfalseOnly one node within a parent can be expanded at the same time. openAll() and closeAll() functions do not work when this is enabled.
    inOrderBooleanfalseIf parent nodes are always added before children, setting this to true speeds up the tree.
    + +

    Example

    +

    mytree.config.target = "mytarget";

    + +
    + +
    + +
    + + + + +
    + +
    + + + + + \ No newline at end of file diff --git a/xinha/plugins/Linker/dTree/dtree.css b/xinha/plugins/Linker/dTree/dtree.css new file mode 100644 index 0000000..44c14fd --- /dev/null +++ b/xinha/plugins/Linker/dTree/dtree.css @@ -0,0 +1,39 @@ +/*--------------------------------------------------| +| dTree 2.05 | www.destroydrop.com/javascript/tree/ | +|---------------------------------------------------| +| Copyright (c) 2002-2003 Geir Landr? | +|--------------------------------------------------*/ + +.dtree { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + color: #666; + white-space: nowrap; +} +.dtree img { + border: 0px; + vertical-align: middle; +} +.dtree a,.dtree a:visited { + color: #333; + text-decoration: none; +} +.dtree a.node, .dtree a.nodeSel { + white-space: nowrap; + padding: 1px 2px 1px 2px; + /*padding: 0px 1px 0px 1px;*/ +} +.dtree a.node:hover, .dtree a.nodeSel:hover { + color: #333; + text-decoration: underline; +} +.dtree a.nodeSel { + background-color: #c0d2ec; + /* + -moz-border-radius : 4px; + border:1px dotted #333; + */ +} +.dtree .clip { + overflow: hidden; +} \ No newline at end of file diff --git a/xinha/plugins/Linker/dTree/dtree.js b/xinha/plugins/Linker/dTree/dtree.js new file mode 100644 index 0000000..52932e2 --- /dev/null +++ b/xinha/plugins/Linker/dTree/dtree.js @@ -0,0 +1,354 @@ +function Node(id,_2,_3,_4,_5,_6,_7,_8,_9){ +this.id=id; +this.pid=_2; +this.name=_3; +this.url=_4; +this.title=_5; +this.target=_6; +this.icon=_7; +this.iconOpen=_8; +this._io=_9||false; +this._is=false; +this._ls=false; +this._hc=false; +this._ai=0; +this._p; +} +function dTree(_a,_b){ +this.config={target:null,folderLinks:true,useSelection:true,useCookies:true,useLines:true,useIcons:true,useStatusText:false,closeSameLevel:false,inOrder:false}; +this.icon={root:_b+"img/base.gif",folder:_b+"img/folder.gif",folderOpen:_b+"img/folderopen.gif",node:_b+"img/page.gif",empty:_b+"img/empty.gif",line:_b+"img/line.gif",join:_b+"img/join.gif",joinBottom:_b+"img/joinbottom.gif",plus:_b+"img/plus.gif",plusBottom:_b+"img/plusbottom.gif",minus:_b+"img/minus.gif",minusBottom:_b+"img/minusbottom.gif",nlPlus:_b+"img/nolines_plus.gif",nlMinus:_b+"img/nolines_minus.gif"}; +this.obj=_a; +this.aNodes=[]; +this.aIndent=[]; +this.root=new Node(-1); +this.selectedNode=null; +this.selectedFound=false; +this.completed=false; +} +dTree.prototype.add=function(id,_d,_e,_f,_10,_11,_12,_13,_14){ +this.aNodes[this.aNodes.length]=new Node(id,_d,_e,_f,_10,_11,_12,_13,_14); +}; +dTree.prototype.openAll=function(){ +this.oAll(true); +}; +dTree.prototype.closeAll=function(){ +this.oAll(false); +}; +dTree.prototype.toString=function(){ +this.setCS_All(); +var str="
    \n"; +if(document.getElementById){ +if(this.config.useCookies){ +this.selectedNode=this.getSelected(); +} +str+=this.addNode(this.root); +}else{ +str+="Browser not supported."; +} +str+="
    "; +if(!this.selectedFound){ +this.selectedNode=null; +} +this.completed=true; +return str; +}; +dTree.prototype.addNode=function(_16){ +var str=""; +var n=0; +if(this.config.inOrder){ +n=_16._ai; +} +for(n;n"+this.indent(_1a,_1b); +if(this.config.useIcons){ +if(!_1a.icon){ +_1a.icon=(this.root.id==_1a.pid)?this.icon.root:((_1a._hc)?this.icon.folder:this.icon.node); +} +if(!_1a.iconOpen){ +_1a.iconOpen=(_1a._hc)?this.icon.folderOpen:this.icon.node; +} +if(this.root.id==_1a.pid){ +_1a.icon=this.icon.root; +_1a.iconOpen=this.icon.root; +} +str+="\"\""; +} +if(_1a.url){ +str+=""; +} +} +str+=_1a.name; +if(_1a.url||((!this.config.folderLinks||!_1a.url)&&_1a._hc)){ +str+=""; +} +str+="
    "; +if(_1a._hc){ +str+="
    "; +str+=this.addNode(_1a); +str+="
    "; +} +this.aIndent.pop(); +return str; +}; +dTree.prototype.indent=function(_1d,_1e){ +var str=""; +if(this.root.id!=_1d.pid){ +for(var n=0;n"; +} +(_1d._ls)?this.aIndent.push(0):this.aIndent.push(1); +if(_1d._hc){ +str+="\"\""; +}else{ +str+="\"\""; +} +} +return str; +}; +dTree.prototype.setCS=function(_21){ +var _22; +for(var n=0;n + + + + + Destroydrop » Javascripts » Tree + + + + + + + + +

    Destroydrop » Javascripts » Tree

    + +

    Example

    + +
    + +

    open all | close all

    + + + +
    + +

    ©2002-2003 Geir Landrö

    + + + + \ No newline at end of file diff --git a/xinha/plugins/Linker/dTree/img/base.gif b/xinha/plugins/Linker/dTree/img/base.gif new file mode 100644 index 0000000..5aa538c Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/base.gif differ diff --git a/xinha/plugins/Linker/dTree/img/cd.gif b/xinha/plugins/Linker/dTree/img/cd.gif new file mode 100644 index 0000000..6dfd68e Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/cd.gif differ diff --git a/xinha/plugins/Linker/dTree/img/copy.gif b/xinha/plugins/Linker/dTree/img/copy.gif new file mode 100644 index 0000000..330771c Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/copy.gif differ diff --git a/xinha/plugins/Linker/dTree/img/empty.gif b/xinha/plugins/Linker/dTree/img/empty.gif new file mode 100644 index 0000000..b5cf523 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/empty.gif differ diff --git a/xinha/plugins/Linker/dTree/img/folder.gif b/xinha/plugins/Linker/dTree/img/folder.gif new file mode 100644 index 0000000..a4e2f29 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/folder.gif differ diff --git a/xinha/plugins/Linker/dTree/img/folderopen.gif b/xinha/plugins/Linker/dTree/img/folderopen.gif new file mode 100644 index 0000000..074649b Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/folderopen.gif differ diff --git a/xinha/plugins/Linker/dTree/img/globe.gif b/xinha/plugins/Linker/dTree/img/globe.gif new file mode 100644 index 0000000..f00ef00 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/globe.gif differ diff --git a/xinha/plugins/Linker/dTree/img/imgfolder.gif b/xinha/plugins/Linker/dTree/img/imgfolder.gif new file mode 100644 index 0000000..7906217 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/imgfolder.gif differ diff --git a/xinha/plugins/Linker/dTree/img/join.gif b/xinha/plugins/Linker/dTree/img/join.gif new file mode 100644 index 0000000..e5e2f6a Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/join.gif differ diff --git a/xinha/plugins/Linker/dTree/img/joinbottom.gif b/xinha/plugins/Linker/dTree/img/joinbottom.gif new file mode 100644 index 0000000..dd83b18 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/joinbottom.gif differ diff --git a/xinha/plugins/Linker/dTree/img/line.gif b/xinha/plugins/Linker/dTree/img/line.gif new file mode 100644 index 0000000..6dcdebe Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/line.gif differ diff --git a/xinha/plugins/Linker/dTree/img/minus.gif b/xinha/plugins/Linker/dTree/img/minus.gif new file mode 100644 index 0000000..6eb44b6 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/minus.gif differ diff --git a/xinha/plugins/Linker/dTree/img/minusbottom.gif b/xinha/plugins/Linker/dTree/img/minusbottom.gif new file mode 100644 index 0000000..1380d72 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/minusbottom.gif differ diff --git a/xinha/plugins/Linker/dTree/img/move.gif b/xinha/plugins/Linker/dTree/img/move.gif new file mode 100644 index 0000000..1aa1eab Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/move.gif differ diff --git a/xinha/plugins/Linker/dTree/img/musicfolder.gif b/xinha/plugins/Linker/dTree/img/musicfolder.gif new file mode 100644 index 0000000..5761a40 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/musicfolder.gif differ diff --git a/xinha/plugins/Linker/dTree/img/nolines_minus.gif b/xinha/plugins/Linker/dTree/img/nolines_minus.gif new file mode 100644 index 0000000..daa8c20 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/nolines_minus.gif differ diff --git a/xinha/plugins/Linker/dTree/img/nolines_plus.gif b/xinha/plugins/Linker/dTree/img/nolines_plus.gif new file mode 100644 index 0000000..3e28a7a Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/nolines_plus.gif differ diff --git a/xinha/plugins/Linker/dTree/img/offline.gif b/xinha/plugins/Linker/dTree/img/offline.gif new file mode 100644 index 0000000..23163a4 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/offline.gif differ diff --git a/xinha/plugins/Linker/dTree/img/offline.png b/xinha/plugins/Linker/dTree/img/offline.png new file mode 100644 index 0000000..bb86270 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/offline.png differ diff --git a/xinha/plugins/Linker/dTree/img/page.gif b/xinha/plugins/Linker/dTree/img/page.gif new file mode 100644 index 0000000..7c1cea6 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/page.gif differ diff --git a/xinha/plugins/Linker/dTree/img/plus.gif b/xinha/plugins/Linker/dTree/img/plus.gif new file mode 100644 index 0000000..f6c9a11 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/plus.gif differ diff --git a/xinha/plugins/Linker/dTree/img/plusbottom.gif b/xinha/plugins/Linker/dTree/img/plusbottom.gif new file mode 100644 index 0000000..c56ad93 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/plusbottom.gif differ diff --git a/xinha/plugins/Linker/dTree/img/question.gif b/xinha/plugins/Linker/dTree/img/question.gif new file mode 100644 index 0000000..5536f00 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/question.gif differ diff --git a/xinha/plugins/Linker/dTree/img/trash.gif b/xinha/plugins/Linker/dTree/img/trash.gif new file mode 100644 index 0000000..4d2fb72 Binary files /dev/null and b/xinha/plugins/Linker/dTree/img/trash.gif differ diff --git a/xinha/plugins/Linker/dialog.html b/xinha/plugins/Linker/dialog.html new file mode 100644 index 0000000..0e7dc83 --- /dev/null +++ b/xinha/plugins/Linker/dialog.html @@ -0,0 +1,107 @@ +

    Insert/Modify Link

    +
    +
    (the dTree goes in here)
    +
    +
    + + + + + + + + + + +
    Target: +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Size:x (px)
    Name:
    Menu Bar:Toolbar:
    Location Bar:Status Bar:
    Scrollbars:Resizeable:
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + +
    +
    + +
    + + + + + + +
    + +
    +
    + +
    + + + +
    +
    +
    \ No newline at end of file diff --git a/xinha/plugins/Linker/lang/de.js b/xinha/plugins/Linker/lang/de.js new file mode 100644 index 0000000..7d0619b --- /dev/null +++ b/xinha/plugins/Linker/lang/de.js @@ -0,0 +1,19 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Udo Schmal (gocher), http://www.schaffrath-neuemedien.de/, udo.schmal@t-online.de +{ + "You must select some text before making a new link.": "Sie müssen einen Text markieren um einen Link zu erstellen", + "Are you sure you wish to remove this link?": "Wollen Sie diesen Link wirklich entfernen?", + "Remove Link": "Link entfernen", + "URL Link": "URL Adresse", + "Ordinary Link": "Standard Link", + "Same Window (jump out of frames)": "Selbes Fenster (ganzer Bereich)", + "New Window": "Neues Fenster", + "Popup Window": "Pop-Up Fenster", + "Email Link": "Email Link", + "Email Address:": "Email Adresse", + "Subject:": "Betreff:", + "Message Template:": "Nachrichten Vorlage:", + "Size:": "Größe:", + "Name:": "Name:" +}; \ No newline at end of file diff --git a/xinha/plugins/Linker/lang/fr.js b/xinha/plugins/Linker/lang/fr.js new file mode 100644 index 0000000..6493e86 --- /dev/null +++ b/xinha/plugins/Linker/lang/fr.js @@ -0,0 +1,18 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "You must select some text before making a new link.": "Vous devez sélectionner un texte avant de créer un nouveau lien", + "Are you sure you wish to remove this link?": "Confirmez-vous la suppression de ce lien ?", + "Remove Link": "Supprimer", + "URL Link": "Lien URL", + "Ordinary Link": "Lien standard", + "Same Window (jump out of frames)": "Même fenêtre (sort des frames)", + "New Window": "Nouvelle fenêtre", + "Popup Window": "Fenêtre popup", + "Email Link": "Lien email", + "Email Address:": "Adresse email", + "Subject:": "Sujet", + "Message Template:": "Message", + "Size:": "Taille", + "Name:": "Nom" +}; \ No newline at end of file diff --git a/xinha/plugins/Linker/lang/ja.js b/xinha/plugins/Linker/lang/ja.js new file mode 100644 index 0000000..931d04e --- /dev/null +++ b/xinha/plugins/Linker/lang/ja.js @@ -0,0 +1,24 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "You must select some text before making a new link.": "リンクを作成するにはテキストを選択する必要があります", + "Are you sure you wish to remove this link?": "本当にこのリンクを削除しますか?", + "Remove Link": "リンク削除", + "URL Link": "URLリンク", + "Ordinary Link": "標準リンク", + "Same Window (jump out of frames)": "同一ウィンドウ (フレーム最上位)", + "New Window": "新しいウィンドウ", + "Popup Window": "ポップアップウィンドウ", + "Email Link": "Eメールリンク", + "Email Address:": "アドレス:", + "Subject:": "件名:", + "Message Template:": "本文雛形:", + "Size:": "サイズ:", + "Name:": "名前:", + "Menu Bar:": "メニュー", + "Toolbar:": "ツールバー", + "Location Bar:": "アドレスバー", + "Status Bar:": "ステータスバー", + "Scrollbars:": "スクロール", + "Resizeable:": "リサイズ" +}; \ No newline at end of file diff --git a/xinha/plugins/Linker/lang/nb.js b/xinha/plugins/Linker/lang/nb.js new file mode 100644 index 0000000..0b5ba68 --- /dev/null +++ b/xinha/plugins/Linker/lang/nb.js @@ -0,0 +1,7 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "You must select some text before making a new link.": "Du må markere tekst eller et bilde før du kan lage en lenke.", + "Are you sure you wish to remove this link?": "Er du sikker på at du vil fjerne lenken?" +}; \ No newline at end of file diff --git a/xinha/plugins/Linker/lang/pl.js b/xinha/plugins/Linker/lang/pl.js new file mode 100644 index 0000000..9e875b0 --- /dev/null +++ b/xinha/plugins/Linker/lang/pl.js @@ -0,0 +1,19 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz, http://www.eskot.krakow.pl/portfolio/, koto@webworkers.pl +{ + "You must select some text before making a new link.": "Zaznacz tekst przed dodaniem odnośnika.", + "Are you sure you wish to remove this link?": "Na pewno chcesz usunąć odnośnik?", + "Remove Link": "USUŃ ODNOŚNIK", + "URL Link": "Adres URL", + "Ordinary Link": "Zwykły odnośnik", + "Same Window (jump out of frames)": "To samo okno (wyskocz z ramek)", + "New Window": "Nowe okno", + "Popup Window": "Okienko pop-up", + "Email Link": "Link do e-maila", + "Email Address:": "Adres e-mail", + "Subject:": "Temat:", + "Message Template:": "Szablon wiadmości:", + "Size:": "Rozmiar:", + "Name:": "Nazwa:" +}; \ No newline at end of file diff --git a/xinha/plugins/Linker/linker.js b/xinha/plugins/Linker/linker.js new file mode 100644 index 0000000..641d3e0 --- /dev/null +++ b/xinha/plugins/Linker/linker.js @@ -0,0 +1,385 @@ +Linker._pluginInfo={name:"Linker",version:"1.0",developer:"James Sleeman",developer_url:"http://www.gogo.co.nz/",c_owner:"Gogo Internet Services",license:"htmlArea",sponsor:"Gogo Internet Services",sponsor_url:"http://www.gogo.co.nz/"}; +Xinha.loadStyle("dTree/dtree.css","Linker"); +Xinha.Config.prototype.Linker={"treeCaption":document.location.host,"backend":_editor_url+"plugins/Linker/scan.php","backend_data":null,"files":null}; +function Linker(_1,_2){ +this.editor=_1; +this.lConfig=_1.config.Linker; +var _3=this; +if(_1.config.btnList.createlink){ +_1.config.btnList.createlink[3]=function(e,_5,_6){ +_3._createLink(_3._getSelectedAnchor()); +}; +}else{ +_1.config.registerButton("createlink","Insert/Modify Hyperlink",[_editor_url+"images/ed_buttons_main.gif",6,1],false,function(e,_8,_9){ +_3._createLink(_3._getSelectedAnchor()); +}); +} +_1.config.addToolbarElement("createlink","createlink",0); +} +Linker.prototype._lc=function(_a){ +return Xinha._lc(_a,"Linker"); +}; +Linker.prototype._createLink=function(a){ +if(!a&&this.editor.selectionEmpty(this.editor.getSelection())){ +alert(this._lc("You must select some text before making a new link.")); +return false; +} +var _c={type:"url",href:"http://www.example.com/",target:"",p_width:"",p_height:"",p_options:["menubar=no","toolbar=yes","location=no","status=no","scrollbars=yes","resizeable=yes"],to:"alice@example.com",subject:"",body:"",anchor:""}; +if(a&&a.tagName.toLowerCase()=="a"){ +var _d=this.editor.fixRelativeLinks(a.getAttribute("href")); +var m=_d.match(/^mailto:(.*@[^?&]*)(\?(.*))?$/); +var _f=_d.match(/^#(.*)$/); +if(m){ +_c.type="mailto"; +_c.to=m[1]; +if(m[3]){ +var _10=m[3].split("&"); +for(var x=0;x<_10.length;x++){ +var j=_10[x].match(/(subject|body)=(.*)/); +if(j){ +_c[j[1]]=decodeURIComponent(j[2]); +} +} +} +}else{ +if(_f){ +_c.type="anchor"; +_c.anchor=_f[1]; +}else{ +if(a.getAttribute("onclick")){ +var m=a.getAttribute("onclick").match(/window\.open\(\s*this\.href\s*,\s*'([a-z0-9_]*)'\s*,\s*'([a-z0-9_=,]*)'\s*\)/i); +_c.href=_d?_d:""; +_c.target="popup"; +_c.p_name=m[1]; +_c.p_options=[]; +var _10=m[2].split(","); +for(var x=0;x<_10.length;x++){ +var i=_10[x].match(/(width|height)=([0-9]+)/); +if(i){ +_c["p_"+i[1]]=parseInt(i[2]); +}else{ +_c.p_options.push(_10[x]); +} +} +}else{ +_c.href=_d; +_c.target=a.target; +} +} +} +} +var _14=this; +this.a=a; +var _15=function(){ +var a=_14.a; +var _17=_14._dialog.hide(); +var atr={href:"",target:"",title:"",onclick:""}; +if(_17.type=="url"){ +if(_17.href){ +atr.href=_17.href; +atr.target=_17.target; +if(_17.target=="popup"){ +if(_17.p_width){ +_17.p_options.push("width="+_17.p_width); +} +if(_17.p_height){ +_17.p_options.push("height="+_17.p_height); +} +atr.onclick="if(window.top && window.top.Xinha){return false}window.open(this.href, '"+(_17.p_name.replace(/[^a-z0-9_]/i,"_"))+"', '"+_17.p_options.join(",")+"');return false;"; +} +} +}else{ +if(_17.type=="anchor"){ +if(_17.anchor){ +atr.href=_17.anchor.value; +} +}else{ +if(_17.to){ +atr.href="mailto:"+_17.to; +if(_17.subject){ +atr.href+="?subject="+encodeURIComponent(_17.subject); +} +if(_17.body){ +atr.href+=(_17.subject?"&":"?")+"body="+encodeURIComponent(_17.body); +} +} +} +} +if(a&&a.tagName.toLowerCase()=="a"){ +if(!atr.href){ +if(confirm(_14._dialog._lc("Are you sure you wish to remove this link?"))){ +var p=a.parentNode; +while(a.hasChildNodes()){ +p.insertBefore(a.removeChild(a.childNodes[0]),a); +} +p.removeChild(a); +_14.editor.updateToolbar(); +return; +} +}else{ +for(var i in atr){ +a.setAttribute(i,atr[i]); +} +if(Xinha.is_ie){ +if(/mailto:([^?<>]*)(\?[^<]*)?$/i.test(a.innerHTML)){ +a.innerHTML=RegExp.$1; +} +} +} +}else{ +if(!atr.href){ +return true; +} +var tmp=Xinha.uniq("http://www.example.com/Link"); +_14.editor._doc.execCommand("createlink",false,tmp); +var _1c=_14.editor._doc.getElementsByTagName("a"); +for(var i=0;i<_1c.length;i++){ +var _1d=_1c[i]; +if(_1d.href==tmp){ +if(!a){ +a=_1d; +} +for(var j in atr){ +_1d.setAttribute(j,atr[j]); +} +} +} +} +_14.editor.selectNodeContents(a); +_14.editor.updateToolbar(); +}; +this._dialog.show(_c,_15); +}; +Linker.prototype._getSelectedAnchor=function(){ +var sel=this.editor.getSelection(); +var rng=this.editor.createRange(sel); +var a=this.editor.activeElement(sel); +if(a!=null&&a.tagName.toLowerCase()=="a"){ +return a; +}else{ +a=this.editor._getFirstAncestor(sel,"a"); +if(a!=null){ +return a; +} +} +return null; +}; +Linker.prototype.onGenerateOnce=function(){ +this._dialog=new Linker.Dialog(this); +}; +Linker.Dialog_dTrees=[]; +Linker.Dialog=function(_22){ +var _23=this; +this.Dialog_nxtid=0; +this.linker=_22; +this.id={}; +this.ready=false; +this.files=false; +this.html=false; +this.dialog=false; +this._prepareDialog(); +}; +Linker.Dialog.prototype._prepareDialog=function(){ +var _24=this; +var _25=this.linker; +if(typeof dTree=="undefined"){ +Xinha._loadback(_editor_url+"plugins/Linker/dTree/dtree.js",function(){ +_24._prepareDialog(); +}); +return; +} +if(this.files==false){ +if(_25.lConfig.backend){ +Xinha._postback(_25.lConfig.backend,_25.lConfig.backend_data,function(txt){ +try{ +_24.files=eval(txt); +} +catch(Error){ +_24.files=[{url:"",title:Error.toString()}]; +} +_24._prepareDialog(); +}); +}else{ +if(_25.lConfig.files!=null){ +_24.files=_25.lConfig.files; +_24._prepareDialog(); +} +} +return; +} +var _27=this.files; +if(this.html==false){ +Xinha._getback(_editor_url+"plugins/Linker/dialog.html",function(txt){ +_24.html=txt; +_24._prepareDialog(); +}); +return; +} +var _29=this.html; +var _2a=this.dialog=new Xinha.Dialog(_25.editor,this.html,"Linker"); +var _2b=Xinha.uniq("dTree_"); +this.dTree=new dTree(_2b,_editor_url+"plugins/Linker/dTree/"); +eval(_2b+" = this.dTree"); +this.dTree.add(this.Dialog_nxtid++,-1,_25.lConfig.treeCaption,null,_25.lConfig.treeCaption); +this.makeNodes(_27,0); +var _2c=this.dialog.getElementById("dTree"); +_2c.innerHTML=""; +_2c.style.position="absolute"; +_2c.style.left=1+"px"; +_2c.style.top=0+"px"; +_2c.style.overflow="auto"; +_2c.style.backgroundColor="white"; +this.ddTree=_2c; +this.dTree._linker_premade=this.dTree.toString(); +var _2d=this.dialog.getElementById("options"); +_2d.style.position="absolute"; +_2d.style.top=0+"px"; +_2d.style.right=0+"px"; +_2d.style.width=320+"px"; +_2d.style.overflow="auto"; +this.dialog.onresize=function(){ +var h=parseInt(_2a.height)-_2a.getElementById("h1").offsetHeight; +var w=parseInt(_2a.width)-322; +if(w<0){ +w=0; +} +if(h<0){ +h=0; +} +_2d.style.height=_2c.style.height=h+"px"; +_2c.style.width=w+"px"; +}; +this.ready=true; +}; +Linker.Dialog.prototype.makeNodes=function(_30,_31){ +for(var i=0;i<_30.length;i++){ +if(typeof _30[i]=="string"){ +this.dTree.add(Linker.nxtid++,_31,_30[i].replace(/^.*\//,""),"javascript:document.getElementsByName('"+this.dialog.id.href+"')[0].value=decodeURIComponent('"+encodeURIComponent(_30[i])+"');document.getElementsByName('"+this.dialog.id.type+"')[0].click();document.getElementsByName('"+this.dialog.id.href+"')[0].focus();void(0);",_30[i]); +}else{ +if(_30[i].length){ +var id=this.Dialog_nxtid++; +this.dTree.add(id,_31,_30[i][0].replace(/^.*\//,""),null,_30[i][0]); +this.makeNodes(_30[i][1],id); +}else{ +if(typeof _30[i]=="object"){ +if(_30[i].children){ +var id=this.Dialog_nxtid++; +}else{ +var id=Linker.nxtid++; +} +if(_30[i].title){ +var _34=_30[i].title; +}else{ +if(_30[i].url){ +var _34=_30[i].url.replace(/^.*\//,""); +}else{ +var _34="no title defined"; +} +} +if(_30[i].url){ +var _35="javascript:document.getElementsByName('"+this.dialog.id.href+"')[0].value=decodeURIComponent('"+encodeURIComponent(_30[i].url)+"');document.getElementsByName('"+this.dialog.id.type+"')[0].click();document.getElementsByName('"+this.dialog.id.href+"')[0].focus();void(0);"; +}else{ +var _35=""; +} +this.dTree.add(id,_31,_34,_35,_34); +if(_30[i].children){ +this.makeNodes(_30[i].children,id); +} +} +} +} +} +}; +Linker.Dialog.prototype._lc=Linker.prototype._lc; +Linker.Dialog.prototype.show=function(_36,ok,_38){ +if(!this.ready){ +var _39=this; +window.setTimeout(function(){ +_39.show(_36,ok,_38); +},100); +return; +} +if(this.ddTree.innerHTML==""){ +this.ddTree.innerHTML=this.dTree._linker_premade; +} +if(_36.type=="url"){ +this.dialog.getElementById("urltable").style.display=""; +this.dialog.getElementById("mailtable").style.display="none"; +this.dialog.getElementById("anchortable").style.display="none"; +}else{ +if(_36.type=="anchor"){ +this.dialog.getElementById("urltable").style.display="none"; +this.dialog.getElementById("mailtable").style.display="none"; +this.dialog.getElementById("anchortable").style.display=""; +}else{ +this.dialog.getElementById("urltable").style.display="none"; +this.dialog.getElementById("mailtable").style.display=""; +this.dialog.getElementById("anchortable").style.display="none"; +} +} +if(_36.target=="popup"){ +this.dialog.getElementById("popuptable").style.display=""; +}else{ +this.dialog.getElementById("popuptable").style.display="none"; +} +var _3a=this.dialog.getElementById("anchor"); +for(var i=_3a.length;i>=0;i--){ +_3a[i]=null; +} +var _3c=this.linker.editor.getHTML(); +var _3d=new Array(); +var m=_3c.match(/]+name="([^"]+)"/gi); +if(m){ +for(i=0;i$url, 'children'=>$subdir); + } + } + elseif(is_file($path)) + { + if(($include && !preg_match($include, $url)) || ($exclude && preg_match($exclude, $url))) continue; + $files[] = array('url'=>$url); + } + + } + } + @closedir($dh); + return dirsort($files); + } + + function dirsort($files) + { + usort($files, 'dircomp'); + return $files; + } + + function dircomp($a, $b) + { + if(is_array($a)) $a = array_shift($a); + if(is_array($b)) $b = array_shift($b); + return strcmp(strtolower($a), strtolower($b)); + } + + echo xinha_to_js(scan($dir)); +?> diff --git a/xinha/plugins/ListType/ListType.css b/xinha/plugins/ListType/ListType.css new file mode 100644 index 0000000..8ad84b9 --- /dev/null +++ b/xinha/plugins/ListType/ListType.css @@ -0,0 +1,43 @@ +.ListType { } +.ListType a { + display:block; + float:left; + margin:2px 0 0 5px; + padding:0; + width:50px; + height:40px; + border:1px solid #9c96a5; +} +.ListType a:hover { + border:1px solid #ffd760; +} +.ListType a.active { + border:1px solid #000084; +} +.ListType a.circle { + background:url(img/circle.png); +} +.ListType a.disc { + background:url(img/disc.png); +} +.ListType a.square { + background:url(img/square.png); +} +.ListType a.decimal { + background:url(img/decimal.png); +} +.ListType a.lower-alpha { + background:url(img/lower-alpha.png); +} +.ListType a.upper-alpha { + background:url(img/upper-alpha.png); +} +.ListType a.lower-roman { + background:url(img/lower-roman.png); +} +.ListType a.upper-roman { + background:url(img/upper-roman.png); +} +.ListType a.none { + background:url(img/none.png); +} diff --git a/xinha/plugins/ListType/img/circle.png b/xinha/plugins/ListType/img/circle.png new file mode 100644 index 0000000..e8fd0b6 Binary files /dev/null and b/xinha/plugins/ListType/img/circle.png differ diff --git a/xinha/plugins/ListType/img/decimal.png b/xinha/plugins/ListType/img/decimal.png new file mode 100644 index 0000000..cda7518 Binary files /dev/null and b/xinha/plugins/ListType/img/decimal.png differ diff --git a/xinha/plugins/ListType/img/disc.png b/xinha/plugins/ListType/img/disc.png new file mode 100644 index 0000000..0dd7b62 Binary files /dev/null and b/xinha/plugins/ListType/img/disc.png differ diff --git a/xinha/plugins/ListType/img/lower-alpha.png b/xinha/plugins/ListType/img/lower-alpha.png new file mode 100644 index 0000000..1714b70 Binary files /dev/null and b/xinha/plugins/ListType/img/lower-alpha.png differ diff --git a/xinha/plugins/ListType/img/lower-roman.png b/xinha/plugins/ListType/img/lower-roman.png new file mode 100644 index 0000000..7c934ff Binary files /dev/null and b/xinha/plugins/ListType/img/lower-roman.png differ diff --git a/xinha/plugins/ListType/img/none.png b/xinha/plugins/ListType/img/none.png new file mode 100644 index 0000000..3343f3d Binary files /dev/null and b/xinha/plugins/ListType/img/none.png differ diff --git a/xinha/plugins/ListType/img/square.png b/xinha/plugins/ListType/img/square.png new file mode 100644 index 0000000..884fffc Binary files /dev/null and b/xinha/plugins/ListType/img/square.png differ diff --git a/xinha/plugins/ListType/img/upper-alpha.png b/xinha/plugins/ListType/img/upper-alpha.png new file mode 100644 index 0000000..1654508 Binary files /dev/null and b/xinha/plugins/ListType/img/upper-alpha.png differ diff --git a/xinha/plugins/ListType/img/upper-roman.png b/xinha/plugins/ListType/img/upper-roman.png new file mode 100644 index 0000000..8d08ce5 Binary files /dev/null and b/xinha/plugins/ListType/img/upper-roman.png differ diff --git a/xinha/plugins/ListType/lang/de.js b/xinha/plugins/ListType/lang/de.js new file mode 100644 index 0000000..86a1cd7 --- /dev/null +++ b/xinha/plugins/ListType/lang/de.js @@ -0,0 +1,12 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Raimund Meyer xinha@ray-of-light.org +{ + "Decimal numbers": "Zahlen", + "Lower roman numbers": "Römisch klein", + "Upper roman numbers": "Römisch groß", + "Lower latin letters": "Zeichen klein", + "Upper latin letters": "Zeichen groß", + "Lower greek letters": "Griechisch", + "Choose list style type (for ordered lists)": "Wählen Sie einen Typ für die Nummerierung aus" +}; diff --git a/xinha/plugins/ListType/lang/fr.js b/xinha/plugins/ListType/lang/fr.js new file mode 100644 index 0000000..300d92f --- /dev/null +++ b/xinha/plugins/ListType/lang/fr.js @@ -0,0 +1,11 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Decimal numbers": "Nombres décimaux", + "Lower roman numbers": "Nombres romains minuscule", + "Upper roman numbers": "Nombres romains majuscule", + "Lower latin letters": "Lettres latines minuscule", + "Upper latin letters": "Lettres latines majuscule", + "Lower greek letters": "Lettres grecques minuscule", + "Choose list style type (for ordered lists)": "Choisissez le style de liste (pour les listes ordonnées)" +}; \ No newline at end of file diff --git a/xinha/plugins/ListType/lang/ja.js b/xinha/plugins/ListType/lang/ja.js new file mode 100644 index 0000000..3d96430 --- /dev/null +++ b/xinha/plugins/ListType/lang/ja.js @@ -0,0 +1,11 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Decimal numbers": "10進数", + "Lower roman numbers": "ローマ数字(小文字)", + "Upper roman numbers": "ローマ数字(大文字)", + "Lower latin letters": "アルファベット(小文字)", + "Upper latin letters": "アルファベット(大文字)", + "Lower greek letters": "ギリシャ文字(小文字)", + "Choose list style type (for ordered lists)": "リスト形式の選択(順序付けリスト用)" +}; \ No newline at end of file diff --git a/xinha/plugins/ListType/lang/nb.js b/xinha/plugins/ListType/lang/nb.js new file mode 100644 index 0000000..3647ee6 --- /dev/null +++ b/xinha/plugins/ListType/lang/nb.js @@ -0,0 +1,12 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Decimal numbers": "Desimaltall", + "Lower roman numbers": "Lower roman numbers", + "Upper roman numbers": "Upper roman numbers", + "Lower latin letters": "Lower latin letters", + "Upper latin letters": "Upper latin letters", + "Lower greek letters": "Lower greek letters", + "Choose list style type (for ordered lists)": "Velg listetype (for nummererte lister)" +}; diff --git a/xinha/plugins/ListType/lang/nl.js b/xinha/plugins/ListType/lang/nl.js new file mode 100644 index 0000000..d5702ea --- /dev/null +++ b/xinha/plugins/ListType/lang/nl.js @@ -0,0 +1,12 @@ +// I18N constants +// LANG: "nl", ENCODING: UTF-8 +// Author: Mihai Bazon, http://dynarch.com/mishoo +{ + "Decimal numbers": "Decimale nummers", + "Lower roman numbers": "Romeinse nummers klein", + "Upper roman numbers": "Romeinse nummers groot", + "Lower latin letters": "Latijnse letters klein", + "Upper latin letters": "Latijnse letters groot", + "Lower greek letters": "Griekse letters", + "Choose list style type (for ordered lists)": "Kies stijl type (voor ordered lists)" +}; diff --git a/xinha/plugins/ListType/lang/pl.js b/xinha/plugins/ListType/lang/pl.js new file mode 100644 index 0000000..44accd1 --- /dev/null +++ b/xinha/plugins/ListType/lang/pl.js @@ -0,0 +1,12 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz, koto1sa@o2.pl, http://www.eskot.krakow.pl/portfolio +{ + "Decimal numbers": "Cyfry arabskie", + "Lower roman numbers": "Małe rzymskie", + "Upper roman numbers": "Duże rzymskie", + "Lower latin letters": "Małe litery", + "Upper latin letters": "Duże litery", + "Lower greek letters": "Małe litery greckie", + "Choose list style type (for ordered lists)": "Wybierz typ listy numerowanej" +}; diff --git a/xinha/plugins/ListType/lang/ru.js b/xinha/plugins/ListType/lang/ru.js new file mode 100644 index 0000000..337e096 --- /dev/null +++ b/xinha/plugins/ListType/lang/ru.js @@ -0,0 +1,12 @@ +// I18N constants +// LANG: "ru", ENCODING: UTF-8 +// Author: Andrei Blagorazumov, a@fnr.ru +{ + "Decimal numbers": "Десятичные числа", + "Lower roman numbers": "Строчные романские числа", + "Upper roman numbers": "Заглавные романские числа", + "Lower latin letters": "Строчные латинские символы", + "Upper latin letters": "Заглавные латинские символы", + "Lower greek letters": "Строчные греческие символы", + "Choose list style type (for ordered lists)": "Выберите стиль списков (для упорядоченных списков)" +}; \ No newline at end of file diff --git a/xinha/plugins/ListType/lang/sv.js b/xinha/plugins/ListType/lang/sv.js new file mode 100644 index 0000000..111a573 --- /dev/null +++ b/xinha/plugins/ListType/lang/sv.js @@ -0,0 +1,12 @@ +// I18N constants +// LANG: "sv" (Swedish), ENCODING: UTF-8 +// translated: Erik Dalén, +{ + "Decimal numbers": "Desimaltal", + "Lower roman numbers": "Små romerska siffror", + "Upper roman numbers": "Stora romerska siffror", + "Lower latin letters": "Små latinska bokstäver", + "Upper latin letters": "Stora latinska bokstäver", + "Lower greek letters": "Små grekiska bokstäver", + "Choose list style type (for ordered lists)": "Välj listtyp (för numrerade listor)" +}; diff --git a/xinha/plugins/ListType/list-type.js b/xinha/plugins/ListType/list-type.js new file mode 100644 index 0000000..6a36daf --- /dev/null +++ b/xinha/plugins/ListType/list-type.js @@ -0,0 +1,137 @@ +HTMLArea.loadStyle("ListType.css","ListType"); +function ListType(_1){ +this.editor=_1; +var _2=_1.config; +var _3=this; +if(_2.ListType.mode=="toolbar"){ +var _4={}; +_4[HTMLArea._lc("Decimal numbers","ListType")]="decimal"; +_4[HTMLArea._lc("Lower roman numbers","ListType")]="lower-roman"; +_4[HTMLArea._lc("Upper roman numbers","ListType")]="upper-roman"; +_4[HTMLArea._lc("Lower latin letters","ListType")]="lower-alpha"; +_4[HTMLArea._lc("Upper latin letters","ListType")]="upper-alpha"; +if(!HTMLArea.is_ie){ +_4[HTMLArea._lc("Lower greek letters","ListType")]="lower-greek"; +} +var _5={id:"listtype",tooltip:HTMLArea._lc("Choose list style type (for ordered lists)","ListType"),options:_4,action:function(_6){ +_3.onSelect(_6,this); +},refresh:function(_7){ +_3.updateValue(_7,this); +},context:"ol"}; +_2.registerDropdown(_5); +_2.addToolbarElement("listtype",["insertorderedlist","orderedlist"],1); +}else{ +_1._ListType=_1.addPanel("right"); +HTMLArea.freeLater(_1,"_ListType"); +HTMLArea.addClass(_1._ListType,"ListType"); +HTMLArea.addClass(_1._ListType.parentNode,"dialog"); +_1.notifyOn("modechange",function(e,_9){ +if(_9.mode=="text"){ +_1.hidePanel(_1._ListType); +} +}); +var _a=["disc","circle","square","none"]; +var _b=["decimal","lower-alpha","upper-alpha","lower-roman","upper-roman","none"]; +var _c=document.createElement("div"); +_c.style.height="90px"; +var _d=document.createElement("div"); +_d.id="LTdivUL"; +_d.style.display="none"; +for(var i=0;i<_a.length;i++){ +_d.appendChild(this.createImage(_a[i])); +} +_c.appendChild(_d); +var _d=document.createElement("div"); +_d.id="LTdivOL"; +_d.style.display="none"; +for(var i=0;i<_b.length;i++){ +_d.appendChild(this.createImage(_b[i])); +} +_c.appendChild(_d); +_1._ListType.appendChild(_c); +_1.hidePanel(_1._ListType); +} +} +HTMLArea.Config.prototype.ListType={"mode":"toolbar"}; +ListType._pluginInfo={name:"ListType",version:"2.1",developer:"Laurent Vilday",developer_url:"http://www.mokhet.com/",c_owner:"Xinha community",sponsor:"",sponsor_url:"",license:"Creative Commons Attribution-ShareAlike License"}; +ListType.prototype.onSelect=function(_f,_10){ +var _11=_f._toolbarObjects[_10.id].element; +var _12=_f.getParentElement(); +while(!/^ol$/i.test(_12.tagName)){ +_12=_12.parentNode; +} +_12.style.listStyleType=_11.value; +}; +ListType.prototype.updateValue=function(_13,_14){ +var _15=_13._toolbarObjects[_14.id].element; +var _16=_13.getParentElement(); +while(_16&&!/^ol$/i.test(_16.tagName)){ +_16=_16.parentNode; +} +if(!_16){ +_15.selectedIndex=0; +return; +} +var _17=_16.style.listStyleType; +if(!_17){ +_15.selectedIndex=0; +}else{ +for(var i=_15.firstChild;i;i=i.nextSibling){ +i.selected=(_17.indexOf(i.value)!=-1); +} +} +}; +ListType.prototype.onUpdateToolbar=function(){ +if(this.editor.config.ListType.mode=="toolbar"){ +return; +} +var _19=this.editor.getParentElement(); +while(_19&&!/^[o|u]l$/i.test(_19.tagName)){ +_19=_19.parentNode; +} +if(_19&&/^[o|u]l$/i.test(_19.tagName)){ +this.showPanel(_19); +}else{ +if(this.editor._ListType.style.display!="none"){ +this.editor.hidePanel(this.editor._ListType); +} +} +}; +ListType.prototype.createImage=function(_1a){ +var _1b=this; +var _1c=this.editor; +var a=document.createElement("a"); +a.href="javascript:void(0)"; +HTMLArea._addClass(a,_1a); +HTMLArea._addEvent(a,"click",function(){ +var _1e=_1c._ListType.currentListTypeParent; +_1e.style.listStyleType=_1a; +_1b.showActive(_1e); +return false; +}); +return a; +}; +ListType.prototype.showActive=function(_1f){ +var _20=document.getElementById((_1f.tagName.toLowerCase()=="ul")?"LTdivUL":"LTdivOL"); +document.getElementById("LTdivUL").style.display="none"; +document.getElementById("LTdivOL").style.display="none"; +_20.style.display="block"; +var _21=_1f.style.listStyleType; +if(""==_21){ +_21=(_1f.tagName.toLowerCase()=="ul")?"disc":"decimal"; +} +for(var i=0;i<_20.childNodes.length;i++){ +var elt=_20.childNodes[i]; +if(HTMLArea._hasClass(elt,_21)){ +HTMLArea._addClass(elt,"active"); +}else{ +HTMLArea._removeClass(elt,"active"); +} +} +}; +ListType.prototype.showPanel=function(_24){ +this.editor._ListType.currentListTypeParent=_24; +this.showActive(_24); +this.editor.showPanel(this.editor._ListType); +}; + diff --git a/xinha/plugins/QuickTag/img/ed_quicktag.gif b/xinha/plugins/QuickTag/img/ed_quicktag.gif new file mode 100644 index 0000000..2ae5ce5 Binary files /dev/null and b/xinha/plugins/QuickTag/img/ed_quicktag.gif differ diff --git a/xinha/plugins/QuickTag/lang/de.js b/xinha/plugins/QuickTag/lang/de.js new file mode 100644 index 0000000..197c6aa --- /dev/null +++ b/xinha/plugins/QuickTag/lang/de.js @@ -0,0 +1,16 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +{ + "Quick Tag Editor": "Quick TAG Editor", + "Enter the TAG you want to insert": "Enter the TAG you want to insert", + "You have to select some text": "You have to select some text", + "There are some unclosed quote": "There are some unclosed quote", + "This attribute already exists in the TAG": "This attribute already exists in the TAG", + "No CSS class avaiable": "No CSS classes avaiable", + "OPTIONS": "OPTIONS", + "ATTRIBUTES": "ATTRIBUTES", + "TAGs": "TAGs", + "Colors": "Colors", + "Ok": "Ok", + "Cancel": "Cancel" +}; diff --git a/xinha/plugins/QuickTag/lang/fr.js b/xinha/plugins/QuickTag/lang/fr.js new file mode 100644 index 0000000..b4b2d54 --- /dev/null +++ b/xinha/plugins/QuickTag/lang/fr.js @@ -0,0 +1,16 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Quick Tag Editor": "Editeur rapide de balise", + "Enter the TAG you want to insert": "Entrez la balise que vous voulez insérer", + "You have to select some text": "Vous devez sélectionner du texte", + "There are some unclosed quote": "Il y a des apostrophes mal fermées", + "This attribute already exists in the TAG": "Cet attribute existe déjà sur cette balise", + "No CSS class avaiable": "Pas de classe CSS accessible", + "OPTIONS": "OPTIONS", + "ATTRIBUTES": "ATTRIBUTS", + "TAGs": "Balises", + "Colors": "Couleurs", + "Ok": "OK", + "Cancel": "Annuler" +}; \ No newline at end of file diff --git a/xinha/plugins/QuickTag/lang/ja.js b/xinha/plugins/QuickTag/lang/ja.js new file mode 100644 index 0000000..45d1e6c --- /dev/null +++ b/xinha/plugins/QuickTag/lang/ja.js @@ -0,0 +1,16 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Quick Tag Editor": "クイックタグエディタ", + "Enter the TAG you want to insert": "挿入したいタグを入力", + "You have to select some text": "テキストを選択しなければなりません", + "There are some unclosed quote": "閉じていない引用符があります", + "This attribute already exists in the TAG": "タグにはすでに同じ属性があります", + "No CSS class avaiable": "CSSクラスがありません", + "OPTIONS": "選択肢", + "ATTRIBUTES": "属性", + "TAGs": "タグ", + "Colors": "色", + "Ok": "OK", + "Cancel": "中止" +}; \ No newline at end of file diff --git a/xinha/plugins/QuickTag/lang/nb.js b/xinha/plugins/QuickTag/lang/nb.js new file mode 100644 index 0000000..c9819b0 --- /dev/null +++ b/xinha/plugins/QuickTag/lang/nb.js @@ -0,0 +1,17 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Quick Tag Editor": "Kjapp TAGG-Editor", + "Enter the TAG you want to insert": "Skriv inn taggen du vil ønsker å sette inn", + "You have to select some text": "Du må velge noe tekst", + "There are some unclosed quote": "Det mangler et hermetegn", + "This attribute already exists in the TAG": "Denne attributten eksisterer allerede i taggen", + "No CSS class avaiable": "Ingen CSS klasse tilgjengelig", + "OPTIONS": "EGENSKAPER", + "ATTRIBUTES": "ATTRIBUTTER", + "TAGs": "TAGGer", + "Colors": "Farger", + "Ok": "OK", + "Cancel": "Avbryt" +}; \ No newline at end of file diff --git a/xinha/plugins/QuickTag/lang/pl.js b/xinha/plugins/QuickTag/lang/pl.js new file mode 100644 index 0000000..fa5d68d --- /dev/null +++ b/xinha/plugins/QuickTag/lang/pl.js @@ -0,0 +1,17 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz, http://www.eskot.krakow.pl/portfolio/, koto@webworkers.pl +{ + "Quick Tag Editor": "Edytor Quick Tag", + "Enter the TAG you want to insert": "Podaj TAG, który chcesz wstawić", + "You have to select some text": "Musisz zaznaczyć tekst.", + "There are some unclosed quote": "Są jakieś niezamknięte cudzysłowia", + "This attribute already exists in the TAG": "TAG posiada już ten atrybut", + "No CSS class avaiable": "Brak dostępnych klas CSS", + "OPTIONS": "OPCJE", + "ATTRIBUTES": "ATRYBUTY", + "TAGs": "TAGi", + "Colors": "Kolory", + "Ok": "Ok", + "Cancel": "Anuluj" +}; diff --git a/xinha/plugins/QuickTag/lang/pt_br.js b/xinha/plugins/QuickTag/lang/pt_br.js new file mode 100644 index 0000000..30f55f0 --- /dev/null +++ b/xinha/plugins/QuickTag/lang/pt_br.js @@ -0,0 +1,16 @@ +// I18N constants +// LANG: "pt_br", ENCODING: UTF-8 +{ + "Quick Tag Editor": "Editor Rápido", + "Enter the TAG you want to insert": "Edite a TAG que deseja inserir", + "You have to select some text": "É preciso selecionar algum texto", + "No CSS class avaiable": "Não há classes CSS", + "There are some unclosed quote...": "Há uma ou mais aspas sem fechamento", + "This attribute already exists in the TAG": "Esse atributo já existe na TAG", + "OPTIONS": "OPÇÕES", + "ATTRIBUTES": "ATRIBUTOS", + "TAGs": "TAGs", + "Colors": "Cores", + "Ok": "Ok", + "Cancel": "Cancelar" +}; diff --git a/xinha/plugins/QuickTag/popups/quicktag.html b/xinha/plugins/QuickTag/popups/quicktag.html new file mode 100644 index 0000000..5ee1143 --- /dev/null +++ b/xinha/plugins/QuickTag/popups/quicktag.html @@ -0,0 +1,354 @@ + + +Quick Tag Editor + + + + + + +
    +
    Quick Tag Editor
    +
    + + + + + + +
    + < + + > +
    +
    +
    +
    + + + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/xinha/plugins/QuickTag/quick-tag.js b/xinha/plugins/QuickTag/quick-tag.js new file mode 100644 index 0000000..bd9859d --- /dev/null +++ b/xinha/plugins/QuickTag/quick-tag.js @@ -0,0 +1,53 @@ +/*---------------------------------------*\ + Quick Tag Editor Plugin for HTMLArea-3.0 + ----------------------------------------- + author: Cau guanabara + e-mail: caugb@ibest.com.br +\*---------------------------------------*/ + +function QuickTag(editor) { + var cfg = editor.config; + var self = this; + + cfg.registerButton({ + id : "quickeditor", + tooltip : this._lc("Quick Tag Editor"), + image : editor.imgURL("ed_quicktag.gif", "QuickTag"), + textMode : false, + action : function(editor) { + self.buttonPress(editor); + } + }); + cfg.addToolbarElement("quickeditor", "htmlmode", 1); +} + +QuickTag.prototype.buttonPress = function(editor) { +var self = this; +var sel = editor.getSelectedHTML().replace(/(<[^>]*>| |\n|\r)/g,""); +var param = new Object(); +param.editor = editor; + + if(/\w/.test(sel)) + editor._popupDialog("plugin://QuickTag/quicktag", function(p) { self.setTag(editor, p); }, param); + else + alert(this._lc('You have to select some text')); +}; + +QuickTag.prototype.setTag = function(editor, param) { +editor.surroundHTML(param.tagopen,param.tagclose); +}; + +QuickTag._pluginInfo = { +name : "QuickTag", +version : "1.0 - beta", +developer : "Cau Guanabara", +developer_url : "mailto:caugb@ibest.com.br", +c_owner : "Cau Guanabara", +sponsor : "Independent production", +sponsor_url : "http://www.netflash.com.br/gb/HA3-rc1/examples/quick-tag.html", +license : "htmlArea" +}; + +QuickTag.prototype._lc = function(string) { + return HTMLArea._lc(string, 'QuickTag'); +}; \ No newline at end of file diff --git a/xinha/plugins/QuickTag/tag-lib.js b/xinha/plugins/QuickTag/tag-lib.js new file mode 100644 index 0000000..fb4afa4 --- /dev/null +++ b/xinha/plugins/QuickTag/tag-lib.js @@ -0,0 +1,27 @@ +var allTags={"a":"a","a (full)":"a href=\"\" target=\"\"","address":"address","b":"b","big":"big","blockquote":"blockquote","code":"code","div":"div","em":"em","fieldset":"fieldset","font":"font","font (full)":"font face=\"\" size=\"\" color=\"\"","h1":"h1","h2":"h2","h3":"h3","h4":"h4","h5":"h5","h6":"h6","i":"i","legend":"legend","li":"li","ol":"ol","ul":"ul","p":"p","pre":"pre","small":"small","span":"span","strong":"strong","sub":"sub","sup":"sup","table":"table"}; +var tagLib={"a":true,"div":true,"font":true,"h1":true,"h2":true,"h3":true,"h4":true,"h5":true,"h6":true,"p":true,"table":true}; +var subTagLib={"table":{"op":"","cl":""}}; +var opTag_a={"href":"href=\"","name":"name=\"","target":"target=\""}; +var opAtt_a={"href":{"http://":"http://","https://":"https://","ftp://":"ftp://","mailto:":"mailto:","#":"#\""},"target":{"_top":"_top\"","_self":"_self\"","_parent":"_parent\"","_blank":"_blank\""}}; +var opTag_font={"face":"face=\"","size":"size=\"","color":"color=\""}; +var opAtt_font={"face":{"Verdana":"Verdana\"","Arial":"Arial\"","Tahoma":"Tahoma\"","Courier New":"Courier New\"","Times New Roman":"Times New Roman\""},"size":{"1":"1\"","2":"2\"","3":"3\"","4":"4\"","5":"5\"","6":"6\"","+1":"+1\"","+2":"+2\"","+3":"+3\"","+4":"+4\"","+5":"+5\"","+6":"+6\"","-1":"-1\"","-2":"-2\"","-3":"-3\"","-4":"-4\"","-5":"-5\"","-6":"-6\""}}; +var opTag_div={"align":"align=\""}; +var opAtt_div={"align":{"center":"center\"","left":"left\"","right":"right\"","justify":"justify\""}}; +var opTag_h={"align":"align=\""}; +var opAtt_h={"align":{"center":"center\"","left":"left\"","right":"right\"","justify":"justify\""}}; +var opTag_p={"align":"align=\""}; +var opAtt_p={"align":{"center":"center\"","left":"left\"","right":"right\"","justify":"justify\""}}; +var opTag_table={"align":"align=\"","width":"width=\"","height":"height=\"","cellpadding":"cellpadding=\"","cellspacing":"cellspacing=\"","background":"background=\"","bgcolor":"bgcolor=\"","border":"border=\"","bordercolor":"bordercolor=\"","bordercolorlight":"bordercolorlight=\"","bordercolordark":"bordercolordark=\""}; +var opAtt_table={"align":{"center":"center\"","left":"left\"","right":"right\""}}; +var opTag_all={"class":"class=\"","dir":"dir=\"","id":"id=\"","lang":"lang=\"","onFocus":"onFocus=\"","onBlur":"onBlur=\"","onClick":"onClick=\"","onDblClick":"onDblClick=\"","onMouseDown":"onMouseDown=\"","onMouseUp":"onMouseUp=\"","onMouseOver":"onMouseOver=\"","onMouseMove":"onMouseMove=\"","onMouseOut":"onMouseOut=\"","onKeyPress":"onKeyPress=\"","onKeyDown":"onKeyDown=\"","onKeyUp":"onKeyUp=\"","style":"style=\"","title":"title=\""}; +var opAtt_all={"class":{},"dir":{"rtl":"rtl\"","ltr":"ltr\""},"lang":{"Afrikaans ":"af\"","Albanian ":"sq\"","Arabic ":"ar\"","Basque ":"eu\"","Breton ":"br\"","Bulgarian ":"bg\"","Belarusian ":"be\"","Catalan ":"ca\"","Chinese ":"zh\"","Croatian ":"hr\"","Czech ":"cs\"","Danish ":"da\"","Dutch ":"nl\"","English ":"en\"","Estonian ":"et\"","Faeroese ":"fo\"","Farsi ":"fa\"","Finnish ":"fi\"","French ":"fr\"","Gaelic ":"gd\"","German ":"de\"","Greek ":"el\"","Hebrew ":"he\"","Hindi ":"hi\"","Hungarian ":"hu\"","Icelandic ":"is\"","Indonesian ":"id\"","Italian ":"it\"","Japanese ":"ja\"","Korean ":"ko\"","Latvian ":"lv\"","Lithuanian ":"lt\"","Macedonian ":"mk\"","Malaysian ":"ms\"","Maltese ":"mt\"","Norwegian ":"no\"","Polish ":"pl\"","Portuguese ":"pt\"","Rhaeto-Romanic ":"rm\"","Romanian ":"ro\"","Russian ":"ru\"","Sami ":"sz\"","Serbian ":"sr\"","Setswana ":"tn\"","Slovak ":"sk\"","Slovenian ":"sl\"","Spanish ":"es\"","Sutu ":"sx\"","Swedish ":"sv\"","Thai ":"th\"","Tsonga ":"ts\"","Turkish ":"tr\"","Ukrainian ":"uk\"","Urdu ":"ur\"","Vietnamese ":"vi\"","Xhosa ":"xh\"","Yiddish ":"yi\"","Zulu":"zu\""},"style":{"azimuth":"azimuth: ","background":"background: ","background-attachment":"background-attachment: ","background-color":"background-color: ","background-image":"background-image: ","background-position":"background-position: ","background-repeat":"background-repeat: ","border":"border: ","border-bottom":"border-bottom: ","border-left":"border-left: ","border-right":"border-right: ","border-top":"border-top: ","border-bottom-color":"border-bottom-color: ","border-left-color":"border-left-color: ","border-right-color":"border-right-color: ","border-top-color":"border-top-color: ","border-bottom-style":"border-bottom-style: ","border-left-style":"border-left-style: ","border-right-style":"border-right-style: ","border-top-style":"border-top-style: ","border-bottom-width":"border-bottom-width: ","border-left-width":"border-left-width: ","border-right-width":"border-right-width: ","border-top-width":"border-top-width: ","border-collapse":"border-collapse: ","border-color":"border-color: ","border-style":"border-style: ","border-width":"border-width: ","bottom":"bottom: ","caption-side":"caption-side: ","cell-spacing":"cell-spacing: ","clear":"clear: ","clip":"clip: ","color":"color: ","column-span":"column-span: ","content":"content: ","cue":"cue: ","cue-after":"cue-after: ","cue-before":"cue-before: ","cursor":"cursor: ","direction":"direction: ","display":"display: ","elevation":"elevation: ","filter":"filter: ","float":"float: ","font-family":"font-family: ","font-size":"font-size: ","font-size-adjust":"font-size-adjust: ","font-style":"font-style: ","font-variant":"font-variant: ","font-weight":"font-weight: ","height":"height: ","!important":"!important: ","left":"left: ","letter-spacing":"letter-spacing: ","line-height":"line-height: ","list-style":"list-style: ","list-style-image":"list-style-image: ","list-style-position":"list-style-position: ","list-style-type":"list-style-type: ","margin":"margin: ","margin-bottom":"margin-bottom: ","margin-left":"margin-left: ","margin-right":"margin-right: ","margin-top":"margin-top: ","marks":"marks: ","max-height":"max-height: ","min-height":"min-height: ","max-width":"max-width: ","min-width":"min-width: ","orphans":"orphans: ","overflow":"overflow: ","padding":"padding: ","padding-bottom":"padding-bottom: ","padding-left":"padding-left: ","padding-right":"padding-right: ","padding-top":"padding-top: ","page-break-after":"page-break-after: ","page-break-before":"page-break-before: ","pause":"pause: ","pause-after":"pause-after: ","pause-before":"pause-before: ","pitch":"pitch: ","pitch-range":"pitch-range: ","play-during":"play-during: ","position":"position: ","richness":"richness: ","right":"right: ","row-span":"row-span: ","size":"size: ","speak":"speak: ","speak-date":"speak-date: ","speak-header":"speak-header: ","speak-numeral":"speak-numeral: ","speak-punctuation":"speak-punctuation: ","speak-time":"speak-time: ","speech-rate":"speech-rate: ","stress":"stress: ","table-layout":"table-layout: ","text-align":"text-align: ","text-decoration":"text-decoration: ","text-indent":"text-indent: ","text-shadow":"text-shadow: ","text-transform":"text-transform: ","top":"top: ","vertical-align":"vertical-align: ","visibility":"visibility: ","voice-family":"voice-family: ","volume":"volume: ","white-space":"white-space: ","widows":"widows: ","width":"width: ","word-spacing":"word-spacing: ","z-index":"z-index: "}}; +for(var i in tagLib){ +i=i.replace(/^h[1-6]$/,"h"); +for(var j in opTag_all){ +eval("opTag_"+i+"[\""+j+"\"] = opTag_all[\""+j+"\"];"); +} +for(var j in opAtt_all){ +eval("opAtt_"+i+"[\""+j+"\"] = opAtt_all[\""+j+"\"];"); +} +} + diff --git a/xinha/plugins/SpellChecker/README b/xinha/plugins/SpellChecker/README new file mode 100644 index 0000000..9b5a2c8 --- /dev/null +++ b/xinha/plugins/SpellChecker/README @@ -0,0 +1,8 @@ +ExecCGI Note: +If you intend to use the perl (.cgi) backend then you will need to have the ExecCGI option enabled for this directory (if you are using Apache), you may be able to do this by adding a file called .htaccess in this directory, with the below contents. + +## EXAMPLE .htaccess +Options +ExecCGI +#################### + +It is however recommended that you use the PHP backend where possible. \ No newline at end of file diff --git a/xinha/plugins/SpellChecker/aspell_setup.php b/xinha/plugins/SpellChecker/aspell_setup.php new file mode 100644 index 0000000..6a4e286 --- /dev/null +++ b/xinha/plugins/SpellChecker/aspell_setup.php @@ -0,0 +1,123 @@ + (int)$aVer[1], 'minor' => (int)$aVer[2], 'release' => (int)@$aVer[3]); + if($aVer['major'] >= 0 && $aVer['minor'] >= 60) + { + $aspell_args .= ' -H --encoding=utf-8'; + } + elseif(preg_match('/--encoding/', shell_exec('aspell 2>&1'))) + { + $aspell_args .= ' --mode=none --add-filter=sgml --encoding=utf-8'; + } + else + { + $aspell_args .= ' --mode=none --add-filter=sgml'; + } + + // Personal dictionaries + $p_dicts_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'personal_dicts'; + + if(isset($_REQUEST['p_dicts_path']) && file_exists($_REQUEST['p_dicts_path']) && is_writable($_REQUEST['p_dicts_path'])) + { + if(!isset($_REQUEST['p_dicts_name'])) + { + if(isset($_COOKIE['SpellChecker_p_dicts_name'])) + { + $_REQUEST['p_dicts_name'] = $_COOKIE['SpellChecker_p_dicts_name']; + } + else + { + $_REQUEST['p_dicts_name'] = uniqid('dict'); + setcookie('SpellChecker_p_dicts_name', $_REQUEST['p_dicts_name'], time() + 60*60*24*365*10); + } + } + $p_dict_path = $_REQUEST['p_dicts_path'] . DIRECTORY_SEPARATOR . preg_replace('/[^a-z0-9_]/i', '', $_REQUEST['p_dicts_name']); + + if(!file_exists($p_dict_path)) + { + // since there is a single directory for all users this could end up containing + // quite a few subdirectories. To prevent a DOS situation we'll limit the + // total directories created to 2000 (arbitrary). Adjust to suit your installation. + + $count = 0; + + if( $dir = @opendir( $p_dicts_path ) ) + { + + while( FALSE !== ($file = readdir($dir)) ) + { + $count++; + } + } + + // TODO: make this a config value. + + if ( $count > 2000 ) + { + + // either very heavy use or a DOS attempt + + die(); + + } + + mkdir($p_dict_path); + chmod($p_dict_path, 02770); + } + + if(file_exists($p_dict_path) && is_writable($p_dict_path)) + { + // Good To Go! + $aspell_args .= ' --home-dir=' . $p_dict_path ; + } + } + +// as an additional precaution check the aspell_args for illegal +// characters + $aspell_args = preg_replace( "/[|><;\$]+/", '', $aspell_args ); + $aspelldictionaries = "$aspell dump dicts"; + $aspellcommand = "$aspell $aspell_args < $temptext"; + + +?> diff --git a/xinha/plugins/SpellChecker/img/he-spell-check.gif b/xinha/plugins/SpellChecker/img/he-spell-check.gif new file mode 100644 index 0000000..8015d2f Binary files /dev/null and b/xinha/plugins/SpellChecker/img/he-spell-check.gif differ diff --git a/xinha/plugins/SpellChecker/img/spell-check.gif b/xinha/plugins/SpellChecker/img/spell-check.gif new file mode 100644 index 0000000..fce009a Binary files /dev/null and b/xinha/plugins/SpellChecker/img/spell-check.gif differ diff --git a/xinha/plugins/SpellChecker/lang/cz.js b/xinha/plugins/SpellChecker/lang/cz.js new file mode 100644 index 0000000..483289c --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/cz.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "cz", ENCODING: UTF-8 +// Author: Jiri Löw, +{ + "Please confirm that you want to open this link": "Prosím potvrďte otevření tohoto odkazu", + "Cancel": "Zrušit", + "Dictionary": "Slovník", + "Finished list of mispelled words": "Dokončen seznam chybných slov", + "I will open it in a new page.": "Bude otevřen jej v nové stránce.", + "Ignore all": "Ignorovat vše", + "Ignore": "Ignorovat", + "No mispelled words found with the selected dictionary.": "Podle zvoleného slovníku nebyla nalezena žádná chybná slova.", + "Spell check complete, didn't find any mispelled words. Closing now...": "Kontrola správnosti slov dokončena, nebyla nalezena žádná chybná slova. Ukončování ...", + "OK": "OK", + "Original word": "Původní slovo", + "Please wait. Calling spell checker.": "Prosím čekejte. Komunikuace s kontrolou správnosti slov.", + "Please wait: changing dictionary to": "Prosím čekejte: změna adresáře na", + "This will drop changes and quit spell checker. Please confirm.": "Změny budou zrušeny a kontrola správnosti slov ukončena. Prosím potvrďte.", + "Re-check": "Překontrolovat", + "Replace all": "Zaměnit všechno", + "Replace with": "Zaměnit za", + "Replace": "Zaměnit", + "Spell-check": "Kontrola správnosti slov", + "Suggestions": "Doporučení", + "One moment...": "strpení prosím ;-)" +}; diff --git a/xinha/plugins/SpellChecker/lang/da.js b/xinha/plugins/SpellChecker/lang/da.js new file mode 100644 index 0000000..60697f4 --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/da.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "da", ENCODING: UTF-8 +// Author: Steen SÞnderup, +{ + "Please confirm that you want to open this link": "Vil du fÞlge dette link?", + "Cancel": "Anuler", + "Dictionary": "Ordbog", + "Finished list of mispelled words": "Listen med stavefejl er gennemgÃ¥et", + "I will open it in a new page.": "Jeg vil Ã¥bne det i en ny side.", + "Ignore all": "Ignorer alle", + "Ignore": "Ignorer", + "No mispelled words found with the selected dictionary.": "Der blev ikke fundet nogle stavefejl med den valgte ordbog.", + "Spell check complete, didn't find any mispelled words. Closing now...": "Stavekontrollen er gennemfÞrt, der blev ikke fundet nogle stavefejl. Lukker...", + "OK": "OK", + "Original word": "Oprindeligt ord", + "Please wait. Calling spell checker.": "Vent venligst. Henter stavekontrol.", + "Please wait: changing dictionary to": "Vent venligst: skifter ordbog til", + "This will drop changes and quit spell checker. Please confirm.": "Alle dine Êndringer vil gÃ¥ tabt, vil du fortsÊtte?", + "Re-check": "Tjek igen", + "Replace all": "Erstat alle", + "Replace with": "Erstat med", + "Replace": "Erstat", + "Spell-check": "Stavekontrol", + "Suggestions": "Forslag", + "One moment...": "Vent venligst" +}; diff --git a/xinha/plugins/SpellChecker/lang/de.js b/xinha/plugins/SpellChecker/lang/de.js new file mode 100644 index 0000000..e1bd992 --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/de.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "en", ENCODING: UTF-8 +// Author: Broxx, +{ + "Please confirm that you want to open this link": "Wollen Sie diesen Link oeffnen", + "Cancel": "Abbrechen", + "Dictionary": "Woerterbuch", + "Finished list of mispelled words": "Liste der nicht bekannten Woerter", + "I will open it in a new page.": "Wird auf neuer Seite geoeffnet", + "Ignore all": "Alle ignorieren", + "Ignore": "Ignorieren", + "No mispelled words found with the selected dictionary.": "Keine falschen Woerter mit gewaehlten Woerterbuch gefunden", + "Spell check complete, didn't find any mispelled words. Closing now...": "Rechtsschreibpruefung wurde ohne Fehler fertiggestellt. Wird nun geschlossen...", + "OK": "OK", + "Original word": "Original Wort", + "Please wait. Calling spell checker.": "Bitte warten. Woerterbuch wird durchsucht.", + "Please wait: changing dictionary to": "Bitte warten: Woerterbuch wechseln zu", + "This will drop changes and quit spell checker. Please confirm.": "Aenderungen werden nicht uebernommen. Bitte bestaettigen.", + "Re-check": "Neuueberpruefung", + "Replace all": "Alle ersetzen", + "Replace with": "Ersetzen mit", + "Replace": "Ersetzen", + "Spell-check": "Ueberpruefung", + "Suggestions": "Vorschlag", + "One moment...": "Bitte warten..." +}; diff --git a/xinha/plugins/SpellChecker/lang/fr.js b/xinha/plugins/SpellChecker/lang/fr.js new file mode 100644 index 0000000..7cece8e --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/fr.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Please confirm that you want to open this link": "Veuillez confirmer l'ouverture de ce lien", + "Cancel": "Annuler", + "Dictionary": "Dictionnaire", + "Finished list of mispelled words": "Liste des mots mal orthographiés", + "I will open it in a new page.": "Ouverture dans une nouvelle fenêtre", + "Ignore all": "Tout ignorer", + "Ignore": "Ignorer", + "No mispelled words found with the selected dictionary.": "Aucune erreur orthographique avec le dictionnaire sélectionné.", + "Spell check complete, didn't find any mispelled words. Closing now...": "Vérification terminée, aucune erreur orthographique détectée. Fermeture en cours...", + "OK": "OK", + "Original word": "Mot original", + "Please wait. Calling spell checker.": "Veuillez patienter. Appel du correcteur.", + "Please wait: changing dictionary to": "Veuillez patienter. Changement du dictionnaire vers", + "This will drop changes and quit spell checker. Please confirm.": "Ceci fermera la fenêtre et annulera les modifications. Veuillez confirmer.", + "Re-check": "Vérifier encore", + "Replace all": "Tout remplacer", + "Replace with": "Remplacer par", + "Replace": "Remplacer", + "Revert": "Annuler", + "Spell-check": "Correction", + "Suggestions": "Suggestions", + "One moment...": "Veuillez patienter" +}; \ No newline at end of file diff --git a/xinha/plugins/SpellChecker/lang/he.js b/xinha/plugins/SpellChecker/lang/he.js new file mode 100644 index 0000000..aac7e1a --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/he.js @@ -0,0 +1,27 @@ +// I18N constants +// LANG: "en", ENCODING: UTF-8 +// Author: Mihai Bazon, http://dynarch.com/mishoo +{ + "Please confirm that you want to open this link": "אנא אשר שברצונך לפתוח קישור זה", + "Cancel": "ביטול", + "Dictionary": "מילון", + "Finished list of mispelled words": "הסתיימה רשימת המילים המאויתות באופן שגוי", + "I will open it in a new page.": "אני אפתח את זה בחלון חדש.", + "Ignore all": "התעלם מהכל", + "Ignore": "התעלם", + "No mispelled words found with the selected dictionary.": "לא נמצאו מילים מאויתות באופן שגוי עם המילון הנבחר.", + "Spell check complete, didn't find any mispelled words. Closing now...": "בדיקת האיות נסתיימה, לא נמצאו מילים מאויתות באופן שגוי. נסגר כעת...", + "OK": "אישור", + "Original word": "המילה המקורית", + "Please wait. Calling spell checker.": "אנא המתן. קורא לבודק איות.", + "Please wait: changing dictionary to": "אנא המתן: מחליף מילון ל-", + "This will drop changes and quit spell checker. Please confirm.": "זה יבטל את השינויים ויצא מבודק האיות. אנא אשר.", + "Re-check": "בדוק מחדש", + "Replace all": "החלף הכל", + "Replace with": "החלף ב-", + "Replace": "החלף", + "Revert": "החזר שינויים", + "Spell-check": "בדיקת איות", + "Suggestions": "הצעות", + "One moment...": "ענא המטן ;-)" +}; diff --git a/xinha/plugins/SpellChecker/lang/hu.js b/xinha/plugins/SpellChecker/lang/hu.js new file mode 100644 index 0000000..82db4ea --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/hu.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "hu", ENCODING: UTF-8 +// Author: Miklós Somogyi, +{ + "Please confirm that you want to open this link": "Megerősítés", + "Cancel": "Mégsem", + "Dictionary": "Szótár", + "Finished list of mispelled words": "A tévesztett szavak listájának vége", + "I will open it in a new page.": "Megnyitás új lapon", + "Ignore all": "Minden elvetése", + "Ignore": "Elvetés", + "No mispelled words found with the selected dictionary.": "A választott szótár szerint nincs tévesztett szó.", + "Spell check complete, didn't find any mispelled words. Closing now...": "A helyesírásellenőrzés kész, tévesztett szó nem fordult elő. Bezárás...", + "OK": "Rendben", + "Original word": "Eredeti szó", + "Please wait. Calling spell checker.": "Kis türelmet, a helyesírásellenőrző hívása folyamatban.", + "Please wait: changing dictionary to": "Kis türelmet, szótár cseréje", + "This will drop changes and quit spell checker. Please confirm.": "Kilépés a változások eldobásával. Jóváhagyja?", + "Re-check": "Újraellenőrzés", + "Replace all": "Mind cseréje", + "Replace with": "Csere a következőre:", + "Replace": "Csere", + "Spell-check": "Helyesírásellenőrzés", + "Suggestions": "Tippek", + "One moment...": "Kis türelmet ;-)" +}; diff --git a/xinha/plugins/SpellChecker/lang/ja.js b/xinha/plugins/SpellChecker/lang/ja.js new file mode 100644 index 0000000..5571693 --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/ja.js @@ -0,0 +1,28 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Please confirm that you want to open this link": "本当にこのリンクを開きますか", + "Cancel": "中止", + "Dictionary": "辞書", + "Finished list of mispelled words": "つづり間違単語の一覧", + "I will open it in a new page.": "新しいページで開きます。", + "Ignore all": "すべて無視", + "Ignore": "無視", + "No mispelled words found with the selected dictionary.": "選択された辞書にはつづり間違い単語がありません。", + "Spell check complete, didn't find any mispelled words. Closing now...": "スペルチェックが完了しましたが、つづり間違い単語はありませんでした。すぐに閉じます...", + "OK": "OK", + "Original word": "元の単語", + "Please wait. Calling spell checker.": "しばらくお待ちください。スペルチェッカーを呼び出しています。", + "Please wait: changing dictionary to": "しばらくお待ちください: 辞書を切り替えています", + "This will drop changes and quit spell checker. Please confirm.": "変更を破棄してスペルチェッカーを終了します。よろしいいですか。", + "Re-check": "再チェック", + "Replace all": "すべて置換", + "Replace with": "これに置換", + "Replace": "置換", + "Revert": "戻す", + "Spell-check": "スペルチェック", + "Suggestions": "候補", + "One moment...": "あともう少し...", + "Info": "情報", + "Learn": "学習" +}; \ No newline at end of file diff --git a/xinha/plugins/SpellChecker/lang/nb.js b/xinha/plugins/SpellChecker/lang/nb.js new file mode 100644 index 0000000..2a07646 --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/nb.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Please confirm that you want to open this link": "Ønsker du å åpne denne lenken", + "Cancel": "Avbryt", + "Dictionary": "Ordliste", + "Finished list of mispelled words": "Ferdig med liste over feilstavede ord", + "I will open it in a new page.": "Åpnes i ny side", + "Ignore all": "Ignorer alle", + "Ignore": "Ignorer", + "No mispelled words found with the selected dictionary.": "Ingen feilstavede ord funnet med den valgte ordlisten", + "Spell check complete, didn't find any mispelled words. Closing now...": "Stavekontroll fullført, ingen feilstavede ord ble funnet, stavekontroll avsluttes.", + "OK": "OK", + "Original word": "Opprinnelig ord", + "Please wait. Calling spell checker.": "Vennligst vent, kaller opp stavekontrollprogrammet", + "Please wait: changing dictionary to": "Vennligst vent, endrer ordliste til", + "This will drop changes and quit spell checker. Please confirm.": "Dette vil droppe endringene og avbryte stavekontrollen, vennligst bekreft.", + "Re-check": "Kjør stavekontroll på nytt", + "Replace all": "Erstatt alle", + "Replace with": "Erstatt med", + "Replace": "Erstatt", + "Spell-check": "Stavekontroll", + "Suggestions": "Forslag", + "One moment...": "Et øyeblikk..." +}; \ No newline at end of file diff --git a/xinha/plugins/SpellChecker/lang/nl.js b/xinha/plugins/SpellChecker/lang/nl.js new file mode 100644 index 0000000..42ae94f --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/nl.js @@ -0,0 +1,27 @@ +// I18N constants +// LANG: "nl", ENCODING: UTF-8 +// Author: A.H van den Broek http://www.kontaktfm.nl, tonbroek@kontaktfm.nl +{ + "Please confirm that you want to open this link": "Weet u zeker dat u deze link wilt openen?", + "Cancel": "Annuleer", + "Dictionary": "Woordenboek", + "Finished list of mispelled words": "klaar met de lijst van fouten woorden", + "I will open it in a new page.": "Ik zal het in een nieuwe pagina openen.", + "Ignore all": "alles overslaan", + "Ignore": "Overslaan", + "No mispelled words found with the selected dictionary.": "Geen fouten gevonden met dit woordenboek.", + "Spell check complete, didn't find any mispelled words. Closing now...": "Spell checking is klaar, geen fouten gevonden. spell checking word gesloten...", + "OK": "OK", + "Original word": "Originele woord", + "Please wait. Calling spell checker.": "Even wachten. spell checker wordt geladen.", + "Please wait: changing dictionary to": "even wachten: woordenboek wordt veranderd naar", + "This will drop changes and quit spell checker. Please confirm.": "Dit zal alle veranderingen annuleren en de spell checker sluiten. Weet u het zeker?", + "Re-check": "Opnieuw", + "Replace all": "Alles vervangen", + "Replace with": "Vervangen met", + "Replace": "Vervangen", + "Revert": "Omkeren", + "Spell-check": "Spell-check", + "Suggestions": "Suggestie", + "One moment...": "Even wachten ;-)" +}; diff --git a/xinha/plugins/SpellChecker/lang/ro.js b/xinha/plugins/SpellChecker/lang/ro.js new file mode 100644 index 0000000..9fe5f8a --- /dev/null +++ b/xinha/plugins/SpellChecker/lang/ro.js @@ -0,0 +1,26 @@ +// I18N constants +// LANG: "ro", ENCODING: UTF-8 +// Author: Mihai Bazon, http://dynarch.com/mishoo +{ + "Please confirm that you want to open this link": "Vă rog confirmaţi că vreţi să deschideţi acest link", + "Cancel": "Anulează", + "Dictionary": "Dicţionar", + "Finished list of mispelled words": "Am terminat lista de cuvinte greşite", + "I will open it in a new page.": "O voi deschide într-o altă fereastră.", + "Ignore all": "Ignoră toate", + "Ignore": "Ignoră", + "No mispelled words found with the selected dictionary.": "Nu am găsit nici un cuvânt greşit cu acest dicţionar.", + "Spell check complete, didn't find any mispelled words. Closing now...": "Am terminat, nu am detectat nici o greşeală. Acum închid fereastra...", + "OK": "OK", + "Original word": "Cuvântul original", + "Please wait. Calling spell checker.": "Vă rog aşteptaţi. Apelez spell-checker-ul.", + "Please wait: changing dictionary to": "Vă rog aşteptaţi. Schimb dicţionarul cu", + "This will drop changes and quit spell checker. Please confirm.": "Doriţi să renunţaţi la modificări şi să închid spell-checker-ul?", + "Re-check": "Scanează", + "Replace all": "Înlocuieşte toate", + "Replace with": "Înlocuieşte cu", + "Replace": "Înlocuieşte", + "Spell-check": "Detectează greşeli", + "Suggestions": "Sugestii", + "One moment...": "va rog ashteptatzi ;-)" +}; diff --git a/xinha/plugins/SpellChecker/readme-tech.html b/xinha/plugins/SpellChecker/readme-tech.html new file mode 100644 index 0000000..c1703ec --- /dev/null +++ b/xinha/plugins/SpellChecker/readme-tech.html @@ -0,0 +1,114 @@ + + + + HTMLArea Spell Checker + + + +

    HTMLArea Spell Checker

    + +

    The HTMLArea Spell Checker subsystem consists of the following + files:

    + +
      + +
    • spell-checker.js — the spell checker plugin interface for + HTMLArea
    • + +
    • spell-checker-ui.html — the HTML code for the user + interface
    • + +
    • spell-checker-ui.js — functionality of the user + interface
    • + +
    • spell-checker-logic.cgi — Perl CGI script that checks a text + given through POST for spelling errors
    • + +
    • spell-checker-style.css — style for mispelled words
    • + +
    • lang/en.js — main language file (English).
    • + +
    + +

    Process overview

    + +

    + When an end-user clicks the "spell-check" button in the HTMLArea + editor, a new window is opened with the URL of "spell-check-ui.html". + This window initializes itself with the text found in the editor (uses + window.opener.SpellChecker.editor global variable) and it + submits the text to the server-side script "spell-check-logic.cgi". + The target of the FORM is an inline frame which is used both to + display the text and correcting. +

    + +

    + Further, spell-check-logic.cgi calls Aspell for each portion of plain + text found in the given HTML. It rebuilds an HTML file that contains + clear marks of which words are incorrect, along with suggestions for + each of them. This file is then loaded in the inline frame. Upon + loading, a JavaScript function from "spell-check-ui.js" is called. + This function will retrieve all mispelled words from the HTML of the + iframe and will setup the user interface so that it allows correction. +

    + +

    The server-side script (spell-check-logic.cgi)

    + +

    + Unicode safety — the program is + Unicode safe. HTML entities are expanded into their corresponding + Unicode characters. These characters will be matched as part of the + word passed to Aspell. All texts passed to Aspell are in Unicode + (when appropriate). However, Aspell seems to not support Unicode + yet (thread concerning Aspell and Unicode). + This mean that words containing Unicode + characters that are not in 0..255 are likely to be reported as "mispelled" by Aspell. +

    + +

    + Update: though I've never seen it mentioned + anywhere, it looks that Aspell does, in fact, speak + Unicode. Or else, maybe Text::Aspell does + transparent conversion; anyway, this new version of our + SpellChecker plugin is, as tests show so far, fully + Unicode-safe... well, probably the only freeware + Web-based spell-checker which happens to have Unicode support. +

    + +

    + The Perl Unicode manual (man perluniintro) states: +

    + +
    + + Starting from Perl 5.6.0, Perl has had the capacity to handle Unicode + natively. Perl 5.8.0, however, is the first recommended release for + serious Unicode work. The maintenance release 5.6.1 fixed many of the + problems of the initial Unicode implementation, but for example regular + expressions still do not work with Unicode in 5.6.1. + +
    + +

    In other words, do not assume that this script is + Unicode-safe on Perl interpreters older than 5.8.0.

    + +

    The following Perl modules are required:

    + + + +

    Of these, only Text::Aspell might need to be installed manually. The + others are likely to be available by default in most Perl distributions.

    + +
    +
    Mihai Bazon
    + + Last modified: Fri Jan 30 19:14:11 EET 2004 + + + diff --git a/xinha/plugins/SpellChecker/spell-check-logic.cgi b/xinha/plugins/SpellChecker/spell-check-logic.cgi new file mode 100755 index 0000000..6c68f24 --- /dev/null +++ b/xinha/plugins/SpellChecker/spell-check-logic.cgi @@ -0,0 +1,210 @@ +#! /usr/bin/perl -w + +# Spell Checker Plugin for HTMLArea-3.0 +# Sponsored by www.americanbible.org +# Implementation by Mihai Bazon, http://dynarch.com/mishoo/ +# +# (c) dynarch.com 2003. +# Distributed under the same terms as HTMLArea itself. +# This notice MUST stay intact for use (see license.txt). +# +# $Id$ + +use strict; +use utf8; +use Encode; +use Text::Aspell; +use XML::DOM; +use CGI; + +my $TIMER_start = undef; +eval { + use Time::HiRes qw( gettimeofday tv_interval ); + $TIMER_start = [gettimeofday()]; +}; +# use POSIX qw( locale_h ); + +binmode STDIN, ':utf8'; +binmode STDOUT, ':utf8'; + +my $debug = 0; + +my $speller = new Text::Aspell; +my $cgi = new CGI; + +my $total_words = 0; +my $total_mispelled = 0; +my $total_suggestions = 0; +my $total_words_suggested = 0; + +# FIXME: report a nice error... +die "Can't create speller!" unless $speller; + +my $dict = $cgi->param('dictionary') || $cgi->cookie('dictionary') || 'en'; + +# add configurable option for this +$speller->set_option('lang', $dict); +$speller->set_option('encoding', 'UTF-8'); +#setlocale(LC_CTYPE, $dict); + +# ultra, fast, normal, bad-spellers +# bad-spellers seems to cause segmentation fault +$speller->set_option('sug-mode', 'normal'); + +my %suggested_words = (); +keys %suggested_words = 128; + +my $file_content = decode('UTF-8', $cgi->param('content')); +$file_content = parse_with_dom($file_content); + +my $ck_dictionary = $cgi->cookie(-name => 'dictionary', + -value => $dict, + -expires => '+30d'); + +print $cgi->header(-type => 'text/html; charset: utf-8', + -cookie => $ck_dictionary); + +my $js_suggested_words = make_js_hash(\%suggested_words); +my $js_spellcheck_info = make_js_hash_from_array + ([ + [ 'Total words' , $total_words ], + [ 'Mispelled words' , $total_mispelled . ' in dictionary \"'.$dict.'\"' ], + [ 'Total suggestions' , $total_suggestions ], + [ 'Total words suggested' , $total_words_suggested ], + [ 'Spell-checked in' , defined $TIMER_start ? (tv_interval($TIMER_start) . ' seconds') : 'n/a' ] + ]); + +print qq^ + + + + + + +^; + +print $file_content; +if ($cgi->param('init') eq '1') { + my @dicts = $speller->dictionary_info(); + my $dictionaries = ''; + foreach my $i (@dicts) { + next if $i->{jargon}; + my $name = $i->{name}; + if ($name eq $dict) { + $name = '@'.$name; + } + $dictionaries .= ',' . $name; + } + $dictionaries =~ s/^,//; + print qq^
    $dictionaries
    ^; +} + +print ''; + +# Perl is beautiful. +sub spellcheck { + my $node = shift; + my $doc = $node->getOwnerDocument; + my $check = sub { # called for each word in the text + # input is in UTF-8 + my $word = shift; + my $already_suggested = defined $suggested_words{$word}; + ++$total_words; + if (!$already_suggested && $speller->check($word)) { + return undef; + } else { + # we should have suggestions; give them back to browser in UTF-8 + ++$total_mispelled; + if (!$already_suggested) { + # compute suggestions for this word + my @suggestions = $speller->suggest($word); + my $suggestions = decode($speller->get_option('encoding'), join(',', @suggestions)); + $suggested_words{$word} = $suggestions; + ++$total_suggestions; + $total_words_suggested += scalar @suggestions; + } + # HA-spellcheck-error + my $err = $doc->createElement('span'); + $err->setAttribute('class', 'HA-spellcheck-error'); + my $tmp = $doc->createTextNode; + $tmp->setNodeValue($word); + $err->appendChild($tmp); + return $err; + } + }; + while ($node->getNodeValue =~ /([\p{IsWord}']+)/) { + my $word = $1; + my $before = $`; + my $after = $'; + my $df = &$check($word); + if (!$df) { + $before .= $word; + } + { + my $parent = $node->getParentNode; + my $n1 = $doc->createTextNode; + $n1->setNodeValue($before); + $parent->insertBefore($n1, $node); + $parent->insertBefore($df, $node) if $df; + $node->setNodeValue($after); + } + } +}; + +sub check_inner_text { + my $node = shift; + my $text = ''; + for (my $i = $node->getFirstChild; defined $i; $i = $i->getNextSibling) { + if ($i->getNodeType == TEXT_NODE) { + spellcheck($i); + } + } +}; + +sub parse_with_dom { + my ($text) = @_; + $text = ''.$text.''; + + my $parser = new XML::DOM::Parser; + if ($debug) { + open(FOO, '>:utf8', '/tmp/foo'); + print FOO $text; + close FOO; + } + my $doc = $parser->parse($text); + my $nodes = $doc->getElementsByTagName('*'); + my $n = $nodes->getLength; + + for (my $i = 0; $i < $n; ++$i) { + my $node = $nodes->item($i); + if ($node->getNodeType == ELEMENT_NODE) { + check_inner_text($node); + } + } + + my $ret = $doc->toString; + $ret =~ s{(.*)}{$1}sg; + return $ret; +}; + +sub make_js_hash { + my ($hash) = @_; + my $js_hash = ''; + while (my ($key, $val) = each %$hash) { + $js_hash .= ',' if $js_hash; + $js_hash .= '"'.$key.'":"'.$val.'"'; + } + return $js_hash; +}; + +sub make_js_hash_from_array { + my ($array) = @_; + my $js_hash = ''; + foreach my $i (@$array) { + $js_hash .= ',' if $js_hash; + $js_hash .= '"'.$i->[0].'":"'.$i->[1].'"'; + } + return $js_hash; +}; diff --git a/xinha/plugins/SpellChecker/spell-check-logic.php b/xinha/plugins/SpellChecker/spell-check-logic.php new file mode 100644 index 0000000..ff59463 --- /dev/null +++ b/xinha/plugins/SpellChecker/spell-check-logic.php @@ -0,0 +1,171 @@ + + + + +'; + +// Lets define some values outside the condition below, in case we have an empty +// document. +$textarray = array(); +$varlines = ''; + +echo ' +'; + +foreach ($textarray as $key=>$value) +{ + echo $value; +} + +$dictionaries = str_replace(chr(10),",", shell_exec($aspelldictionaries)); +if(ereg(",$",$dictionaries)) + $dictionaries = ereg_replace(",$","",$dictionaries); +echo '
    '.$dictionaries.'
    '; + +echo ''; +?> \ No newline at end of file diff --git a/xinha/plugins/SpellChecker/spell-check-savedicts.php b/xinha/plugins/SpellChecker/spell-check-savedicts.php new file mode 100644 index 0000000..0086165 --- /dev/null +++ b/xinha/plugins/SpellChecker/spell-check-savedicts.php @@ -0,0 +1,38 @@ +&1'); + unlink($temptext); + } +?> \ No newline at end of file diff --git a/xinha/plugins/SpellChecker/spell-check-style.css b/xinha/plugins/SpellChecker/spell-check-style.css new file mode 100644 index 0000000..1408ba0 --- /dev/null +++ b/xinha/plugins/SpellChecker/spell-check-style.css @@ -0,0 +1,10 @@ +.HA-spellcheck-error { border-bottom: 1px dashed #f00; cursor: default; } +.HA-spellcheck-same { background-color: #cef; color: #000; } +.HA-spellcheck-hover { background-color: #433; color: white; } +.HA-spellcheck-fixed { border-bottom: 1px dashed #0b8; } +.HA-spellcheck-current { background-color: #9be; color: #000; } +.HA-spellcheck-suggestions { display: none; } + +#HA-spellcheck-dictionaries { display: none; } + +a:link, a:visited { color: #55e; } diff --git a/xinha/plugins/SpellChecker/spell-check-ui.html b/xinha/plugins/SpellChecker/spell-check-ui.html new file mode 100644 index 0000000..58980df --- /dev/null +++ b/xinha/plugins/SpellChecker/spell-check-ui.html @@ -0,0 +1,125 @@ + + + + + Spell Checker + + + + + + + + + +
    + + + + + + + + + + + + + +
    +
    Dictionary + + +
    + Please wait. Calling spell checker. +
    +
    + +
    +
    Original word
    +
    pliz weit ;-)
    +
    + +
    +
    Replace with
    +
    +
    +
    +
    + +
    +
    +
    Suggestions
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    + + + + diff --git a/xinha/plugins/SpellChecker/spell-check-ui.js b/xinha/plugins/SpellChecker/spell-check-ui.js new file mode 100644 index 0000000..0a6baff --- /dev/null +++ b/xinha/plugins/SpellChecker/spell-check-ui.js @@ -0,0 +1,392 @@ +var SpellChecker=window.opener.SpellChecker; +var Xinha=window.opener.Xinha; +var HTMLArea=Xinha; +var _editor_url=window.opener._editor_url; +var is_ie=HTMLArea.is_ie; +var editor=SpellChecker.editor; +var frame=null; +var currentElement=null; +var wrongWords=null; +var modified=false; +var allWords={}; +var fixedWords=[]; +var suggested_words={}; +var to_p_dict=[]; +var to_r_list=[]; +function _lc(_1){ +return HTMLArea._lc(_1,"SpellChecker"); +} +function makeCleanDoc(_2){ +var _3=wrongWords.concat(fixedWords); +for(var i=_3.length;--i>=0;){ +var el=_3[i]; +if(!(_2&&/HA-spellcheck-fixed/.test(el.className))){ +if(el.firstChild){ +el.parentNode.insertBefore(el.firstChild,el); +} +el.parentNode.removeChild(el); +}else{ +el.className="HA-spellcheck-fixed"; +} +} +return Xinha.getHTML(frame.contentWindow.document.body,true,editor); +} +function recheckClicked(){ +document.getElementById("status").innerHTML=_lc("Please wait: changing dictionary to")+": \""+document.getElementById("f_dictionary").value+"\"."; +var _6=document.getElementById("f_content"); +_6.value=makeCleanDoc(true); +_6.form.submit(); +} +function saveClicked(){ +if(modified){ +editor.setHTML(makeCleanDoc(false)); +} +if(to_p_dict.length||to_r_list.length&&editor.config.SpellChecker.backend=="php"){ +var _7={}; +for(var i=0;i=0;){ +var el=els[j]; +if(el.childNodes.length==1&&/\S/.test(el.innerHTML)){ +var txt=el.innerHTML; +el.innerHTML=_lc(txt); +} +} +} +} +function initDocument(){ +internationalizeWindow(); +modified=false; +frame=document.getElementById("i_framecontent"); +var _1a=document.getElementById("f_content"); +_1a.value=HTMLArea.getHTML(editor._doc.body,false,editor); +var _1b=document.getElementById("f_dictionary"); +if(typeof editor.config.SpellChecker.defaultDictionary!="undefined"&&editor.config.SpellChecker.defaultDictionary!=""){ +_1b.value=editor.config.SpellChecker.defaultDictionary; +}else{ +_1b.value="en_GB"; +} +if(editor.config.SpellChecker.backend=="php"){ +_1a.form.action=_editor_url+"/plugins/SpellChecker/spell-check-logic.php"; +} +if(editor.config.SpellChecker.utf8_to_entities){ +document.getElementById("utf8_to_entities").value=1; +}else{ +document.getElementById("utf8_to_entities").value=0; +} +_1a.form.submit(); +document.getElementById("f_init").value="0"; +var _1c=document.getElementById("v_suggestions"); +_1c.onchange=function(){ +document.getElementById("v_replacement").value=this.value; +}; +if(is_ie){ +_1c.attachEvent("ondblclick",replaceClicked); +}else{ +_1c.addEventListener("dblclick",replaceClicked,true); +} +document.getElementById("b_replace").onclick=replaceClicked; +if(editor.config.SpellChecker.backend=="php"){ +document.getElementById("b_learn").onclick=learnClicked; +}else{ +document.getElementById("b_learn").parentNode.removeChild(document.getElementById("b_learn")); +} +document.getElementById("b_replall").onclick=replaceAllClicked; +document.getElementById("b_ignore").onclick=ignoreClicked; +document.getElementById("b_ignall").onclick=ignoreAllClicked; +document.getElementById("b_recheck").onclick=recheckClicked; +document.getElementById("b_revert").onclick=revertClicked; +document.getElementById("b_info").onclick=displayInfo; +document.getElementById("b_ok").onclick=saveClicked; +document.getElementById("b_cancel").onclick=cancelClicked; +_1c=document.getElementById("v_dictionaries"); +_1c.onchange=function(){ +document.getElementById("f_dictionary").value=this.value; +}; +} +function getAbsolutePos(el){ +var r={x:el.offsetLeft,y:el.offsetTop}; +if(el.offsetParent){ +var tmp=getAbsolutePos(el.offsetParent); +r.x+=tmp.x; +r.y+=tmp.y; +} +return r; +} +function wordClicked(_20){ +var _21=this; +if(_20){ +(function(){ +var pos=getAbsolutePos(_21); +var ws={x:frame.offsetWidth-4,y:frame.offsetHeight-4}; +var wp={x:frame.contentWindow.document.body.scrollLeft,y:frame.contentWindow.document.body.scrollTop}; +pos.x-=Math.round(ws.x/2); +if(pos.x<0){ +pos.x=0; +} +pos.y-=Math.round(ws.y/2); +if(pos.y<0){ +pos.y=0; +} +frame.contentWindow.scrollTo(pos.x,pos.y); +})(); +} +if(currentElement){ +var a=allWords[currentElement.__msh_origWord]; +currentElement.className=currentElement.className.replace(/\s*HA-spellcheck-current\s*/g," "); +for(var i=0;i"+currentElement.__msh_origWord+"
    \""; +for(var i=_2a.length;--i>=0;){ +_2a.remove(i); +} +for(var i=0;i<_29.length;++i){ +var txt=_29[i]; +var _2b=document.createElement("option"); +_2b.value=txt; +_2b.appendChild(document.createTextNode(txt)); +_2a.appendChild(_2b); +} +document.getElementById("v_currentWord").innerHTML=this.__msh_origWord; +if(_29.length>0){ +_2a.selectedIndex=0; +_2a.onchange(); +}else{ +document.getElementById("v_replacement").value=this.innerHTML; +} +_2a.style.display="none"; +_2a.style.display="block"; +return false; +} +function wordMouseOver(){ +this.className+=" HA-spellcheck-hover"; +} +function wordMouseOut(){ +this.className=this.className.replace(/\s*HA-spellcheck-hover\s*/g," "); +} +function displayInfo(){ +var _2c=frame.contentWindow.spellcheck_info; +if(!_2c){ +alert("No information available"); +}else{ +var txt="** Document information **"; +for(var i in _2c){ +txt+="\n"+i+" : "+_2c[i]; +} +alert(txt); +} +return false; +} +function finishedSpellChecking(){ +currentElement=null; +wrongWords=null; +allWords={}; +fixedWords=[]; +suggested_words=frame.contentWindow.suggested_words; +document.getElementById("status").innerHTML="HTMLArea Spell Checker (info)"; +var doc=frame.contentWindow.document; +var _30=doc.getElementsByTagName("span"); +var sps=[]; +var id=0; +for(var i=0;i<_30.length;++i){ +var el=_30[i]; +if(/HA-spellcheck-error/.test(el.className)){ +sps.push(el); +el.__msh_wordClicked=wordClicked; +el.onclick=function(ev){ +ev||(ev=window.event); +ev&&HTMLArea._stopEvent(ev); +return this.__msh_wordClicked(false); +}; +el.onmouseover=wordMouseOver; +el.onmouseout=wordMouseOut; +el.__msh_id=id++; +var txt=(el.__msh_origWord=el.firstChild.data); +el.__msh_fixed=false; +if(typeof allWords[txt]=="undefined"){ +allWords[txt]=[el]; +}else{ +allWords[txt].push(el); +} +}else{ +if(/HA-spellcheck-fixed/.test(el.className)){ +fixedWords.push(el); +} +} +} +var _37=doc.getElementById("HA-spellcheck-dictionaries"); +if(_37){ +_37.parentNode.removeChild(_37); +_37=_37.innerHTML.split(/,/); +var _38=document.getElementById("v_dictionaries"); +for(var i=_38.length;--i>=0;){ +_38.remove(i); +} +var _39=document.getElementById("f_dictionary").value; +for(var i=0;i<_37.length;++i){ +var txt=_37[i]; +var _3a=document.createElement("option"); +if(txt==_39){ +_3a.selected=true; +} +_3a.value=txt; +_3a.appendChild(document.createTextNode(txt)); +_38.appendChild(_3a); +} +} +wrongWords=sps; +if(sps.length==0){ +if(!modified){ +alert(_lc("No mispelled words found with the selected dictionary.")); +}else{ +alert(_lc("No mispelled words found with the selected dictionary.")); +} +return false; +} +(currentElement=sps[0]).__msh_wordClicked(true); +var as=doc.getElementsByTagName("a"); +for(var i=as.length;--i>=0;){ +var a=as[i]; +a.onclick=function(){ +if(confirm(_lc("Please confirm that you want to open this link")+":\n"+this.href+"\n"+_lc("I will open it in a new page."))){ +window.open(this.href); +} +return false; +}; +} +} + diff --git a/xinha/plugins/SpellChecker/spell-checker.js b/xinha/plugins/SpellChecker/spell-checker.js new file mode 100644 index 0000000..a3eab8a --- /dev/null +++ b/xinha/plugins/SpellChecker/spell-checker.js @@ -0,0 +1,73 @@ +// Spell Checker Plugin for HTMLArea-3.0 +// Sponsored by www.americanbible.org +// Implementation by Mihai Bazon, http://dynarch.com/mishoo/ +// +// (c) dynarch.com 2003. +// Distributed under the same terms as HTMLArea itself. +// This notice MUST stay intact for use (see license.txt). +// +// $Id$ + +HTMLArea.Config.prototype.SpellChecker = { 'backend': 'php', 'personalFilesDir' : '', 'defaultDictionary' : 'en_GB', 'utf8_to_entities' : true }; + +function SpellChecker(editor) { + this.editor = editor; + + var cfg = editor.config; + var bl = SpellChecker.btnList; + var self = this; + + // see if we can find the mode switch button, insert this before that + var id = "SC-spell-check"; + cfg.registerButton(id, this._lc("Spell-check"), editor.imgURL("spell-check.gif", "SpellChecker"), false, + function(editor, id) { + // dispatch button press event + self.buttonPress(editor, id); + }); + + cfg.addToolbarElement("SC-spell-check", "htmlmode", 1); +} + +SpellChecker._pluginInfo = { + name : "SpellChecker", + version : "1.0", + developer : "Mihai Bazon", + developer_url : "http://dynarch.com/mishoo/", + c_owner : "Mihai Bazon", + sponsor : "American Bible Society", + sponsor_url : "http://www.americanbible.org", + license : "htmlArea" +}; + +SpellChecker.prototype._lc = function(string) { + return HTMLArea._lc(string, 'SpellChecker'); +}; + +SpellChecker.btnList = [ + null, // separator + ["spell-check"] + ]; + +SpellChecker.prototype.buttonPress = function(editor, id) { + switch (id) { + case "SC-spell-check": + SpellChecker.editor = editor; + SpellChecker.init = true; + var uiurl = _editor_url + "plugins/SpellChecker/spell-check-ui.html"; + var win; + if (HTMLArea.is_ie) { + win = window.open(uiurl, "SC_spell_checker", + "toolbar=no,location=no,directories=no,status=no,menubar=no," + + "scrollbars=no,resizable=yes,width=600,height=450"); + } else { + win = window.open(uiurl, "SC_spell_checker", + "toolbar=no,menubar=no,personalbar=no,width=600,height=450," + + "scrollbars=no,resizable=yes"); + } + win.focus(); + break; + } +}; + +// this needs to be global, it's accessed from spell-check-ui.html +SpellChecker.editor = null; \ No newline at end of file diff --git a/xinha/plugins/Stylist/lang/de.js b/xinha/plugins/Stylist/lang/de.js new file mode 100644 index 0000000..b70497d --- /dev/null +++ b/xinha/plugins/Stylist/lang/de.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// Author: Mihai Bazon, http://dynarch.com/mishoo +{ + "Styles": "Stile" +}; diff --git a/xinha/plugins/Stylist/lang/fr.js b/xinha/plugins/Stylist/lang/fr.js new file mode 100644 index 0000000..a09f734 --- /dev/null +++ b/xinha/plugins/Stylist/lang/fr.js @@ -0,0 +1,5 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Styles": "Styles" +}; \ No newline at end of file diff --git a/xinha/plugins/Stylist/lang/ja.js b/xinha/plugins/Stylist/lang/ja.js new file mode 100644 index 0000000..2e455d5 --- /dev/null +++ b/xinha/plugins/Stylist/lang/ja.js @@ -0,0 +1,5 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Styles": "スタイル" +}; \ No newline at end of file diff --git a/xinha/plugins/Stylist/lang/nb.js b/xinha/plugins/Stylist/lang/nb.js new file mode 100644 index 0000000..a5b899b --- /dev/null +++ b/xinha/plugins/Stylist/lang/nb.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Styles": "Stiler" +}; \ No newline at end of file diff --git a/xinha/plugins/Stylist/lang/pl.js b/xinha/plugins/Stylist/lang/pl.js new file mode 100644 index 0000000..8f17f08 --- /dev/null +++ b/xinha/plugins/Stylist/lang/pl.js @@ -0,0 +1,6 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz koto@webworkers.pl +{ + "Styles": "Style" +}; diff --git a/xinha/plugins/Stylist/stylist.js b/xinha/plugins/Stylist/stylist.js new file mode 100644 index 0000000..1b93027 --- /dev/null +++ b/xinha/plugins/Stylist/stylist.js @@ -0,0 +1,372 @@ +Xinha.Config.prototype.css_style={}; +Xinha.Config.prototype.stylistLoadStylesheet=function(_1,_2){ +if(!_2){ +_2={}; +} +var _3=Xinha.ripStylesFromCSSFile(_1); +for(var i in _3){ +if(_2[i]){ +this.css_style[i]=_2[i]; +}else{ +this.css_style[i]=_3[i]; +} +} +this.pageStyleSheets[this.pageStyleSheets.length]=_1; +}; +Xinha.Config.prototype.stylistLoadStyles=function(_5,_6){ +if(!_6){ +_6={}; +} +var _7=Xinha.ripStylesFromCSSString(_5); +for(var i in _7){ +if(_6[i]){ +this.css_style[i]=_6[i]; +}else{ +this.css_style[i]=_7[i]; +} +} +this.pageStyle+=_5; +}; +Xinha.prototype._fillStylist=function(){ +if(!this._stylist){ +return false; +} +this.plugins.Stylist.instance.main.innerHTML=""; +var _9=true; +var _a=this._getSelection(); +var _b=this._activeElement(_a); +for(var x in this.config.css_style){ +var _d=null; +var _e=x.trim(); +var _f=true; +var _10=_b; +if(_f&&/[^a-zA-Z0-9_.-]/.test(_e)){ +_f=false; +} +if(_e.indexOf(".")<0){ +_f=false; +} +if(_f&&(_e.indexOf(".")>0)){ +_d=_e.substring(0,_e.indexOf(".")).toLowerCase(); +_e=_e.substring(_e.indexOf("."),_e.length); +if(_b!=null&&_b.tagName.toLowerCase()==_d){ +_f=true; +_10=_b; +}else{ +if(this._getFirstAncestor(this._getSelection(),[_d])!=null){ +_f=true; +_10=this._getFirstAncestor(this._getSelection(),[_d]); +}else{ +if((_d=="div"||_d=="span"||_d=="p"||(_d.substr(0,1)=="h"&&_d.length==2&&_d!="hr"))){ +if(!this._selectionEmpty(this._getSelection())){ +_f=true; +_10="new"; +}else{ +_10=this._getFirstAncestor(_a,["p","h1","h2","h3","h4","h5","h6","h7"]); +if(_10!=null){ +_f=true; +} +} +}else{ +_f=false; +} +} +} +} +if(_f){ +_e=_e.substring(_e.indexOf("."),_e.length); +_e=_e.replace("."," "); +if(_10==null){ +if(this._selectionEmpty(this._getSelection())){ +_10=this._getFirstAncestor(this._getSelection(),null); +}else{ +_10="new"; +_d="span"; +} +} +} +var _11=(this._ancestorsWithClasses(_a,_d,_e).length>0?true:false); +var _12=this._ancestorsWithClasses(_a,_d,_e); +if(_f){ +var _13=document.createElement("a"); +_13._stylist_className=_e.trim(); +_13._stylist_applied=_11; +_13._stylist_appliedTo=_12; +_13._stylist_applyTo=_10; +_13._stylist_applyTag=_d; +_13.innerHTML=this.config.css_style[x]; +_13.href="javascript:void(0)"; +var _14=this; +_13.onclick=function(){ +if(this._stylist_applied==true){ +_14._stylistRemoveClasses(this._stylist_className,this._stylist_appliedTo); +}else{ +_14._stylistAddClasses(this._stylist_applyTo,this._stylist_applyTag,this._stylist_className); +} +return false; +}; +_13.style.display="block"; +_13.style.paddingLeft="3px"; +_13.style.paddingTop="1px"; +_13.style.paddingBottom="1px"; +_13.style.textDecoration="none"; +if(_11){ +_13.style.background="Highlight"; +_13.style.color="HighlightText"; +} +this.plugins.Stylist.instance.main.appendChild(_13); +} +} +}; +Xinha.prototype._stylistAddClasses=function(el,tag,_17){ +if(el=="new"){ +this.insertHTML("<"+tag+" class=\""+_17+"\">"+this.getSelectedHTML()+""); +}else{ +if(tag!=null&&el.tagName.toLowerCase()!=tag){ +var _18=this.switchElementTag(el,tag); +if(typeof el._stylist_usedToBe!="undefined"){ +_18._stylist_usedToBe=el._stylist_usedToBe; +_18._stylist_usedToBe[_18._stylist_usedToBe.length]={"tagName":el.tagName,"className":el.getAttribute("class")}; +}else{ +_18._stylist_usedToBe=[{"tagName":el.tagName,"className":el.getAttribute("class")}]; +} +Xinha.addClasses(_18,_17); +}else{ +Xinha._addClasses(el,_17); +} +} +this.focusEditor(); +this.updateToolbar(); +}; +Xinha.prototype._stylistRemoveClasses=function(_19,_1a){ +for(var x=0;x<_1a.length;x++){ +this._stylistRemoveClassesFull(_1a[x],_19); +} +this.focusEditor(); +this.updateToolbar(); +}; +Xinha.prototype._stylistRemoveClassesFull=function(el,_1d){ +if(el!=null){ +var _1e=el.className.trim().split(" "); +var _1f=[]; +var _20=_1d.split(" "); +for(var x=0;x<_1e.length;x++){ +var _22=false; +for(var i=0;_22==false&&i<_20.length;i++){ +if(_20[i]==_1e[x]){ +_22=true; +} +} +if(_22==false){ +_1f[_1f.length]=_1e[x]; +} +} +if(_1f.length==0&&el._stylist_usedToBe&&el._stylist_usedToBe.length>0&&el._stylist_usedToBe[el._stylist_usedToBe.length-1].className!=null){ +var _24=el._stylist_usedToBe[el._stylist_usedToBe.length-1]; +var _25=Xinha.arrayFilter(_24.className.trim().split(" "),function(c){ +if(c==null||c.trim()==""){ +return false; +} +return true; +}); +if((_1f.length==0)||(Xinha.arrayContainsArray(_1f,_25)&&Xinha.arrayContainsArray(_25,_1f))){ +el=this.switchElementTag(el,_24.tagName); +_1f=_25; +}else{ +el._stylist_usedToBe=[]; +} +} +if(_1f.length>0||el.tagName.toLowerCase()!="span"||(el.id&&el.id!="")){ +el.className=_1f.join(" ").trim(); +}else{ +var _27=el.parentNode; +var _28=el.childNodes; +for(var x=0;x<_28.length;x++){ +_27.insertBefore(_28[x],el); +} +_27.removeChild(el); +} +} +}; +Xinha.prototype.switchElementTag=function(el,tag){ +var _2b=el.parentNode; +var _2c=this._doc.createElement(tag); +if(Xinha.is_ie||el.hasAttribute("id")){ +_2c.setAttribute("id",el.getAttribute("id")); +} +if(Xinha.is_ie||el.hasAttribute("style")){ +_2c.setAttribute("style",el.getAttribute("style")); +} +var _2d=el.childNodes; +for(var x=0;x<_2d.length;x++){ +_2c.appendChild(_2d[x].cloneNode(true)); +} +_2b.insertBefore(_2c,el); +_2c._stylist_usedToBe=[el.tagName]; +_2b.removeChild(el); +this.selectNodeContents(_2c); +return _2c; +}; +Xinha.prototype._getAncestorsClassNames=function(sel){ +var _30=this._activeElement(sel); +if(_30==null){ +_30=(Xinha.is_ie?this._createRange(sel).parentElement():this._createRange(sel).commonAncestorContainer); +} +var _31=[]; +while(_30){ +if(_30.nodeType==1){ +var _32=_30.className.trim().split(" "); +for(var x=0;x<_32.length;x++){ +_31[_31.length]=_32[x]; +} +if(_30.tagName.toLowerCase()=="body"){ +break; +} +if(_30.tagName.toLowerCase()=="table"){ +break; +} +} +_30=_30.parentNode; +} +return _31; +}; +Xinha.prototype._ancestorsWithClasses=function(sel,tag,_36){ +var _37=[]; +var _38=this._activeElement(sel); +if(_38==null){ +try{ +_38=(Xinha.is_ie?this._createRange(sel).parentElement():this._createRange(sel).commonAncestorContainer); +} +catch(e){ +return _37; +} +} +var _39=_36.trim().split(" "); +while(_38){ +if(_38.nodeType==1&&_38.className){ +if(tag==null||_38.tagName.toLowerCase()==tag){ +var _36=_38.className.trim().split(" "); +var _3a=true; +for(var i=0;i<_39.length;i++){ +var _3c=false; +for(var x=0;x<_36.length;x++){ +if(_39[i]==_36[x]){ +_3c=true; +break; +} +} +if(!_3c){ +_3a=false; +break; +} +} +if(_3a){ +_37[_37.length]=_38; +} +} +if(_38.tagName.toLowerCase()=="body"){ +break; +} +if(_38.tagName.toLowerCase()=="table"){ +break; +} +} +_38=_38.parentNode; +} +return _37; +}; +Xinha.ripStylesFromCSSFile=function(URL){ +var css=Xinha._geturlcontent(URL); +return Xinha.ripStylesFromCSSString(css); +}; +Xinha.ripStylesFromCSSString=function(css){ +RE_comment=/\/\*(.|\r|\n)*?\*\//g; +RE_rule=/\{(.|\r|\n)*?\}/g; +css=css.replace(RE_comment,""); +css=css.replace(RE_rule,","); +css=css.split(","); +var _41={}; +for(var x=0;x0)?_47.main.offsetHeight-_4b.panel.offsetHeight:0)+"px"; +_46._stylist.style.height=_47.caption.offsetHeight+"px"; +_46.sizeEditor(); +break; +case "hide": +_47.resize(); +break; +} +}); +_46.notifyOn("before_resize",function(){ +_46._stylist.style.height=_47.caption.offsetHeight+"px"; +}); +_46.notifyOn("resize",function(){ +_47.resize(); +}); +} +}; +Stylist.prototype.resize=function(){ +var _4d=this.editor; +var _4e=_4d._stylist.parentNode; +var _4f=_4e.offsetHeight; +for(var i=0;i<_4e.childNodes.length;++i){ +if(_4e.childNodes[i]==_4d._stylist||!_4e.childNodes[i].offsetHeight){ +continue; +} +_4f-=_4e.childNodes[i].offsetHeight; +} +_4d._stylist.style.height=_4f+"px"; +this.main.style.height=_4f-this.caption.offsetHeight+"px"; +}; +Stylist.prototype.onUpdateToolbar=function(){ +if(this.editor._stylist){ +if(this._timeoutID){ +window.clearTimeout(this._timeoutID); +} +var e=this.editor; +this._timeoutID=window.setTimeout(function(){ +e._fillStylist(); +},250); +} +}; + diff --git a/xinha/plugins/SuperClean/dialog.html b/xinha/plugins/SuperClean/dialog.html new file mode 100644 index 0000000..abced76 --- /dev/null +++ b/xinha/plugins/SuperClean/dialog.html @@ -0,0 +1,9 @@ +

    Clean up HTML

    +
    + Please select from the following cleaning options... + +
    + + +
    +
    \ No newline at end of file diff --git a/xinha/plugins/SuperClean/filters/paragraph.js b/xinha/plugins/SuperClean/filters/paragraph.js new file mode 100644 index 0000000..041a575 --- /dev/null +++ b/xinha/plugins/SuperClean/filters/paragraph.js @@ -0,0 +1,6 @@ +function(html) { + html = html.replace(/<\s*p[^>]*>/gi, ''); + html = html.replace(/<\/\s*p\s*>/gi, ''); + html = html.trim(); + return html; +} \ No newline at end of file diff --git a/xinha/plugins/SuperClean/filters/word.js b/xinha/plugins/SuperClean/filters/word.js new file mode 100644 index 0000000..495a719 --- /dev/null +++ b/xinha/plugins/SuperClean/filters/word.js @@ -0,0 +1,53 @@ +function(html) { + // Remove HTML comments + html = html.replace(//gi, "" ); + html = html.replace(//gi, ''); + // Remove all HTML tags + html = html.replace(/<\/?\s*HTML[^>]*>/gi, "" ); + // Remove all BODY tags + html = html.replace(/<\/?\s*BODY[^>]*>/gi, "" ); + // Remove all META tags + html = html.replace(/<\/?\s*META[^>]*>/gi, "" ); + // Remove all SPAN tags + html = html.replace(/<\/?\s*SPAN[^>]*>/gi, "" ); + // Remove all FONT tags + html = html.replace(/<\/?\s*FONT[^>]*>/gi, ""); + // Remove all IFRAME tags. + html = html.replace(/<\/?\s*IFRAME[^>]*>/gi, ""); + // Remove all STYLE tags & content + html = html.replace(/<\/?\s*STYLE[^>]*>(.|[\n\r\t])*<\/\s*STYLE\s*>/gi, "" ); + // Remove all TITLE tags & content + html = html.replace(/<\s*TITLE[^>]*>(.|[\n\r\t])*<\/\s*TITLE\s*>/gi, "" ); + // Remove javascript + html = html.replace(/<\s*SCRIPT[^>]*>[^\0]*<\/\s*SCRIPT\s*>/gi, ""); + // Remove all HEAD tags & content + html = html.replace(/<\s*HEAD[^>]*>(.|[\n\r\t])*<\/\s*HEAD\s*>/gi, "" ); + // Remove Class attributes + html = html.replace(/<\s*(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3") ; + // Remove Style attributes + html = html.replace(/<\s*(\w[^>]*) style="([^"]*)"([^>]*)/gi, "<$1$3") ; + // Remove Lang attributes + html = html.replace(/<\s*(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3") ; + // Remove XML elements and declarations + html = html.replace(/<\\?\?xml[^>]*>/gi, "") ; + // Remove Tags with XML namespace declarations: + html = html.replace(/<\/?\w+:[^>]*>/gi, "") ; + // Replace the   + html = html.replace(/ /, " " ); + + // Transform


    to
    + //html = html.replace(/<\s*p[^>]*>\s*<\s*br\s*\/>\s*<\/\s*p[^>]*>/gi, "
    "); + html = html.replace(/<\s*p[^>]*><\s*br\s*\/?>\s*<\/\s*p[^>]*>/gi, "
    "); + + // Remove

    + html = html.replace(/<\s*p[^>]*>/gi, ""); + + // Replace

    with
    + html = html.replace(/<\/\s*p[^>]*>/gi, "
    "); + + // Remove any
    at the end + html = html.replace(/(\s*
    \s*)*$/, ""); + + html = html.trim(); + return html; +} \ No newline at end of file diff --git a/xinha/plugins/SuperClean/img/ed_superclean.gif b/xinha/plugins/SuperClean/img/ed_superclean.gif new file mode 100644 index 0000000..53180a8 Binary files /dev/null and b/xinha/plugins/SuperClean/img/ed_superclean.gif differ diff --git a/xinha/plugins/SuperClean/lang/de.js b/xinha/plugins/SuperClean/lang/de.js new file mode 100644 index 0000000..9e4f6c7 --- /dev/null +++ b/xinha/plugins/SuperClean/lang/de.js @@ -0,0 +1,17 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Raimund Meyer xinha@ray-of-light.org +{ + "Clean up HTML": "HTML säubern", + "Please select from the following cleaning options...": "Bitte Optionen auswählen...", + "General tidy up and correction of some problems.": "Allgemeines aufräumen und Korrektur einiger Probleme.", + "Clean bad HTML from Microsoft Word": "Schlechtes HTML aus Microsoft Word aufräumen", + "Remove custom typefaces (font \"styles\").": "Schriftarten entfernen (font face).", + "Remove custom font sizes.": "Schriftgrößen entfernen (font size).", + "Remove custom text colors.": "Schriftfarben entfernen (font color).", + "Remove lang attributes.": "Sprachattribute entfernen.", + "Go": "Go", + "Cancel": "Abbrechen", + "Tidy failed. Check your HTML for syntax errors.": "Säubern fehlgeschlagen. Überprüfen Sie Ihren Code auf Fehler.", + "You don't have anything to tidy!": "Es gibt nichts zu säubern...!" +}; diff --git a/xinha/plugins/SuperClean/lang/fr.js b/xinha/plugins/SuperClean/lang/fr.js new file mode 100644 index 0000000..867489c --- /dev/null +++ b/xinha/plugins/SuperClean/lang/fr.js @@ -0,0 +1,16 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Clean up HTML": "Nettoyer le code HTML", + "Please select from the following cleaning options...": "Veuillez sélectionner une option de nettoyage.", + "General tidy up and correction of some problems.": "Nettoyage générique et correction des problèmes mineurs.", + "Clean bad HTML from Microsoft Word": "Nettoyer les balises HTML de Microsoft Word", + "Remove custom typefaces (font \"styles\").": "Supprimer les polices personalisées (font \"styles\").", + "Remove custom font sizes.": "Supprimer les tailles de polices personnalisées.", + "Remove custom text colors.": "Supprimer les couleurs de texte personalisées.", + "Remove lang attributes.": "Supprimer les attributs de langue.", + "Go": "Commencer", + "Cancel": "Annuler", + "Tidy failed. Check your HTML for syntax errors.": "Tidy a échoué. Vérifier la syntaxe HTML.", + "You don't have anything to tidy!": "Rien à transmettre à tidy !" +}; \ No newline at end of file diff --git a/xinha/plugins/SuperClean/lang/ja.js b/xinha/plugins/SuperClean/lang/ja.js new file mode 100644 index 0000000..ae8b797 --- /dev/null +++ b/xinha/plugins/SuperClean/lang/ja.js @@ -0,0 +1,18 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Clean up HTML": "HTMLのクリーンナップ", + "Please select from the following cleaning options...": "以下のクリーンナップオプションを選択してください...", + "General tidy up and correction of some problems.": "一般的な適正化といくつかの問題を修正します。", + "Clean bad HTML from Microsoft Word": "Microsoft Wordによる不正なHTMLの清潔化", + "Remove custom typefaces (font \"styles\").": "独自フォント名設定の除去 (font face)。", + "Remove custom font sizes.": "独自フォントサイズ設定の除去。", + "Remove custom text colors.": "独自文字色設定の除去。", + "Remove lang attributes.": "言語属性の除去。", + "Go": "実行", + "Cancel": "中止", + "Tidy failed. Check your HTML for syntax errors.": "適正化に失敗しました。HTMLの文法エラーを確認してください。", + "You don't have anything to tidy!": "適正化するものは何もありません!", + "Replace directional quote marks with non-directional quote marks.": "方向つき引用符を方向なし引用符に置換。", + "CANCEL": "中止" +}; \ No newline at end of file diff --git a/xinha/plugins/SuperClean/lang/nb.js b/xinha/plugins/SuperClean/lang/nb.js new file mode 100644 index 0000000..f8822d3 --- /dev/null +++ b/xinha/plugins/SuperClean/lang/nb.js @@ -0,0 +1,17 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com +{ + "Clean up HTML": "Vask HTML kode", + "Please select from the following cleaning options...": "Vennligst velg blandt de forskjellige mulighetene å vaske/ rydde i HTML koden", + "General tidy up and correction of some problems.": "Generell opprydding i HTML koden samt korrigering av typiske feil", + "Clean bad HTML from Microsoft Word": "Vask HTML kode for feil og problemer etter Microsoft Word", + "Remove custom typefaces (font \"styles\").": "Fjerne egendefinerte skrifttyper (font face)", + "Remove custom font sizes.": "Fjerne egendefinerte skriftstørrelser (font size)", + "Remove custom text colors.": "Fjerne egendefinerte skriftfarger (font color)", + "Remove lang attributes.": "Fjerne lang-attributter.", + "Go": "Utfør", + "Cancel": "Avbryt", + "Tidy failed. Check your HTML for syntax errors.": "Tidy (Programmet som retter HTML koden) feilet. Vennligst se over HTML koden for feil.", + "You don't have anything to tidy!": "Det finnes ingen HTML kode å vaske!" +}; \ No newline at end of file diff --git a/xinha/plugins/SuperClean/super-clean.js b/xinha/plugins/SuperClean/super-clean.js new file mode 100644 index 0000000..a634984 --- /dev/null +++ b/xinha/plugins/SuperClean/super-clean.js @@ -0,0 +1,211 @@ +function SuperClean(_1,_2){ +this.editor=_1; +var _3=this; +_1._superclean_on=false; +_1.config.registerButton("superclean",this._lc("Clean up HTML"),_1.imgURL("ed_superclean.gif","SuperClean"),true,function(e,_5,_6){ +_3._superClean(null,_6); +}); +_1.config.addToolbarElement("superclean","killword",0); +} +SuperClean._pluginInfo={name:"SuperClean",version:"1.0",developer:"James Sleeman, Niko Sams",developer_url:"http://www.gogo.co.nz/",c_owner:"Gogo Internet Services",license:"htmlArea",sponsor:"Gogo Internet Services",sponsor_url:"http://www.gogo.co.nz/"}; +SuperClean.prototype._lc=function(_7){ +return Xinha._lc(_7,"SuperClean"); +}; +SuperClean.prototype._superClean=function(_8,_9){ +var _a=this; +var _b=function(){ +var _c=_a._dialog.hide(); +var _d=_a.editor; +if(_c.word_clean){ +_d._wordClean(); +} +var D=_d.getInnerHTML(); +for(var _f in _d.config.SuperClean.filters){ +if(_f=="tidy"||_f=="word_clean"){ +continue; +} +if(_c[_f]){ +D=SuperClean.filterFunctions[_f](D,_d); +} +} +D=D.replace(/(style|class)="\s*"/gi,""); +D=D.replace(/<(font|span)\s*>/gi,""); +_d.setHTML(D); +if(_c.tidy){ +var _10=function(_11){ +eval("var response = "+_11); +switch(response.action){ +case "setHTML": +_d.setHTML(response.value); +break; +case "alert": +alert(_a._lc(response.value)); +break; +} +}; +Xinha._postback(_d.config.SuperClean.tidy_handler,{"content":_d.getInnerHTML()},_10); +} +return true; +}; +if(this.editor.config.SuperClean.show_dialog){ +var _12={}; +this._dialog.show(_12,_b); +}else{ +var _13=this.editor; +var _14=_13.getInnerHTML(); +for(var _15 in _13.config.SuperClean.filters){ +if(_15=="tidy"){ +continue; +} +_14=SuperClean.filterFunctions[_15](_14,_13); +} +_14=_14.replace(/(style|class)="\s*"/gi,""); +_14=_14.replace(/<(font|span)\s*>/gi,""); +_13.setHTML(_14); +if(_13.config.SuperClean.filters.tidy){ +SuperClean.filterFunctions.tidy(_14,_13); +} +} +}; +Xinha.Config.prototype.SuperClean={"tidy_handler":_editor_url+"plugins/SuperClean/tidy.php","filters":{"tidy":Xinha._lc("General tidy up and correction of some problems.","SuperClean"),"word_clean":Xinha._lc("Clean bad HTML from Microsoft Word","SuperClean"),"remove_faces":Xinha._lc("Remove custom typefaces (font \"styles\").","SuperClean"),"remove_sizes":Xinha._lc("Remove custom font sizes.","SuperClean"),"remove_colors":Xinha._lc("Remove custom text colors.","SuperClean"),"remove_lang":Xinha._lc("Remove lang attributes.","SuperClean"),"remove_fancy_quotes":{label:Xinha._lc("Replace directional quote marks with non-directional quote marks.","SuperClean"),checked:false}},"show_dialog":true}; +SuperClean.filterFunctions={}; +SuperClean.filterFunctions.remove_colors=function(D){ +D=D.replace(/color="?[^" >]*"?/gi,""); +D=D.replace(/([^-])color:[^;}"']+;?/gi,"$1"); +return (D); +}; +SuperClean.filterFunctions.remove_sizes=function(D){ +D=D.replace(/size="?[^" >]*"?/gi,""); +D=D.replace(/font-size:[^;}"']+;?/gi,""); +return (D); +}; +SuperClean.filterFunctions.remove_faces=function(D){ +D=D.replace(/face="?[^" >]*"?/gi,""); +D=D.replace(/font-family:[^;}"']+;?/gi,""); +return (D); +}; +SuperClean.filterFunctions.remove_lang=function(D){ +D=D.replace(/lang="?[^" >]*"?/gi,""); +return (D); +}; +SuperClean.filterFunctions.word_clean=function(_1a,_1b){ +_1b.setHTML(_1a); +_1b._wordClean(); +return _1b.getInnerHTML(); +}; +SuperClean.filterFunctions.remove_fancy_quotes=function(D){ +D=D.replace(new RegExp(String.fromCharCode(8216),"g"),"'"); +D=D.replace(new RegExp(String.fromCharCode(8217),"g"),"'"); +D=D.replace(new RegExp(String.fromCharCode(8218),"g"),"'"); +D=D.replace(new RegExp(String.fromCharCode(8219),"g"),"'"); +D=D.replace(new RegExp(String.fromCharCode(8220),"g"),"\""); +D=D.replace(new RegExp(String.fromCharCode(8221),"g"),"\""); +D=D.replace(new RegExp(String.fromCharCode(8222),"g"),"\""); +D=D.replace(new RegExp(String.fromCharCode(8223),"g"),"\""); +return D; +}; +SuperClean.filterFunctions.tidy=function(_1d,_1e){ +Xinha._postback(_1e.config.SuperClean.tidy_handler,{"content":_1d},function(_1f){ +eval(_1f); +}); +}; +SuperClean.prototype.onGenerate=function(){ +if(this.editor.config.SuperClean.show_dialog&&!this._dialog){ +this._dialog=new SuperClean.Dialog(this); +} +if(this.editor.config.tidy_handler){ +this.editor.config.SuperClean.tidy_handler=this.editor.config.tidy_handler; +this.editor.config.tidy_handler=null; +} +if(!this.editor.config.SuperClean.tidy_handler&&this.editor.config.filters.tidy){ +this.editor.config.filters.tidy=null; +} +var sc=this; +for(var _21 in this.editor.config.SuperClean.filters){ +if(!SuperClean.filterFunctions[_21]){ +var _22=this.editor.config.SuperClean.filters[_21]; +if(typeof _22.filterFunction!="undefined"){ +SuperClean.filterFunctions[_21]=filterFunction; +}else{ +Xinha._getback(_editor_url+"plugins/SuperClean/filters/"+_21+".js",function(_23){ +eval("SuperClean.filterFunctions."+_21+"="+_23+";"); +sc.onGenerate(); +}); +} +return; +} +} +}; +SuperClean.Dialog=function(_24){ +var _25=this; +this.Dialog_nxtid=0; +this.SuperClean=_24; +this.id={}; +this.ready=false; +this.files=false; +this.html=false; +this.dialog=false; +this._prepareDialog(); +}; +SuperClean.Dialog.prototype._prepareDialog=function(){ +var _26=this; +var _27=this.SuperClean; +if(this.html==false){ +Xinha._getback(_editor_url+"plugins/SuperClean/dialog.html",function(txt){ +_26.html=txt; +_26._prepareDialog(); +}); +return; +} +var _29=""; +for(var _2a in this.SuperClean.editor.config.SuperClean.filters){ +_29+="
    \n"; +var _2b=this.SuperClean.editor.config.SuperClean.filters[_2a]; +if(typeof _2b.label=="undefined"){ +_29+=" \n"; +_29+=" \n"; +}else{ +_29+=" \n"; +_29+=" \n"; +} +_29+="
    \n"; +} +this.html=this.html.replace("",_29); +var _2c=this.html; +var _2d=this.dialog=new Xinha.Dialog(_27.editor,this.html,"SuperClean"); +this.ready=true; +}; +SuperClean.Dialog.prototype._lc=SuperClean.prototype._lc; +SuperClean.Dialog.prototype.show=function(_2e,ok,_30){ +if(!this.ready){ +var _31=this; +window.setTimeout(function(){ +_31.show(_2e,ok,_30); +},100); +return; +} +var _32=this.dialog; +var _31=this; +if(ok){ +this.dialog.getElementById("ok").onclick=ok; +}else{ +this.dialog.getElementById("ok").onclick=function(){ +_31.hide(); +}; +} +if(_30){ +this.dialog.getElementById("cancel").onclick=_30; +}else{ +this.dialog.getElementById("cancel").onclick=function(){ +_31.hide(); +}; +} +this.SuperClean.editor.disableToolbar(["fullscreen","SuperClean"]); +this.dialog.show(_2e); +this.dialog.onresize(); +}; +SuperClean.Dialog.prototype.hide=function(){ +this.SuperClean.editor.enableToolbar(); +return this.dialog.hide(); +}; + diff --git a/xinha/plugins/SuperClean/tidy.php b/xinha/plugins/SuperClean/tidy.php new file mode 100644 index 0000000..84cc7e4 --- /dev/null +++ b/xinha/plugins/SuperClean/tidy.php @@ -0,0 +1,179 @@ +,{,},@,\n,\r"; + + if(!is_array($strings)) + { + $tr = array(); + foreach(explode(',', $strings) as $chr) + { + $tr[$chr] = sprintf('\x%02X', ord($chr)); + } + $strings = $tr; + } + + return strtr($string, $strings); + } + + // Any errors would screq up our javascript + error_reporting(E_NONE); + ini_set('display_errors', false); + + if(trim(@$_REQUEST['content'])) + { + // PHP's urldecode doesn't understand %uHHHH for unicode + $_REQUEST['content'] = preg_replace('/%u([a-f0-9]{4,4})/ei', 'utf8_chr(0x$1)', $_REQUEST['content']); + function utf8_chr($num) + { + if($num<128)return chr($num); + if($num<1024)return chr(($num>>6)+192).chr(($num&63)+128); + if($num<32768)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128); + if($num<2097152)return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128) .chr(($num&63)+128); + return ''; + } + ob_start(); + passthru("echo " . escapeshellarg($_REQUEST['content']) . " | tidy -q -i -u -wrap 9999 -utf8 -bare -asxhtml 2>/dev/null", $result); + $content = ob_get_contents(); + ob_end_clean(); + + if(strlen($content) < 4) + { + // Tidy on the local machine failed, try a post + $res_1 + = PostIt( + array + ( + '_function' => 'tidy', + '_html' => $_REQUEST['content'], + 'char-encoding' => 'utf8', + '_output' => 'warn', + 'indent' => 'auto', + 'wrap' => 9999, + 'break-before-br' => 'y', + 'bare' => 'n', + 'word-2000' => 'n', + 'drop-empty-paras' => 'y', + 'drop-font-tags' => 'n', + + ), + 'http://infohound.net/tidy/tidy.pl'); + + if(preg_match('/ diff --git a/xinha/plugins/TableOperations/img/cell-delete.gif b/xinha/plugins/TableOperations/img/cell-delete.gif new file mode 100644 index 0000000..2fd629b Binary files /dev/null and b/xinha/plugins/TableOperations/img/cell-delete.gif differ diff --git a/xinha/plugins/TableOperations/img/cell-insert-after.gif b/xinha/plugins/TableOperations/img/cell-insert-after.gif new file mode 100644 index 0000000..ddea8a0 Binary files /dev/null and b/xinha/plugins/TableOperations/img/cell-insert-after.gif differ diff --git a/xinha/plugins/TableOperations/img/cell-insert-before.gif b/xinha/plugins/TableOperations/img/cell-insert-before.gif new file mode 100644 index 0000000..2e7b36b Binary files /dev/null and b/xinha/plugins/TableOperations/img/cell-insert-before.gif differ diff --git a/xinha/plugins/TableOperations/img/cell-merge.gif b/xinha/plugins/TableOperations/img/cell-merge.gif new file mode 100644 index 0000000..2da38f3 Binary files /dev/null and b/xinha/plugins/TableOperations/img/cell-merge.gif differ diff --git a/xinha/plugins/TableOperations/img/cell-prop.gif b/xinha/plugins/TableOperations/img/cell-prop.gif new file mode 100644 index 0000000..e9495aa Binary files /dev/null and b/xinha/plugins/TableOperations/img/cell-prop.gif differ diff --git a/xinha/plugins/TableOperations/img/cell-split.gif b/xinha/plugins/TableOperations/img/cell-split.gif new file mode 100644 index 0000000..0b22593 Binary files /dev/null and b/xinha/plugins/TableOperations/img/cell-split.gif differ diff --git a/xinha/plugins/TableOperations/img/col-delete.gif b/xinha/plugins/TableOperations/img/col-delete.gif new file mode 100644 index 0000000..5202886 Binary files /dev/null and b/xinha/plugins/TableOperations/img/col-delete.gif differ diff --git a/xinha/plugins/TableOperations/img/col-insert-after.gif b/xinha/plugins/TableOperations/img/col-insert-after.gif new file mode 100644 index 0000000..a1ffb6e Binary files /dev/null and b/xinha/plugins/TableOperations/img/col-insert-after.gif differ diff --git a/xinha/plugins/TableOperations/img/col-insert-before.gif b/xinha/plugins/TableOperations/img/col-insert-before.gif new file mode 100644 index 0000000..1a3359f Binary files /dev/null and b/xinha/plugins/TableOperations/img/col-insert-before.gif differ diff --git a/xinha/plugins/TableOperations/img/col-split.gif b/xinha/plugins/TableOperations/img/col-split.gif new file mode 100644 index 0000000..2fbe949 Binary files /dev/null and b/xinha/plugins/TableOperations/img/col-split.gif differ diff --git a/xinha/plugins/TableOperations/img/row-delete.gif b/xinha/plugins/TableOperations/img/row-delete.gif new file mode 100644 index 0000000..1fed389 Binary files /dev/null and b/xinha/plugins/TableOperations/img/row-delete.gif differ diff --git a/xinha/plugins/TableOperations/img/row-insert-above.gif b/xinha/plugins/TableOperations/img/row-insert-above.gif new file mode 100644 index 0000000..3cbeceb Binary files /dev/null and b/xinha/plugins/TableOperations/img/row-insert-above.gif differ diff --git a/xinha/plugins/TableOperations/img/row-insert-under.gif b/xinha/plugins/TableOperations/img/row-insert-under.gif new file mode 100644 index 0000000..89fc588 Binary files /dev/null and b/xinha/plugins/TableOperations/img/row-insert-under.gif differ diff --git a/xinha/plugins/TableOperations/img/row-prop.gif b/xinha/plugins/TableOperations/img/row-prop.gif new file mode 100644 index 0000000..7a90011 Binary files /dev/null and b/xinha/plugins/TableOperations/img/row-prop.gif differ diff --git a/xinha/plugins/TableOperations/img/row-split.gif b/xinha/plugins/TableOperations/img/row-split.gif new file mode 100644 index 0000000..8d799f1 Binary files /dev/null and b/xinha/plugins/TableOperations/img/row-split.gif differ diff --git a/xinha/plugins/TableOperations/img/table-prop.gif b/xinha/plugins/TableOperations/img/table-prop.gif new file mode 100644 index 0000000..10ec553 Binary files /dev/null and b/xinha/plugins/TableOperations/img/table-prop.gif differ diff --git a/xinha/plugins/TableOperations/lang/cz.js b/xinha/plugins/TableOperations/lang/cz.js new file mode 100644 index 0000000..3235f08 --- /dev/null +++ b/xinha/plugins/TableOperations/lang/cz.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "cz", ENCODING: UTF-8 +// Author: Jiri Löw, +{ + "Align": "Zarovnání", + "All four sides": "Všechny čtyři strany", + "Background": "Pozadí", + "Baseline": "Základní linka", + "Border": "Obrys", + "Borders": "Obrysy", + "Bottom": "Dolů", + "Style [CSS]": "Kaskádové styly (CSS)", + "Caption": "Titulek", + "Cell Properties": "Vlastnosti buňky", + "Center": "Na střed", + "Char": "Znak", + "Collapsed borders": "Stlačené okraje", + "Color": "Barva", + "Description": "Popis", + "FG Color": "Barva popředí", + "Float": "Obtékání", + "Frames": "Rámečky", + "Height": "Výška", + "How many columns would you like to merge?": "Kolik sloupců si přejete spojit?", + "How many rows would you like to merge?": "Kolik řádků si přejete spojit?", + "Image URL": "Adresa obrázku", + "Justify": "Do stran", + "Layout": "Rozložení", + "Left": "Vlevo", + "Margin": "Okraj", + "Middle": "Na střed", + "No rules": "Žádné čáry", + "No sides": "Žádné strany", + "None": "Žádné", + "Padding": "Odsazování", + "Please click into some cell": "Prosím klikněte do některé buňky", + "Right": "Vpravo", + "Row Properties": "Vlastnosti řádku", + "Rules will appear between all rows and columns": "Čáry mezi všemi řádky i sloupci", + "Rules will appear between columns only": "Čáry pouze mezi sloupci", + "Rules will appear between rows only": "Čáry pouze mezi řádky", + "Rules": "Čáry", + "Spacing and padding": "Mezery a odsazování", + "Spacing": "Mezery", + "Summary": "Shrnutí", + "Delete cell": "Smazat buňku", + "Insert cell after": "Vložit buňku za", + "Insert cell before": "Vložit buňku před", + "Merge cells": "Spojit buňky", + "Cell properties": "Vlastnosti buňky", + "Split cell": "Rozdělit buňku", + "Delete column": "Smazat sloupec", + "Insert column after": "Vložit sloupec za", + "Insert column before": "Vložit sloupec před", + "Split column": "Rozdělit sloupec", + "Delete row": "Smazat řádek", + "Insert row before": "Smazat řádek nad", + "Insert row after": "Smazat řádek pod", + "Row properties": "Vlastnosti řádku", + "Split row": "Rozdělit řádek", + "Table properties": "Vlastnosti tabulky", + "Table Properties": "Vlastnosti tabulky", + "Text align": "Zarovnání textu", + "The bottom side only": "Pouze spodní strana", + "The left-hand side only": "Pouze levá strana", + "The right and left sides only": "Pouze levá a pravá strana", + "The right-hand side only": "Pouze pravá strana", + "The top and bottom sides only": "Pouze horní a dolní strana", + "The top side only": "Pouze horní strana", + "Top": "Nahoru", + "Unset color": "Zrušit barvu", + "Vertical align": "Svislé zarovnání", + "Width": "Šířka", + "HTMLArea cowardly refuses to delete the last cell in row.": "HTMLArea zbaběle odmítá smazat poslední buňku v řádku.", + "HTMLArea cowardly refuses to delete the last column in table.": "HTMLArea zbaběle odmítá smazat poslední sloupec v tabulce.", + "HTMLArea cowardly refuses to delete the last row in table.": "HTMLArea zbaběle odmítá smazat poslední řádek v tabulce.", + "percent": "procent", + "pixels": "pixelů" +}; diff --git a/xinha/plugins/TableOperations/lang/da.js b/xinha/plugins/TableOperations/lang/da.js new file mode 100644 index 0000000..b15072b --- /dev/null +++ b/xinha/plugins/TableOperations/lang/da.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "da", ENCODING: UTF-8 +// Author: Steen Sønderup, +{ + "Align": "Placer", + "All four sides": "Alle fire sider", + "Background": "Baggrund", + "Baseline": "Bundlinie", + "Border": "Kant", + "Borders": "Kanter", + "Bottom": "Bund", + "Style [CSS]": "Stil [CSS]", + "Caption": "Titel", + "Cell Properties": "Celle egenskaber", + "Center": "Centrer", + "Char": "Plads", + "Collapsed borders": "Sammensmelt rammer", + "Color": "Farve", + "Description": "Beskrivelse", + "FG Color": "Font farve", + "Float": "Justering", + "Frames": "Udvendig", + "Height": "Højde", + "How many columns would you like to merge?": "Hvor mange kollonner vil du samle?", + "How many rows would you like to merge?": "Hvor mange rækker vil du samle?", + "Image URL": "Billede URL", + "Justify": "Lige margener", + "Layout": "Opsætning", + "Left": "Venstre", + "Margin": "Margen", + "Middle": "Centrer", + "No rules": "Ingen rammer", + "No sides": "Ingen sider", + "None": "Ingen", + "Padding": "Margen", + "Please click into some cell": "Klik på en celle", + "Right": "Højre", + "Row Properties": "Række egenskaber", + "Rules will appear between all rows and columns": "Rammer mellem rækker og kolonner", + "Rules will appear between columns only": "Kun rammer mellem kolonner", + "Rules will appear between rows only": "Kun rammer mellem rækker", + "Rules": "Invendig", + "Spacing and padding": "Afstand og margen", + "Spacing": "Afstand", + "Summary": "Beskrivelse", + "Delete cell": "Slet celle", + "Insert cell after": "Indsæt celle efter", + "Insert cell before": "Indsæt celle før", + "Merge cells": "Sammensæt celler", + "Cell properties": "Celle egenskaber", + "Split cell": "Opdel celle", + "Delete column": "Slet kollonne", + "Insert column after": "Indsæt kolonne efter", + "Insert column before": "Indsæt kolonne før", + "Split column": "Opdel kolonne", + "Delete row": "Slet række", + "Insert row before": "Indsæt række før", + "Insert row after": "Indsæt række efter", + "Row properties": "Række egenskaber", + "Split row": "Opdel række", + "Table properties": "Tabel egenskaber", + "Table Properties": "Tabel egenskaber", + "Text align": "Tekst", + "The bottom side only": "Kun i bunden", + "The left-hand side only": "Kun i højre side", + "The right and left sides only": "Kun i siderne", + "The right-hand side only": "Kun i venstre side", + "The top and bottom sides only": "Kun i top og bund", + "The top side only": "Kun i toppen", + "Top": "Top", + "Unset color": "Farve ikke valgt", + "Vertical align": "Vertikal placering", + "Width": "Bredde", + "HTMLArea cowardly refuses to delete the last cell in row.": "Du kan ikke slette den sidste celle i en række.", + "HTMLArea cowardly refuses to delete the last column in table.": "Du kan ikke slette den sidste kolonne i en tabel.", + "HTMLArea cowardly refuses to delete the last row in table.": "Du kan ikke slette den sidste række i en tabel.", + "percent": "procent", + "pixels": "pixel" +}; diff --git a/xinha/plugins/TableOperations/lang/de.js b/xinha/plugins/TableOperations/lang/de.js new file mode 100644 index 0000000..2088b20 --- /dev/null +++ b/xinha/plugins/TableOperations/lang/de.js @@ -0,0 +1,81 @@ +// I18N constants +// LANG: "de", ENCODING: UTF-8 +// translated: Raimund Meyer xinha@ray-of-light.org +{ + "Align": "Ausrichtung", + "All four sides": "Alle 4 Seiten", + "Background": "Hintergrund", + "Baseline": "Grundlinie", + "Border": "Rahmen", + "Borders": "Rahmen", + "Bottom": "Unten", + "Style [CSS]": "Style [CSS]", + "Caption": "Überschrift", + "Cell Properties": "Zellenoptionen", + "Center": "Zentriert", + "Char": "Zeichen", + "Collapsed borders": "Rahmen fallen zusammen", + "Color": "Farbe", + "Description": "Beschreibung", + "FG Color": "Vordergrundfarbe", + "Float": "Float", + "Frames": "Rahmen", + "Height": "Höhe", + "How many columns would you like to merge?": "Wieviele Spalten wollen Sie verbinden?", + "How many rows would you like to merge?": "Wieviele Zeilen wollen Sie verbinden?", + "Image URL": "Bild-URL", + "Justify": "Blocksatz", + "Layout": "Layout", + "Left": "Links", + "Margin": "Rand", + "Middle": "Mitte", + "No rules": "Keine Gitterlinien", + "No sides": "Keine Ränder", + "None": "Keine", + "Padding": "Innenabstand", + "Please click into some cell": "Bitte eine Zelle auswählen", + "Right": "Rechts", + "Row Properties": "Zeilenoptionen", + "Rules will appear between all rows and columns": "Linien zwischen Zeilen und Spalten", + "Rules will appear between columns only": "Linien zwischen Spalten", + "Rules will appear between rows only": "Linien zwischen Zeilen", + "Rules": "Linien", + "Spacing and padding": "Abstände", + "Spacing": "Abstand", + "Summary": "Zusammenfassung", + "Delete cell": "Zelle löschen", + "Insert cell after": "Zelle einfügen nach", + "Insert cell before": "Zelle einfügen vor", + "Merge cells": "Zellen zusammenfügen", + "Cell properties": "Zellenoptionen", + "Split cell": "Zellen teilen", + "Delete column": "Spalte löschen", + "Insert column after": "Spalte einfügen nach", + "Insert column before": "Spalte einfügen vor", + "Split column": "Spalte teilen", + "Delete row": "Reihe loeschen", + "Insert row before": "Reihe einfügen vor", + "Insert row after": "Reihe einfügen nach", + "Row properties": "Reiheneinstellungen", + "Split row": "Reihen aufteilen", + "Table properties": "Tabellenoptionen", + "Table Properties": "Tabellenoptionen", + "Text align": "Textausrichtung", + "The bottom side only": "Nur untere Seite", + "The left-hand side only": "Nur linke Seite", + "The right and left sides only": "Nur linke und rechte Seite", + "The right-hand side only": "Nur rechte Seite", + "The top and bottom sides only": "Nur obere und untere Seite", + "The top side only": "Nur obere Seite", + "Top": "Oben", + "Unset color": "Farbe entfernen", + "Vertical align": "Vertikale Ausrichtung", + "Width": "Breite", + "HTMLArea cowardly refuses to delete the last cell in row.": "Letzte Zelle in dieser Zeile kann nicht gelöscht werden", + "HTMLArea cowardly refuses to delete the last column in table.": "Letzte Spalte in dieser Tabelle kann nicht gelöscht werden", + "HTMLArea cowardly refuses to delete the last row in table.": "Letzte Reihe in dieser Tabelle kann nicht gelöscht werden", + "percent": "%", + "pixels": "Pixel", + "OK": "OK", + "Cancel": "Abbrechen" +}; diff --git a/xinha/plugins/TableOperations/lang/el.js b/xinha/plugins/TableOperations/lang/el.js new file mode 100644 index 0000000..9df38bf --- /dev/null +++ b/xinha/plugins/TableOperations/lang/el.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "el", ENCODING: UTF-8 +// Author: Dimitris Glezos, dimitris@glezos.com +{ + "Align": "Στοίχηση", + "All four sides": "Και οι 4 πλευρές", + "Background": "Φόντο", + "Baseline": "Baseline", + "Border": "Περίγραμμα", + "Borders": "Περιγράμματα", + "Bottom": "Κάτω μέρος", + "Style [CSS]": "Στυλ [CSS]", + "Caption": "Λεζάντα", + "Cell Properties": "Ιδιότητες Κελιού", + "Center": "Κέντρο", + "Char": "Χαρακτήρας", + "Collapsed borders": "Συμπτυγμένα περιγράμματα", + "Color": "Χρώμα", + "Description": "Περιγραφή", + "FG Color": "Χρώμα αντικειμένων", + "Float": "Float", + "Frames": "Frames", + "Height": "Ύψος", + "How many columns would you like to merge?": "Πόσες στήλες θέλετε να ενώσετε;", + "How many rows would you like to merge?": "Πόσες γραμμές θέλετε να ενώσετε;", + "Image URL": "URL εικόνας", + "Justify": "Πλήρης στοίχηση", + "Layout": "Διάταξη", + "Left": "Αριστερά", + "Margin": "Περιθώριο", + "Middle": "Κέντρο", + "No rules": "Χωρίς Γραμμές", + "No sides": "No sides", + "None": "Τίποτα", + "Padding": "Εσοχή", + "Please click into some cell": "Κάντε κλικ μέσα σε κάποιο κελί", + "Right": "Δεξιά", + "Row Properties": "Ιδιότητες Γραμμής", + "Rules will appear between all rows and columns": "Γραμμές θα εμφανίζονται μεταξύ όλων των γραμμών και στηλών", + "Rules will appear between columns only": "Γραμμές θα εμφανίζονται μόνο μεταξύ στηλών", + "Rules will appear between rows only": "Γραμμές θα εμφανίζονται μόνο μεταξύ γραμμών", + "Rules": "Γραμμές", + "Spacing and padding": "Αποστάσεις και εσοχές", + "Spacing": "Αποστάσεις", + "Summary": "Σύνοψη", + "Delete cell": "Διαγραφή κελιού", + "Insert cell after": "Εισαγωγή κελιού μετά", + "Insert cell before": "Εισαγωγή κελιού πριν", + "Merge cells": "Συγχώνευση κελιών", + "Cell properties": "Ιδιότητες κελιού", + "Split cell": "Διαίρεση κελιού", + "Delete column": "Διαγραφή στήλης", + "Insert column after": "Εισαγωγή στήλης μετά", + "Insert column before": "Εισαγωγή στήλης πριν", + "Split column": "Διαίρεση στήλης", + "Delete row": "Διαγραφή γραμμής", + "Insert row before": "Εισαγωγή γραμμής μετά", + "Insert row after": "Εισαγωγή γραμμής πριν", + "Row properties": "Ιδιότητες γραμμής", + "Split row": "Διαίρεση γραμμής", + "Table properties": "Ιδιότητες πίνακα", + "Table Properties": "Ιδιότητες πίνακα", + "Text align": "Στοίχηση κειμένου", + "The bottom side only": "Η κάτω πλευρά μόνο", + "The left-hand side only": "Η αριστερή πλευρά μόνο", + "The right and left sides only": "Οι δεξιές και αριστερές πλευρές μόνο", + "The right-hand side only": "Η δεξιά πλευρά μόνο", + "The top and bottom sides only": "Οι πάνω και κάτω πλευρές μόνο", + "The top side only": "Η πάνω πλευρά μόνο", + "Top": "Πάνω", + "Unset color": "Αναίρεση χρώματος", + "Vertical align": "Κατακόρυφη στοίχηση", + "Width": "Πλάτος", + "HTMLArea cowardly refuses to delete the last cell in row.": "Δεν μπορεί να διαγραφεί το τελευταίο κελί σε μια γραμμή.", + "HTMLArea cowardly refuses to delete the last column in table.": "Δεν μπορεί να διαγραφεί η τελευταία στήλη σε ένα πίνακα.", + "HTMLArea cowardly refuses to delete the last row in table.": "Δεν μπορεί να διαγραφεί η τελευταία γραμμή σε ένα πίνακα.", + "percent": "τοις εκατόν", + "pixels": "pixels" +}; diff --git a/xinha/plugins/TableOperations/lang/fi.js b/xinha/plugins/TableOperations/lang/fi.js new file mode 100644 index 0000000..f7a946a --- /dev/null +++ b/xinha/plugins/TableOperations/lang/fi.js @@ -0,0 +1,68 @@ +// I18N constants +// LANG: "fi", ENCODING: UTF-8 +{ + "Align": "Kohdistus", + "All four sides": "Kaikki neljä sivua", + "Background": "Tausta", + "Baseline": "Takaraja", + "Border": "Reuna", + "Borders": "Reunat", + "Bottom": "Alle", + "Style [CSS]": "Tyyli [CSS]", + "Caption": "Otsikko", + "Cell Properties": "Solun asetukset", + "Center": "Keskelle", + "Char": "Merkki", + "Collapsed borders": "Luhistetut reunat", + "Color": "Väri", + "Description": "Kuvaus", + "FG Color": "FG Väri", + "Frames": "Kehykset", + "Image URL": "Kuvan osoite", + "Layout": "Sommittelu", + "Left": "Vasen", + "Margin": "Marginaali", + "Middle": "Keskelle", + "No rules": "Ei viivoja", + "No sides": "Ei sivuja", + "Padding": "Palstantäyte", + "Right": "Oikea", + "Row Properties": "Rivin asetukset", + "Rules will appear between all rows and columns": "Viivat jokaisen rivin ja sarakkeen välillä", + "Rules will appear between columns only": "Viivat ainoastaan sarakkeiden välillä", + "Rules will appear between rows only": "Viivat ainoastaan rivien välillä", + "Rules": "Viivat", + "Spacing": "Palstatila", + "Summary": "Yhteenveto", + "Delete cell": "Poista solu", + "Insert cell after": "Lisää solu perään", + "Insert cell before": "Lisää solu ennen", + "Merge cells": "Yhdistä solut", + "Cell properties": "Solun asetukset", + "Split cell": "Jaa solu", + "Delete column": "Poista sarake", + "Insert column after": "Lisää sarake perään", + "Insert column before": "Lisää sarake ennen", + "Split column": "Jaa sarake", + "Delete row": "Poista rivi", + "Insert row before": "Lisää rivi yläpuolelle", + "Insert row after": "Lisää rivi alapuolelle", + "Row properties": "Rivin asetukset", + "Split row": "Jaa rivi", + "Table properties": "Taulukon asetukset", + "Top": "Ylös", + "Table Properties": "Taulukon asetukset", + "The bottom side only": "Ainoastaan alapuolelle", + "The left-hand side only": "Ainoastaan vasenreuna", + "The right and left sides only": "Oikea- ja vasenreuna", + "The right-hand side only": "Ainoastaan oikeareuna", + "The top and bottom sides only": "Ylä- ja alapuoli.", + "The top side only": "Ainoastaan yläpuoli", + "Vertical align": "Vertikaali kohdistus", + "Width": "Leveys", + "HTMLArea cowardly refuses to delete the last cell in row.": "Ei voida poistaa viimeistä solua rivistä.", + "HTMLArea cowardly refuses to delete the last column in table.": "Ei voida poistaa viimeistä saraketta taulusta.", + "HTMLArea cowardly refuses to delete the last row in table.": "Ei voida poistaa viimeistä riviä taulusta.", + "percent": "prosenttia", + "pixels": "pikseliä" +}; diff --git a/xinha/plugins/TableOperations/lang/fr.js b/xinha/plugins/TableOperations/lang/fr.js new file mode 100644 index 0000000..edf9b22 --- /dev/null +++ b/xinha/plugins/TableOperations/lang/fr.js @@ -0,0 +1,78 @@ +// I18N constants +// LANG: "fr", ENCODING: UTF-8 +{ + "Align": "Aligner", + "All four sides": "Quatre cotés", + "Background": "Arrière plan", + "Baseline": "Ligne de base", + "Border": "Bordure", + "Borders": "Bordures", + "Bottom": "Bas", + "Style [CSS]": "Style [CSS]", + "Caption": "Étiquette", + "Cell Properties": "Propriétés de cellule", + "Center": "Centre", + "Char": "Charactère", + "Collapsed borders": "Bordure effondrés", + "Color": "Couleur", + "Description": "Description", + "FG Color": "Couleur de face", + "Float": "Flotteur", + "Frames": "Vues", + "Height": "Largeur", + "How many columns would you like to merge?": "Combien de colonnes voulez-vous fusionner?", + "How many rows would you like to merge?": "Combien de rangées voulez-vous fusionner?", + "Image URL": "URL pour l'image", + "Justify": "Justifié", + "Layout": "Arrangement", + "Left": "Gauche", + "Margin": "Marge", + "Middle": "Milieu", + "No rules": "Aucune règle", + "No sides": "Aucun côté", + "None": "Aucun", + "Padding": "Remplissage", + "Please click into some cell": "Cliquer sur une cellule", + "Right": "Droit", + "Row Properties": "Propriétés de rangée", + "Rules will appear between all rows and columns": "Règles entre les rangées et les cellules", + "Rules will appear between columns only": "Règles entre les colonnes seulement", + "Rules will appear between rows only": "Règles entre les rangées seulement", + "Rules": "Les règles", + "Spacing and padding": "Espacement et remplissage", + "Spacing": "Espacement", + "Summary": "Sommaire", + "Delete cell": "Supprimer une cellule", + "Insert cell after": "Insérer une cellule après", + "Insert cell before": "Insérer une cellule avant", + "Merge cells": "Fusionner les cellules", + "Cell properties": "Cell properties", + "Split cell": "Diviser la cellule", + "Delete column": "Supprimer la colonne", + "Insert column after": "Insérer une colonne après", + "Insert column before": "Insérer une colonne avant", + "Split column": "Diviser une colonne", + "Delete row": "Supprimer une rangée", + "Insert row before": "Insérer une rangée avant", + "Insert row after": "Insérer une rangée après", + "Row properties": "Propriétés de rangée", + "Split row": "Diviser la rangée", + "Table properties": "Propriétés de table", + "Table Properties": "Propriétés de table", + "Text align": "Alignement", + "The bottom side only": "Côté du bas seulement", + "The left-hand side only": "Côté gauche seulement", + "The right and left sides only": "Côté gauche et droit seulement", + "The right-hand side only": "Côté droit seulement", + "The top and bottom sides only": "Côté haut et bas seulement", + "The top side only": "Côté haut seulement", + "Top": "Haut", + "Unset color": "Enlever la couleur", + "Vertical align": "Vertical", + "Width": "Longeur", + "HTMLArea cowardly refuses to delete the last cell in row.": "Il est impossible de supprimer la dernière cellule de la rangée.", + "HTMLArea cowardly refuses to delete the last column in table.": "Il est impossible de supprimer la dernière colonne de la table.", + "HTMLArea cowardly refuses to delete the last row in table.": "Il est impossible de supprimer la dernière rangée de la table", + "percent": "%", + "pixels": "pixels" +}; \ No newline at end of file diff --git a/xinha/plugins/TableOperations/lang/he.js b/xinha/plugins/TableOperations/lang/he.js new file mode 100644 index 0000000..06d8d18 --- /dev/null +++ b/xinha/plugins/TableOperations/lang/he.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "he", ENCODING: UTF-8 +// Author: Liron Newman, http://www.eesh.net, +{ + "Align": "ישור", + "All four sides": "כל ארבעת הצדדים", + "Background": "רקע", + "Baseline": "קו בסיס", + "Border": "גבול", + "Borders": "גבולות", + "Bottom": "תחתון", + "Style [CSS]": "סגנון [CSS]", + "Caption": "כותרת", + "Cell Properties": "מאפייני תא", + "Center": "מרכז", + "Char": "תו", + "Collapsed borders": "גבולות קורסים", + "Color": "צבע", + "Description": "תיאור", + "FG Color": "צבע קידמה", + "Float": "מרחף", + "Frames": "מסגרות", + "Height": "גובה", + "How many columns would you like to merge?": "כמה טורים ברצונך למזג?", + "How many rows would you like to merge?": "כמה שורות ברצונך למזג?", + "Image URL": "URL התמונה", + "Justify": "ישור", + "Layout": "פריסה", + "Left": "שמאל", + "Margin": "שוליים", + "Middle": "אמצע", + "No rules": "ללא קווים", + "No sides": "ללא צדדים", + "None": "אין", + "Padding": "ריווח בשוליים", + "Please click into some cell": "אנא לחץ על תא כלשהו", + "Right": "ימין", + "Row Properties": "מאפייני שורה", + "Rules will appear between all rows and columns": "קווים יופיעו בין כל השורות והטורים", + "Rules will appear between columns only": "קווים יופיעו בין טורים בלבד", + "Rules will appear between rows only": "קווים יופיעו בין שורות בלבד", + "Rules": "קווים", + "Spacing and padding": "ריווח ושוליים", + "Spacing": "ריווח", + "Summary": "סיכום", + "Delete cell": "מחק תא", + "Insert cell after": "הכנס תא אחרי", + "Insert cell before": "הכנס תא לפני", + "Merge cells": "מזג תאים", + "Cell properties": "מאפייני תא", + "Split cell": "פצל תא", + "Delete column": "מחק טור", + "Insert column after": "הכנס טור אחרי", + "Insert column before": "הכנס טור לפני", + "Split column": "פצל טור", + "Delete row": "מחק שורה", + "Insert row before": "הכנס שורה לפני", + "Insert row after": "הכנס שורה אחרי", + "Row properties": "מאפייני שורה", + "Split row": "פצל שורה", + "Table properties": "מאפייני טבלה", + "Table Properties": "מאפייני טבלה", + "Text align": "ישור טקסט", + "The bottom side only": "הצד התחתון בלבד", + "The left-hand side only": "הצד השמאלי בלבד", + "The right and left sides only": "הצדדים הימני והשמאלי בלבד", + "The right-hand side only": "הצד הימני בלבד", + "The top and bottom sides only": "הצדדים העליון והתחתון בלבד", + "The top side only": "הצד העליון בלבד", + "Top": "עליון", + "Unset color": "צבע לא נבחר", + "Vertical align": "יישור אנכי", + "Width": "רוחב", + "HTMLArea cowardly refuses to delete the last cell in row.": "HTMLArea מסרב בפחדנות למחוק את התא האחרון בשורה.", + "HTMLArea cowardly refuses to delete the last column in table.": "HTMLArea מסרב בפחדנות למחוק את הטור האחרון בטבלה.", + "HTMLArea cowardly refuses to delete the last row in table.": "HTMLArea מסרב בפחדנות למחוק את השורה האחרונה בטבלה.", + "percent": "אחוז", + "pixels": "פיקסלים" +}; diff --git a/xinha/plugins/TableOperations/lang/it.js b/xinha/plugins/TableOperations/lang/it.js new file mode 100644 index 0000000..14f747b --- /dev/null +++ b/xinha/plugins/TableOperations/lang/it.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "it", ENCODING: UTF-8 +// Author: Fabio Rotondo +{ + "Align": "Allinea", + "All four sides": "Tutti e quattro i lati", + "Background": "Sfondo", + "Baseline": "Allineamento", + "Border": "Bordo", + "Borders": "Bordi", + "Bottom": "Basso", + "Style [CSS]": "Stile [CSS]", + "Caption": "Titolo", + "Cell Properties": "Proprietà della Cella", + "Center": "Centra", + "Char": "Carattere", + "Collapsed borders": "Bordi chiusi", + "Color": "Colore", + "Description": "Descrizione", + "FG Color": "Colore Principale", + "Float": "Fluttuante", + "Frames": "Frames", + "Height": "Altezza", + "How many columns would you like to merge?": "Quante colonne vuoi unire?", + "How many rows would you like to merge?": "Quante righe vuoi unire?", + "Image URL": "URL dell'Immagine", + "Justify": "Justifica", + "Layout": "Layout", + "Left": "Sinistra", + "Margin": "Margine", + "Middle": "Centrale", + "No rules": "Nessun righello", + "No sides": "Nessun lato", + "None": "Nulla", + "Padding": "Padding", + "Please click into some cell": "Per favore, clicca in una cella", + "Right": "Destra", + "Row Properties": "Proprietà della Riga", + "Rules will appear between all rows and columns": "Le linee appariranno tra tutte le righe e colonne", + "Rules will appear between columns only": "Le linee appariranno solo tra le colonne", + "Rules will appear between rows only": "Le linee appariranno solo tra le righe", + "Rules": "Linee", + "Spacing and padding": "Spaziatura e Padding", + "Spacing": "Spaziatura", + "Summary": "Sommario", + "Delete cell": "Cancella cella", + "Insert cell after": "Inserisci cella dopo", + "Insert cell before": "Inserisci cella prima", + "Merge cells": "Unisci celle", + "Cell properties": "Proprietà della cella", + "Split cell": "Dividi cella", + "Delete column": "Cancella colonna", + "Insert column after": "Inserisci colonna dopo", + "Insert column before": "Inserisci colonna prima", + "Split column": "Dividi colonna", + "Delete row": "Cancella riga", + "Insert row before": "Inserisci riga prima", + "Insert row after": "Inserisci riga dopo", + "Row properties": "Proprietà della riga", + "Split row": "Dividi riga", + "Table properties": "Proprietà della Tabella", + "Table Properties": "Proprietà della Tabella", + "Text align": "Allineamento del Testo", + "The bottom side only": "Solo la parte inferiore", + "The left-hand side only": "Solo la parte sinistra", + "The right and left sides only": "Solo destra e sinistra", + "The right-hand side only": "Solo la parte destra", + "The top and bottom sides only": "Solo sopra e sotto", + "The top side only": "Solo la parte sopra", + "Top": "Alto", + "Unset color": "Rimuovi colore", + "Vertical align": "Allineamento verticale", + "Width": "Larghezza", + "HTMLArea cowardly refuses to delete the last cell in row.": "HTMLArea si rifiuta codardamente di cancellare l'ultima cella nella riga.", + "HTMLArea cowardly refuses to delete the last column in table.": "HTMLArea si rifiuta codardamente di cancellare l'ultima colonna nella tabella.", + "HTMLArea cowardly refuses to delete the last row in table.": "HTMLArea si rifiuta codardamente di cancellare l'ultima riga nella tabella.", + "percent": "percento", + "pixels": "pixels" +}; diff --git a/xinha/plugins/TableOperations/lang/ja.js b/xinha/plugins/TableOperations/lang/ja.js new file mode 100644 index 0000000..5d24ab3 --- /dev/null +++ b/xinha/plugins/TableOperations/lang/ja.js @@ -0,0 +1,83 @@ +// I18N constants +// LANG: "ja", ENCODING: UTF-8 +{ + "Align": "行揃え", + "All four sides": "四辺すべて", + "Background": "背景", + "Baseline": "ベースライン", + "Border": "境界線", + "Borders": "境界線", + "Bottom": "下", + "Style [CSS]": "スタイル [CSS]", + "Caption": "キャプション", + "Cell Properties": "セルプロパティ", + "Center": "中央", + "Char": "文字", + "Collapsed borders": "隣接境界線を重ねる", + "Color": "色", + "Description": "説明", + "FG Color": "前景色", + "Float": "フロート", + "Frames": "外枠", + "Height": "高さ", + "How many columns would you like to merge?": "何列結合しますか?", + "How many rows would you like to merge?": "何行結合しますか?", + "Image URL": "画像URL", + "Justify": "両端揃え", + "Layout": "レイアウト", + "Left": "左", + "Margin": "間隔", + "Middle": "中", + "No rules": "区切りなし", + "No sides": "外枠なし", + "None": "なし", + "Padding": "余白", + "Please click into some cell": "いずれかのセル内をクリックしてください", + "Please select the cells you want to merge.": "結合したいセルを複数選択してください。", + "Right": "右", + "Row Properties": "行プロパティ", + "Rules will appear between all rows and columns": "すべての行間と列間に線を引く", + "Rules will appear between columns only": "列の間にのみ線を引く", + "Rules will appear between rows only": "行の間にのみ線を引く", + "Rules": "区切り", + "Spacing and padding": "間隔と余白", + "Spacing": "間隔", + "Summary": "要約", + "Delete cell": "セルの削除", + "Insert cell after": "次にセルを挿入", + "Insert cell before": "前にセルを挿入", + "Merge cells": "セルの結合", + "Cell properties": "セルのプロパティ", + "Split cell": "セルの分割", + "Delete column": "列の削除", + "Insert column after": "右に列を挿入", + "Insert column before": "左に列を挿入", + "Split column": "列の分割", + "Delete row": "行の削除", + "Insert row before": "上に行を挿入", + "Insert row after": "下に行を挿入", + "Row properties": "行のプロパティ", + "Split row": "行の分割", + "Table properties": "テーブルのプロパティ", + "Table Properties": "テーブルのプロパティ", + "Text align": "水平位置", + "The bottom side only": "下辺のみ", + "The left-hand side only": "左辺のみ", + "The right and left sides only": "左右辺のみ", + "The right-hand side only": "右辺のみ", + "The top and bottom sides only": "上下辺のみ", + "The top side only": "上辺のみ", + "Top": "上", + "Unset color": "色指定解除", + "Vertical align": "垂直位置", + "Width": "幅", + "HTMLArea cowardly refuses to delete the last cell in row.": "安全のために、行にひとつだけ残っている列の削除は拒否されます。", + "HTMLArea cowardly refuses to delete the last column in table.": "安全のために、テーブルにひとつだけ残っている列の削除は拒否されます。", + "HTMLArea cowardly refuses to delete the last row in table.": "安全のために、テーブルにひとつだけ残っている行の削除は拒否されます。", + "percent": "パーセント", + "pixels": "ピクセル", + "OK": "OK", + "Cancel": "中止", + "CSS Style": "CSSスタイル", + "Frame and borders": "外枠と境界線" +}; \ No newline at end of file diff --git a/xinha/plugins/TableOperations/lang/nb.js b/xinha/plugins/TableOperations/lang/nb.js new file mode 100644 index 0000000..5c973cb --- /dev/null +++ b/xinha/plugins/TableOperations/lang/nb.js @@ -0,0 +1,80 @@ +// I18N constants +// LANG: "nb", ENCODING: UTF-8 +// Author: Mihai Bazon, +// translated into Norwegian: ses@online.no 11.11.03 +{ + "Align": "Juster", + "All four sides": "Alle fire sider", + "Background": "Bakgrund", + "Baseline": "Grunnlinje", + "Border": "Kantlinje", + "Borders": "Kantlinjer", + "Bottom": "Bunn", + "Style [CSS]": "Stil [CSS]", + "Caption": "Overskrift", + "Cell Properties": "Celleegenskaper", + "Center": "Sentrer", + "Char": "Tegn", + "Collapsed borders": "Fjern kantlinjer", + "Color": "Farge", + "Description": "Beskrivelse", + "FG Color": "FG farge", + "Float": "Flytende", + "Frames": "rammer", + "Height": "Høyde", + "How many columns would you like to merge?": "Hvor mange kolonner vil du slå sammen?", + "How many rows would you like to merge?": "Hvor mange rader vil du slå sammen?", + "Image URL": "Bildets URL", + "Justify": "Juster", + "Layout": "Layout", + "Left": "Venstre", + "Margin": "Marg", + "Middle": "Midten", + "No rules": "Ingen linjal", + "No sides": "Ingen sider", + "None": "Ingen", + "Padding": "Luft", + "Please click into some cell": "Klikk i en eller annen celle", + "Right": "Høyre", + "Row Properties": "Egenskaper for rad", + "Rules will appear between all rows and columns": "Linjer vil synes mellom alle rader og kolonner", + "Rules will appear between columns only": "Linjer vil synes kun mellom kolonner", + "Rules will appear between rows only": "Linjer vil synes kun mellom rader", + "Rules": "Linjer", + "Spacing and padding": "Luft", + "Spacing": "Luft", + "Summary": "Sammendrag", + "Delete cell": "Slett celle", + "Insert cell after": "Sett inn celle etter", + "Insert cell before": "Sett inn celle foran", + "Merge cells": "Slå sammen celler", + "Cell properties": "Egenskaper for celle", + "Split cell": "Del celle", + "Delete column": "Slett kolonne", + "Insert column after": "Skyt inn kolonne etter", + "Insert column before": "Skyt inn kolonne før", + "Split column": "Del kolonne", + "Delete row": "Slett rad", + "Insert row before": "Skyt inn rad foran", + "Insert row after": "Skyt inn rad etter", + "Row properties": "Egenskaper for rad", + "Split row": "Del rad", + "Table properties": "Tabellegenskaper", + "Table Properties": "Tabellegenskaper", + "Text align": "Juster tekst", + "The bottom side only": "Bunnen kun", + "The left-hand side only": "Venstresiden kun", + "The right and left sides only": "Høyre- og venstresiden kun", + "The right-hand side only": "Høyresiden kun", + "The top and bottom sides only": "The top and bottom sides only", + "The top side only": "Overkanten kun", + "Top": "Overkant", + "Unset color": "Ikke-bestemt farge", + "Vertical align": "Vertikal justering", + "Width": "Bredde", + "HTMLArea cowardly refuses to delete the last cell in row.": "HTMLArea nekter å slette siste cellen i tabellen.", + "HTMLArea cowardly refuses to delete the last column in table.": "HTMLArea nekter å slette siste kolonnen i tabellen.", + "HTMLArea cowardly refuses to delete the last row in table.": "HTMLArea nekter å slette siste raden i tabellen.", + "percent": "prosent", + "pixels": "billedpunkter" +}; \ No newline at end of file diff --git a/xinha/plugins/TableOperations/lang/nl.js b/xinha/plugins/TableOperations/lang/nl.js new file mode 100644 index 0000000..b14d9fa --- /dev/null +++ b/xinha/plugins/TableOperations/lang/nl.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "nl", ENCODING: UTF-8 +// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl +{ + "Align": "Uitlijning", + "All four sides": "Alle 4 zijden", + "Background": "Achtergrond", + "Baseline": "Basis", + "Border": "Rand", + "Borders": "Randen", + "Bottom": "Onder", + "Style [CSS]": "CSS Style", + "Caption": "Opmerking", + "Cell Properties": "Celeigenschappen", + "Center": "Centreren", + "Char": "Karakter", + "Collapsed borders": "Geen randen", + "Color": "Kleur", + "Description": "Omschrijving", + "FG Color": "Voorgrond", + "Float": "Zwevend", + "Frames": "Frames", + "Height": "Hoogte", + "How many columns would you like to merge?": "Hoeveel kolommen wilt u samenvoegen?", + "How many rows would you like to merge?": "Hoeveel rijen wilt u samenvoegen?", + "Image URL": "Afbeelding URL", + "Justify": "Uitvullen", + "Layout": "Opmaak", + "Left": "Links", + "Margin": "Marge", + "Middle": "Midden", + "No rules": "Geen regels", + "No sides": "Geen zijlijnen", + "None": "Geen", + "Padding": "Celmarge", + "Please click into some cell": "Klik in een cel a.u.b.", + "Right": "Rechts", + "Row Properties": "Rijeigenschappen", + "Rules will appear between all rows and columns": "Regels verschijnen tussen alle rijen en kolommen", + "Rules will appear between columns only": "Regels verschijnen enkel tussen de kolommen", + "Rules will appear between rows only": "Regels verschijnen enkel tussen de rijen", + "Rules": "Regels", + "Spacing and padding": "Celmarge en afstand tussen cellen", + "Spacing": "marge", + "Summary": "Overzicht", + "Delete cell": "Cel verwijderen", + "Insert cell after": "Voeg cel toe achter", + "Insert cell before": "Voeg cel toe voor", + "Merge cells": "Cellen samenvoegen", + "Cell properties": "Celeigenschappen", + "Split cell": "Cel splitsen", + "Delete column": "Kolom verwijderen", + "Insert column after": "Kolom invoegen achter", + "Insert column before": "Kolom invoegen voor", + "Split column": "Kolom splitsen", + "Delete row": "Rij verwijderen", + "Insert row before": "Rij invoegen boven", + "Insert row after": "Rij invoegen onder", + "Row properties": "Rij eigenschappen", + "Split row": "Rij splitsen", + "Table properties": "Tabel eigenschappen", + "Table Properties": "Tabel eigenschappen", + "Text align": "Text uitlijning", + "The bottom side only": "Enkel aan de onderkant", + "The left-hand side only": "Enkel aan de linkerkant", + "The right and left sides only": "Enkel aan de linker en rechterkant", + "The right-hand side only": "Enkel aan de rechterkant", + "The top and bottom sides only": "Enkel aan de bovenen onderkant", + "The top side only": "Enkel aan de bovenkant", + "Top": "Boven", + "Unset color": "Wis kleur", + "Vertical align": "Vertikale uitlijning", + "Width": "Breedte", + "HTMLArea cowardly refuses to delete the last cell in row.": "HTMLArea kan de laatste cel in deze tabel niet verwijderen.", + "HTMLArea cowardly refuses to delete the last column in table.": "HTMLArea kan de laatste kolom in deze tabel niet verwijderen.", + "HTMLArea cowardly refuses to delete the last row in table.": "HTMLArea kan de laatste rij in deze tabel niet verwijderen.", + "percent": "procent", + "pixels": "pixels" +}; diff --git a/xinha/plugins/TableOperations/lang/pl.js b/xinha/plugins/TableOperations/lang/pl.js new file mode 100644 index 0000000..13eba48 --- /dev/null +++ b/xinha/plugins/TableOperations/lang/pl.js @@ -0,0 +1,83 @@ +// I18N constants +// LANG: "pl", ENCODING: UTF-8 +// translated: Krzysztof Kotowicz koto@webworkers.pl +{ + "Align": "Wyrównanie", + "All four sides": "Wszystkie 4 strony", + "Background": "Tło", + "Baseline": "Linia bazowa", + "Border": "Ramka", + "Borders": "Ramki", + "Bottom": "Dół", + "Style [CSS]": "Styl [CSS]", + "CSS Style": "Styl CSS", + "Caption": "Podpis", + "Cell Properties": "Właściwości komórki", + "Center": "Środek", + "Char": "Znak", + "Collapsed borders": "Ramki skolapsowane", + "Color": "Kolor", + "Description": "Opis", + "FG Color": "Kolor czcionek", + "Float": "Opływanie", + "Frames": "Ramki zewn.", + "Frame and borders": "Obramowania", + "Height": "Wysokość", + "How many columns would you like to merge?": "Ile kolumn chcesz scalić?", + "How many rows would you like to merge?": "Ile wierszy chcesz scalić?", + "Image URL": "URL obrazka", + "Justify": "Wyjustuj", + "Layout": "Layout", + "Left": "Lewo", + "Margin": "Margines", + "Middle": "Środek", + "No rules": "Bez wewnętrzych", + "No sides": "Bez ramek", + "None": "Brak", + "Padding": "Wcięcia", + "Please click into some cell": "Kliknij w jakąś komórkę", + "Right": "Prawo", + "Row Properties": "Właściwości wiersza", + "Rules will appear between all rows and columns": "Linie będą widoczne pomiędzy kolumnami i wierszami", + "Rules will appear between columns only": "Linie będą widoczne tylko pomiędzy kolumnami", + "Rules will appear between rows only": "Linie będą widoczne tylko pomiędzy wierszami", + "Rules": "Linie wewn.", + "Spacing and padding": "Spacjowanie", + "Spacing": "Odstęp", + "Summary": "Podsumowanie", + "Delete cell": "Usuń komórkę", + "Insert cell after": "Wstaw komórkę po", + "Insert cell before": "Wstaw komórkę przed", + "Merge cells": "Scal komórki", + "Cell properties": "Właściwości komórki", + "Split cell": "Rozdziel komórkę", + "Delete column": "Usuń kolumnę", + "Insert column after": "Wstaw kolumnę po", + "Insert column before": "Wstaw kolumnę przed", + "Split column": "Rozdziel kolumnę", + "Delete row": "Usuń wiersz", + "Insert row before": "Wstaw wiersz przed", + "Insert row after": "Wstaw wiersz po", + "Row properties": "Właściwości wiersza", + "Split row": "Rozdziel wiersz", + "Table properties": "Właściwości tabeli", + "Table Properties": "Właściwości tabeli", + "Text align": "Wyr. w poziomie", + "The bottom side only": "Tylko dolna linia", + "The left-hand side only": "Tylko lewa linia", + "The right and left sides only": "Lewa i prawa linia", + "The right-hand side only": "Tylko prawa linia", + "The top and bottom sides only": "Górna i dolna linia", + "The top side only": "Tylko górna linia", + "Top": "Góra", + "Unset color": "Usuń kolor", + "Vertical align": "Wyr. w pionie", + "Width": "Szerokość", + "HTMLArea cowardly refuses to delete the last cell in row.": "Nie możesz skasować ostatniej komórki w wierszu.", + "HTMLArea cowardly refuses to delete the last column in table.": "Nie możesz skasować ostatniej kolumny w tabeli.", + "HTMLArea cowardly refuses to delete the last row in table.": "Nie możesz skasować ostatniego wiersza w tabeli.", + "percent": "%", + "pixels": "pikseli", + "OK": "OK", + "Cancel": "Anuluj" +}; diff --git a/xinha/plugins/TableOperations/lang/ro.js b/xinha/plugins/TableOperations/lang/ro.js new file mode 100644 index 0000000..f896967 --- /dev/null +++ b/xinha/plugins/TableOperations/lang/ro.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "ro", ENCODING: UTF-8 +// Author: Mihai Bazon, http://dynarch.com/mishoo +{ + "Align": "Aliniere", + "All four sides": "Toate părţile", + "Background": "Fundal", + "Baseline": "Baseline", + "Border": "Chenar", + "Borders": "Chenare", + "Bottom": "Jos", + "Style [CSS]": "Stil [CSS]", + "Caption": "Titlu de tabel", + "Cell Properties": "Proprietăţile celulei", + "Center": "Centru", + "Char": "Caracter", + "Collapsed borders": "Chenare asimilate", + "Color": "Culoare", + "Description": "Descriere", + "FG Color": "Culoare text", + "Float": "Poziţie", + "Frames": "Chenare", + "Height": "Înălţimea", + "How many columns would you like to merge?": "Câte coloane vrei să uneşti?", + "How many rows would you like to merge?": "Câte linii vrei să uneşti?", + "Image URL": "URL-ul imaginii", + "Justify": "Justify", + "Layout": "Aranjament", + "Left": "Stânga", + "Margin": "Margine", + "Middle": "Mijloc", + "No rules": "Fără linii", + "No sides": "Fără părţi", + "None": "Nimic", + "Padding": "Spaţiere", + "Please click into some cell": "Vă rog să daţi click într-o celulă", + "Right": "Dreapta", + "Row Properties": "Proprietăţile liniei", + "Rules will appear between all rows and columns": "Vor apărea linii între toate rândurile şi coloanele", + "Rules will appear between columns only": "Vor apărea doar linii verticale", + "Rules will appear between rows only": "Vor apărea doar linii orizontale", + "Rules": "Linii", + "Spacing and padding": "Spaţierea", + "Spacing": "Între celule", + "Summary": "Sumar", + "Delete cell": "Şterge celula", + "Insert cell after": "Inserează o celulă la dreapta", + "Insert cell before": "Inserează o celulă la stânga", + "Merge cells": "Uneşte celulele", + "Cell properties": "Proprietăţile celulei", + "Split cell": "Împarte celula", + "Delete column": "Şterge coloana", + "Insert column after": "Inserează o coloană la dreapta", + "Insert column before": "Inserează o coloană la stânga", + "Split column": "Împarte coloana", + "Delete row": "Şterge rândul", + "Insert row before": "Inserează un rând înainte", + "Insert row after": "Inserează un rând după", + "Row properties": "Proprietăţile rândului", + "Split row": "Împarte rândul", + "Table properties": "Proprietăţile tabelei", + "Table Properties": "Proprietăţile tabelei", + "Text align": "Aliniere", + "The bottom side only": "Doar partea de jos", + "The left-hand side only": "Doar partea din stânga", + "The right and left sides only": "Partea din stânga şi cea din dreapta", + "The right-hand side only": "Doar partea din dreapta", + "The top and bottom sides only": "Partea de sus si cea de jos", + "The top side only": "Doar partea de sus", + "Top": "Sus", + "Unset color": "Dezactivează culoarea", + "Vertical align": "Aliniere pe verticală", + "Width": "Lăţime", + "HTMLArea cowardly refuses to delete the last cell in row.": "HTMLArea refuză cu laşitate să şteargă ultima celulă din rând.", + "HTMLArea cowardly refuses to delete the last column in table.": "HTMLArea refuză cu laşitate să şteargă ultima coloamă din tabela.", + "HTMLArea cowardly refuses to delete the last row in table.": "HTMLArea refuză cu laşitate să şteargă ultimul rând din tabela.", + "percent": "procente", + "pixels": "pixeli" +}; diff --git a/xinha/plugins/TableOperations/lang/ru.js b/xinha/plugins/TableOperations/lang/ru.js new file mode 100644 index 0000000..790aa2a --- /dev/null +++ b/xinha/plugins/TableOperations/lang/ru.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "ru", ENCODING: UTF-8 +// Author: Andrei Blagorazumov, a@fnr.ru +{ + "Align": "Выравнивание", + "All four sides": "Все 4 стороны", + "Background": "Фон", + "Baseline": "Базовая линия", + "Border": "Рамка", + "Borders": "Рамки", + "Bottom": "Низ", + "Style [CSS]": "Стиль [CSS]", + "Caption": "Заголовок", + "Cell Properties": "Свойства ячеек", + "Center": "Центр", + "Char": "Символ", + "Collapsed borders": "Накладывающиеся рамки", + "Color": "Цвет", + "Description": "Описание", + "FG Color": "Цвет переднего плана", + "Float": "Обтекание", + "Frames": "Фреймы", + "Height": "Высота", + "How many columns would you like to merge?": "Сколько столбцов вы хотите объединить?", + "How many rows would you like to merge?": "Сколько строк вы хотите объединить?", + "Image URL": "URL картинки", + "Justify": "По правому краю", + "Layout": "Раскладка", + "Left": "Лево", + "Margin": "Отступ", + "Middle": "Середина", + "No rules": "Нет линейки", + "No sides": "Нет сторон", + "None": "Ничего", + "Padding": "Поля", + "Please click into some cell": "Пожалуйста щелкните в некоторые ячейки", + "Right": "Право", + "Row Properties": "Свойства строк", + "Rules will appear between all rows and columns": "Линейки появятся между всеми строками и столбцами", + "Rules will appear between columns only": "Линейки появятся только между столбцами", + "Rules will appear between rows only": "Линейки появятся только между строками", + "Rules": "Линейки", + "Spacing and padding": "Поля и отступы", + "Spacing": "Отступы", + "Summary": "Сводка", + "Delete cell": "Удалить ячейку", + "Insert cell after": "Вставить ячейку после", + "Insert cell before": "Вставить ячейку до", + "Merge cells": "Объединить ячейки", + "Cell properties": "Свойства ячеек", + "Split cell": "Разделить ячейку", + "Delete column": "Удалить столбец", + "Insert column after": "Вставить столбец после", + "Insert column before": "Вставить столбец до", + "Split column": "Разделить столбец", + "Delete row": "Удалить строку", + "Insert row before": "Вставить строку до", + "Insert row after": "Вставить строку после", + "Row properties": "Свойства строки", + "Split row": "Разделить строку", + "Table properties": "Свойства таблиц", + "Table Properties": "Свойства таблиц", + "Text align": "Выравнивание теста", + "The bottom side only": "Только нижний край", + "The left-hand side only": "Только левый край", + "The right and left sides only": "Только левый и правый край", + "The right-hand side only": "Только правый край", + "The top and bottom sides only": "Только верхний и нижний край", + "The top side only": "Только верхний край", + "Top": "Верх", + "Unset color": "Отменить цвет", + "Vertical align": "Вертикальное выравнивание", + "Width": "Ширина", + "HTMLArea cowardly refuses to delete the last cell in row.": "HTMLArea отказалась удалять последнюю ячейку в строке.", + "HTMLArea cowardly refuses to delete the last column in table.": "HTMLArea отказалась удалять последний столбец в таблице.", + "HTMLArea cowardly refuses to delete the last row in table.": "HTMLArea отказалась удалять последнюю строку в таблице.", + "percent": "процентов", + "pixels": "пикселей" +}; \ No newline at end of file diff --git a/xinha/plugins/TableOperations/lang/sv.js b/xinha/plugins/TableOperations/lang/sv.js new file mode 100644 index 0000000..f3e1189 --- /dev/null +++ b/xinha/plugins/TableOperations/lang/sv.js @@ -0,0 +1,79 @@ +// I18N constants +// LANG: "sv" (Swedish), ENCODING: UTF-8 +// translated into Swedish: Erik Dalén, +{ + "Align": "Justera", + "All four sides": "Alla fyra sidor", + "Background": "Bakgrund", + "Baseline": "Baslinje", + "Border": "Kantlinje", + "Borders": "Kantlinjer", + "Bottom": "Botten", + "Style [CSS]": "Stil [CSS]", + "Caption": "Överskrift", + "Cell Properties": "Cellegenskaper", + "Center": "Centrera", + "Char": "Tecken", + "Collapsed borders": "Osynliga kantlinjer", + "Color": "Färg", + "Description": "Beskrivning", + "FG Color": "Förgrundsfärg", + "Float": "Flytande", + "Frames": "ramar", + "Height": "Höjd", + "How many columns would you like to merge?": "Hur många kolumner vill du slå samman?", + "How many rows would you like to merge?": "Hur många rader vill du slå samman?", + "Image URL": "Bildens URL", + "Justify": "Justera", + "Layout": "Layout", + "Left": "Venster", + "Margin": "Marginal", + "Middle": "Mitten", + "No rules": "Ingen linjal", + "No sides": "Inga sidor", + "None": "Ingen", + "Padding": "Luft", + "Please click into some cell": "Klicka i valfri cell", + "Right": "Höger", + "Row Properties": "Egenskaper for rad", + "Rules will appear between all rows and columns": "Linjaler kommer att synas mellan alla rader och kolumner", + "Rules will appear between columns only": "Linjaler kommer enbart synas mellan kolumner", + "Rules will appear between rows only": "Linjaler kommer enbart synas mellan rader", + "Rules": "Linjaler", + "Spacing and padding": "Mellanrum och luft", + "Spacing": "Mellanrum", + "Summary": "Sammandrag", + "Delete cell": "Radera cell", + "Insert cell after": "Infoga cell efter", + "Insert cell before": "Infoga cell före", + "Merge cells": "Slå samman celler", + "Cell properties": "Egenskaper for cell", + "Split cell": "Dela cell", + "Delete column": "Radera kolumn", + "Insert column after": "Infoga kolumn efter", + "Insert column before": "Infoga kolumn före", + "Split column": "Dela kolumn", + "Delete row": "Radera rad", + "Insert row before": "Infoga rad före", + "Insert row after": "Infoga rad efter", + "Row properties": "Egenskaper för rad", + "Split row": "Dela rad", + "Table properties": "Tabellegenskaper", + "Table Properties": "Tabellegenskaper", + "Text align": "Justera text", + "The bottom side only": "Nederkanten enbart", + "The left-hand side only": "Vänstersidan enbart", + "The right and left sides only": "Höger- och vänstersidan enbart", + "The right-hand side only": "Högersidan enbart", + "The top and bottom sides only": "Över- och nederkanten enbart", + "The top side only": "Överkanten enbart", + "Top": "Överkant", + "Unset color": "Obestämd färg", + "Vertical align": "Vertikal justering", + "Width": "Bredd", + "HTMLArea cowardly refuses to delete the last cell in row.": "Xinha nekar att radera sista cellen i tabellen.", + "HTMLArea cowardly refuses to delete the last column in table.": "Xinha nekar att radera sista kolumnen i tabellen.", + "HTMLArea cowardly refuses to delete the last row in table.": "Xinha nekar att radera sista raden i tabellen.", + "percent": "procent", + "pixels": "bildpunkter" +}; diff --git a/xinha/plugins/TableOperations/popups/merge_cells.html b/xinha/plugins/TableOperations/popups/merge_cells.html new file mode 100644 index 0000000..03bb2a8 --- /dev/null +++ b/xinha/plugins/TableOperations/popups/merge_cells.html @@ -0,0 +1,65 @@ + + + + + Merge Cells + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    +
    Merge Cells
    +
    + Merge current cell with: +
    Cells to the right, and
    Cells down
    +
    + + +
    +
    + + + diff --git a/xinha/plugins/TableOperations/table-operations.js b/xinha/plugins/TableOperations/table-operations.js new file mode 100644 index 0000000..aa7738c --- /dev/null +++ b/xinha/plugins/TableOperations/table-operations.js @@ -0,0 +1,893 @@ +function TableOperations(_1){ +this.editor=_1; +var _2=_1.config; +var bl=TableOperations.btnList; +var _4=this; +_2.removeToolbarElement(" inserttable toggleborders "); +var _5=["linebreak","inserttable","toggleborders"]; +for(var i=0;i
    "+HTMLArea._lc("Description","TableOperations")+"
    "+HTMLArea._lc("Caption","TableOperations")+":
    "+HTMLArea._lc("Summary","TableOperations")+":
    "+HTMLArea._lc("Spacing and padding","TableOperations")+" "+"
    "+HTMLArea._lc("Spacing","TableOperations")+":  "+HTMLArea._lc("Padding","TableOperations")+":   "+HTMLArea._lc("pixels","TableOperations")+"
    "+HTMLArea._lc("Frame and borders","TableOperations")+"
    "+HTMLArea._lc("Borders","TableOperations")+":   "+HTMLArea._lc("pixels","TableOperations")+"
    "+HTMLArea._lc("Frames","TableOperations")+":
    "+HTMLArea._lc("Rules","TableOperations")+":
    "; +var _27=TableOperations.createStyleFieldset(_1a.doc,_1a.editor,_12); +var p=_1a.doc.getElementById("--HA-style"); +p.appendChild(_27); +var _29=TableOperations.createStyleLayoutFieldset(_1a.doc,_1a.editor,_12); +p=_1a.doc.getElementById("--HA-layout"); +p.appendChild(_29); +_1a.modal=true; +_1a.addButtons("OK","Cancel"); +_1a.showAtElement(_1a.editor._iframe,"c"); +}); +}; +TableOperations.prototype.dialogRowCellProperties=function(_2a){ +var _2b=this.getClosest(_2a?"td":"tr"); +var _2c=this.getClosest("table"); +var _2d=new PopupWin(this.editor,_2a?HTMLArea._lc("Cell Properties","TableOperations"):HTMLArea._lc("Row Properties","TableOperations"),function(_2e,_2f){ +TableOperations.processStyle(_2f,_2b); +for(var i in _2f){ +if(typeof _2f[i]=="function"){ +continue; +} +var val=_2f[i]; +switch(i){ +case "f_align": +_2b.align=val; +break; +case "f_char": +_2b.ch=val; +break; +case "f_valign": +_2b.vAlign=val; +break; +} +} +_2e.editor.forceRedraw(); +_2e.editor.focusEditor(); +_2e.editor.updateToolbar(); +var _32=_2c.style.borderCollapse; +_2c.style.borderCollapse="collapse"; +_2c.style.borderCollapse="separate"; +_2c.style.borderCollapse=_32; +},function(_33){ +var _34=_2b.align; +var _35=_2b.vAlign; +var _36=_2b.ch; +function selected(val){ +return val?" selected":""; +} +_33.content.style.width="400px"; +_33.content.innerHTML="
    "+HTMLArea._lc(_2a?"Cell Properties":"Row Properties","TableOperations")+"
    "+"
    "; +var _38=TableOperations.createStyleFieldset(_33.doc,_33.editor,_2b); +var p=_33.doc.getElementById("--HA-style"); +p.appendChild(_38); +var _3a=TableOperations.createStyleLayoutFieldset(_33.doc,_33.editor,_2b); +p=_33.doc.getElementById("--HA-layout"); +p.appendChild(_3a); +_33.modal=true; +_33.addButtons("OK","Cancel"); +_33.showAtElement(_33.editor._iframe,"c"); +}); +}; +TableOperations.prototype.buttonPress=function(_3b,_3c){ +this.editor=_3b; +var _3d=HTMLArea.is_gecko?"
    ":""; +function clearRow(tr){ +var tds=tr.getElementsByTagName("td"); +for(var i=tds.length;--i>=0;){ +var td=tds[i]; +td.rowSpan=1; +td.innerHTML=_3d; +} +} +function splitRow(td){ +var n=parseInt(""+td.rowSpan); +var nc=parseInt(""+td.colSpan); +td.rowSpan=1; +tr=td.parentNode; +var itr=tr.rowIndex; +var trs=tr.parentNode.rows; +var _47=td.cellIndex; +while(--n>0){ +tr=trs[++itr]; +var otd=_3b._doc.createElement("td"); +otd.colSpan=td.colSpan; +otd.innerHTML=_3d; +tr.insertBefore(otd,tr.cells[_47]); +} +_3b.forceRedraw(); +_3b.updateToolbar(); +} +function splitCol(td){ +var nc=parseInt(""+td.colSpan); +td.colSpan=1; +tr=td.parentNode; +var ref=td.nextSibling; +while(--nc>0){ +var otd=_3b._doc.createElement("td"); +otd.rowSpan=td.rowSpan; +otd.innerHTML=_3d; +tr.insertBefore(otd,ref); +} +_3b.forceRedraw(); +_3b.updateToolbar(); +} +function splitCell(td){ +var nc=parseInt(""+td.colSpan); +splitCol(td); +var _4f=td.parentNode.cells; +var _50=td.cellIndex; +while(nc-->0){ +splitRow(_4f[_50++]); +} +} +function selectNextNode(el){ +var _52=el.nextSibling; +while(_52&&_52.nodeType!=1){ +_52=_52.nextSibling; +} +if(!_52){ +_52=el.previousSibling; +while(_52&&_52.nodeType!=1){ +_52=_52.previousSibling; +} +} +if(!_52){ +_52=el.parentNode; +} +_3b.selectNodeContents(_52); +} +function cellMerge(_53,_54,_55,_56,_57){ +var _58=[]; +var _59=[]; +try{ +for(i=_55;i<_55+_57;i++){ +var row=_53.rows[i]; +for(j=_54;j<_54+_56;j++){ +if(row.cells[j].colSpan>1||row.cells[j].rowSpan>1){ +splitCell(row.cells[j]); +} +_59.push(row.cells[j]); +} +if(_59.length>0){ +_58.push(_59); +_59=[]; +} +} +} +catch(e){ +alert("Invalid selection"); +return false; +} +var _5b=_58[0][0].parentNode.rowIndex; +var _5c=_58[_58.length-1][0].parentNode.rowIndex; +var _5d=_58[_58.length-1][0].rowSpan; +var _5e=""; +for(i=0;i<_58.length;++i){ +var _59=_58[i]; +for(var j=0;j<_59.length;++j){ +var _60=_59[j]; +_5e+=_60.innerHTML; +(i||j)&&(_60.parentNode.removeChild(_60)); +} +} +var td=_58[0][0]; +td.innerHTML=_5e; +td.rowSpan=_5c-_5b+_5d; +var _62=0; +for(j=0;j<_58[0].length;j++){ +_62+=_58[0][j].colSpan; +} +td.colSpan=_62; +_3b.selectNodeContents(td); +_3b.forceRedraw(); +_3b.focusEditor(); +} +switch(_3c){ +case "TO-row-insert-above": +case "TO-row-insert-under": +var tr=this.getClosest("tr"); +if(!tr){ +break; +} +var otr=tr.cloneNode(true); +clearRow(otr); +tr.parentNode.insertBefore(otr,/under/.test(_3c)?tr.nextSibling:tr); +_3b.forceRedraw(); +_3b.focusEditor(); +break; +case "TO-row-delete": +var tr=this.getClosest("tr"); +if(!tr){ +break; +} +var par=tr.parentNode; +if(par.rows.length==1){ +alert(HTMLArea._lc("HTMLArea cowardly refuses to delete the last row in table.","TableOperations")); +break; +} +selectNextNode(tr); +par.removeChild(tr); +_3b.forceRedraw(); +_3b.focusEditor(); +_3b.updateToolbar(); +break; +case "TO-row-split": +var td=this.getClosest("td"); +if(!td){ +break; +} +splitRow(td); +break; +case "TO-col-insert-before": +case "TO-col-insert-after": +var td=this.getClosest("td"); +if(!td){ +break; +} +var _67=td.parentNode.parentNode.rows; +var _68=td.cellIndex; +var _69=(td.parentNode.cells.length==_68+1); +for(var i=_67.length;--i>=0;){ +var tr=_67[i]; +var otd=_3b._doc.createElement("td"); +otd.innerHTML=_3d; +if(_69&&HTMLArea.is_ie){ +tr.insertBefore(otd); +}else{ +var ref=tr.cells[_68+(/after/.test(_3c)?1:0)]; +tr.insertBefore(otd,ref); +} +} +_3b.focusEditor(); +break; +case "TO-col-split": +var td=this.getClosest("td"); +if(!td){ +break; +} +splitCol(td); +break; +case "TO-col-delete": +var td=this.getClosest("td"); +if(!td){ +break; +} +var _68=td.cellIndex; +if(td.parentNode.cells.length==1){ +alert(HTMLArea._lc("HTMLArea cowardly refuses to delete the last column in table.","TableOperations")); +break; +} +selectNextNode(td); +var _67=td.parentNode.parentNode.rows; +for(var i=_67.length;--i>=0;){ +var tr=_67[i]; +tr.removeChild(tr.cells[_68]); +} +_3b.forceRedraw(); +_3b.focusEditor(); +_3b.updateToolbar(); +break; +case "TO-cell-split": +var td=this.getClosest("td"); +if(!td){ +break; +} +splitCell(td); +break; +case "TO-cell-insert-before": +case "TO-cell-insert-after": +var td=this.getClosest("td"); +if(!td){ +break; +} +var tr=td.parentNode; +var otd=_3b._doc.createElement("td"); +otd.innerHTML=_3d; +tr.insertBefore(otd,/after/.test(_3c)?td.nextSibling:td); +_3b.forceRedraw(); +_3b.focusEditor(); +break; +case "TO-cell-delete": +var td=this.getClosest("td"); +if(!td){ +break; +} +if(td.parentNode.cells.length==1){ +alert(HTMLArea._lc("HTMLArea cowardly refuses to delete the last cell in row.","TableOperations")); +break; +} +selectNextNode(td); +td.parentNode.removeChild(td); +_3b.forceRedraw(); +_3b.updateToolbar(); +break; +case "TO-cell-merge": +var sel=_3b._getSelection(); +if(!HTMLArea.is_ie&&sel.rangeCount>1){ +var _6e=sel.getRangeAt(0); +var td=_6e.startContainer.childNodes[_6e.startOffset]; +var tr=td.parentNode; +var _6f=td.cellIndex; +var _70=tr.rowIndex; +var _71=0; +var _72=_70; +var _73=0; +var _74=0; +var td2,tr2; +for(i=0;i_73){ +_73=_74; +} +if(tr2.rowIndex+td2.rowSpan-1>_71){ +_71=tr2.rowIndex+td2.rowSpan-1; +} +} +var _76=_71-_70+1; +var _77=tr.parentNode; +cellMerge(_77,_6f,_70,_73,_76); +}else{ +var td=this.getClosest("td"); +if(!td){ +alert(HTMLArea._lc("Please click into some cell","TableOperations")); +break; +} +_3b._popupDialog("plugin://TableOperations/merge_cells.html",function(_78){ +if(!_78){ +return false; +} +_73=parseInt(_78["f_cols"],10)+1; +_76=parseInt(_78["f_rows"],10)+1; +var tr=td.parentNode; +var _7a=td.cellIndex; +var _7b=tr.rowIndex; +var _7c=tr.parentNode; +cellMerge(_7c,_7a,_7b,_73,_76); +},null); +} +break; +case "TO-table-prop": +this.dialogTableProperties(); +break; +case "TO-row-prop": +this.dialogRowCellProperties(false); +break; +case "TO-cell-prop": +this.dialogRowCellProperties(true); +break; +default: +alert("Button ["+_3c+"] not yet implemented"); +} +}; +TableOperations.btnList=[["table-prop","table","Table properties"],null,["row-prop","tr","Row properties"],["row-insert-above","tr","Insert row before"],["row-insert-under","tr","Insert row after"],["row-delete","tr","Delete row"],["row-split","td[rowSpan!=1]","Split row"],null,["col-insert-before","td","Insert column before"],["col-insert-after","td","Insert column after"],["col-delete","td","Delete column"],["col-split","td[colSpan!=1]","Split column"],null,["cell-prop","td","Cell properties"],["cell-insert-before","td","Insert cell before"],["cell-insert-after","td","Insert cell after"],["cell-delete","td","Delete cell"],["cell-merge","tr","Merge cells"],["cell-split","td[colSpan!=1,rowSpan!=1]","Split cell"]]; +TableOperations.getLength=function(_7d){ +var len=parseInt(_7d); +if(isNaN(len)){ +len=""; +} +return len; +}; +TableOperations.processStyle=function(_7f,_80){ +var _81=_80.style; +for(var i in _7f){ +if(typeof _7f[i]=="function"){ +continue; +} +var val=_7f[i]; +switch(i){ +case "f_st_backgroundColor": +_81.backgroundColor=val; +break; +case "f_st_color": +_81.color=val; +break; +case "f_st_backgroundImage": +if(/\S/.test(val)){ +_81.backgroundImage="url("+val+")"; +}else{ +_81.backgroundImage="none"; +} +break; +case "f_st_borderWidth": +_81.borderWidth=val; +break; +case "f_st_borderStyle": +_81.borderStyle=val; +break; +case "f_st_borderColor": +_81.borderColor=val; +break; +case "f_st_borderCollapse": +_81.borderCollapse=val?"collapse":""; +break; +case "f_st_width": +if(/\S/.test(val)){ +_81.width=val+_7f["f_st_widthUnit"]; +}else{ +_81.width=""; +} +break; +case "f_st_height": +if(/\S/.test(val)){ +_81.height=val+_7f["f_st_heightUnit"]; +}else{ +_81.height=""; +} +break; +case "f_st_textAlign": +if(val=="char"){ +var ch=_7f["f_st_textAlignChar"]; +if(ch=="\""){ +ch="\\\""; +} +_81.textAlign="\""+ch+"\""; +}else{ +if(val=="-"){ +_81.textAlign=""; +}else{ +_81.textAlign=val; +} +} +break; +case "f_st_verticalAlign": +_80.vAlign=""; +if(val=="-"){ +_81.verticalAlign=""; +}else{ +_81.verticalAlign=val; +} +break; +case "f_st_float": +_81.cssFloat=val; +break; +} +} +}; +TableOperations.createColorButton=function(doc,_86,_87,_88){ +if(!_87){ +_87=""; +}else{ +if(!/#/.test(_87)){ +_87=HTMLArea._colorToRgb(_87); +} +} +var df=doc.createElement("span"); +var _8a=doc.createElement("input"); +_8a.type="hidden"; +df.appendChild(_8a); +_8a.name="f_st_"+_88; +_8a.value=_87; +var _8b=doc.createElement("span"); +_8b.className="buttonColor"; +df.appendChild(_8b); +var _8c=doc.createElement("span"); +_8c.className="chooser"; +_8c.style.backgroundColor=_87; +_8b.appendChild(_8c); +_8b.onmouseover=function(){ +if(!this.disabled){ +this.className+=" buttonColor-hilite"; +} +}; +_8b.onmouseout=function(){ +if(!this.disabled){ +this.className="buttonColor"; +} +}; +_8c.onclick=function(){ +if(this.parentNode.disabled){ +return false; +} +_86._popupDialog("select_color.html",function(_8d){ +if(_8d){ +_8c.style.backgroundColor="#"+_8d; +_8a.value="#"+_8d; +} +},_87); +}; +var _8e=doc.createElement("span"); +_8e.innerHTML="×"; +_8e.className="nocolor"; +_8e.title=HTMLArea._lc("Unset color","TableOperations"); +_8b.appendChild(_8e); +_8e.onmouseover=function(){ +if(!this.parentNode.disabled){ +this.className+=" nocolor-hilite"; +} +}; +_8e.onmouseout=function(){ +if(!this.parentNode.disabled){ +this.className="nocolor"; +} +}; +_8e.onclick=function(){ +_8c.style.backgroundColor=""; +_8a.value=""; +}; +return df; +}; +TableOperations.createStyleLayoutFieldset=function(doc,_90,el){ +var _92=doc.createElement("fieldset"); +var _93=doc.createElement("legend"); +_92.appendChild(_93); +_93.innerHTML=HTMLArea._lc("Layout","TableOperations"); +var _94=doc.createElement("table"); +_92.appendChild(_94); +_94.style.width="100%"; +var _95=doc.createElement("tbody"); +_94.appendChild(_95); +var _96=el.tagName.toLowerCase(); +var tr,td,input,select,option,options,i; +if(_96!="td"&&_96!="tr"&&_96!="th"){ +tr=doc.createElement("tr"); +_95.appendChild(tr); +td=doc.createElement("td"); +td.className="label"; +tr.appendChild(td); +td.innerHTML=HTMLArea._lc("Float","TableOperations")+":"; +td=doc.createElement("td"); +tr.appendChild(td); +select=doc.createElement("select"); +td.appendChild(select); +select.name="f_st_float"; +options=["None","Left","Right"]; +for(var i=0;i + + +Page Cleaner + + + + + + + +
    Page Cleaner
    + +
    +
    + Cleaning Area + Selection + All +
    +
    +
    + Cleaning options +
    +
    Formatting:
    + +

    +

    All HTML:
    + +

    +

    +

    +

    Select which types of formatting you would like to remove.

    + +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/xinha/plugins/UnFormat/un-format.js b/xinha/plugins/UnFormat/un-format.js new file mode 100644 index 0000000..eef48f3 --- /dev/null +++ b/xinha/plugins/UnFormat/un-format.js @@ -0,0 +1,65 @@ +// Unormat plugin for HTMLArea + + +function UnFormat(editor) { + this.editor = editor; + var cfg = editor.config; + var self = this; + + cfg.registerButton({ + id : "unformat", + tooltip : this._lc("Page Cleaner"), + image : editor.imgURL("unformat.gif", "UnFormat"), + textMode : false, + action : function(editor) { + self.buttonPress(editor); + } + }); + + cfg.addToolbarElement("unformat", "killword", 1); +} + +UnFormat._pluginInfo = { + name : "UnFormat", + version : "1.0", + license : "htmlArea" +}; + + +UnFormat.prototype._lc = function(string) { + return HTMLArea._lc(string, 'UnFormat'); +}; + +UnFormat.prototype.buttonPress = function(editor){ + editor._popupDialog( "plugin://UnFormat/unformat", function( param){ + if (param) { + if (param["cleaning_area"] == "all") { + var html = editor._doc.body.innerHTML; + } else { + var html = editor.getSelectedHTML(); + } + + if (param["html_all"]== true) { + html = html.replace(/<[\!]*?[^<>]*?>/g, ""); + } + + if (param["formatting"] == true) { + html = html.replace(/style="[^"]*"/gi, ""); + html = html.replace(/<\/?font[^>]*>/gi,""); + html = html.replace(/<\/?b>/gi,""); + html = html.replace(/<\/?strong[^>]*>/gi,""); + html = html.replace(/<\/?i>/gi,""); + html = html.replace(/<\/?em[^>]*>/gi,""); + html = html.replace(/<\/?u[^>]*>/gi,""); + html = html.replace(/<\/?strike[^>]*>/gi,""); + html = html.replace(/ align=[^\s|>]*/gi,""); + html = html.replace(/ class=[^\s|>]*/gi,""); + } + if (param["cleaning_area"] == "all") { + editor._doc.body.innerHTML = html; + } else { + editor.insertHTML(html); + } + } else { return false; } + }, null); +}; \ No newline at end of file diff --git a/xinha/popups/about.html b/xinha/popups/about.html new file mode 100644 index 0000000..2091075 --- /dev/null +++ b/xinha/popups/about.html @@ -0,0 +1,296 @@ + + + + + +About Xinha + + + + + + + +
    + +

    Xinha

    + +
    + +
    +
    + +
    + +

    A free WYSIWYG editor replacement for <textarea> fields.

    +

    Visit the Xinha Website for more information.

    + +

    + Use of Xinha is granted by the terms of the htmlArea License (based on BSD license) +

    +

    + Xinha was originally based on work by Mihai Bazon which is: +

    +
    Copyright (c) 2003-2004 dynarch.com.
    +    Copyright (c) 2002-2003 interactivetools.com, inc.
    +    This copyright notice MUST stay intact for use.
    + +
    + +
    + +

    + The development of Xinha would not have been possible without the original work of Mihai Bazon, InteractiveTools.com, and the many sponsors and contributors from around the world. +

    + +
    + +
    +
    htmlArea License (based on BSD license)
    +Copyright (c) 2002-2004, interactivetools.com, inc.
    +Copyright (c) 2003-2004 dynarch.com
    +All rights reserved.
    +
    +Redistribution and use in source and binary forms, with or without
    +modification, are permitted provided that the following conditions are met:
    +
    +1) Redistributions of source code must retain the above copyright notice,
    +   this list of conditions and the following disclaimer.
    +
    +2) Redistributions in binary form must reproduce the above copyright notice,
    +   this list of conditions and the following disclaimer in the documentation
    +   and/or other materials provided with the distribution.
    +
    +3) Neither the name of interactivetools.com, inc. nor the names of its
    +   contributors may be used to endorse or promote products derived from this
    +   software without specific prior written permission.
    +
    +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    +POSSIBILITY OF SUCH DAMAGE.
    +
    + +
    +
    +
    +
    + + +
    + +
    + +
    + + +
    + + +
    +
    About
    Thanks
    License
    Plugins
    Version
    + +
    + +
    + + diff --git a/xinha/popups/blank.html b/xinha/popups/blank.html new file mode 100644 index 0000000..5b1b16d --- /dev/null +++ b/xinha/popups/blank.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/xinha/popups/editor_help.html b/xinha/popups/editor_help.html new file mode 100644 index 0000000..ac4fb1a --- /dev/null +++ b/xinha/popups/editor_help.html @@ -0,0 +1,62 @@ + + + Editor Help + + + + + + + +
    Xinha Help
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Keyboard shortcuts
    + The editor provides the following key combinations: +
    ENTERnew paragraph(<P>)
    SHIFT-ENTERinsert linebreak(<BR>)
    CTRL-ASelect all
    CTRL-BBold
    CTRL-IItalic
    CTRL-UUnderline
    CTRL-SStrikethrough
    CTRL-LJustify Left
    CTRL-EJustify Center
    CTRL-RJustify Right
    CTRL-JJustify Full
    CTRL-ZUndoes your last action
    CTRL-YRedoes your last action
    CTRL-NSet format to paragraph
    CTRL-0 (zero)Clean content pasted from Word
    CTRL-1 .. CTRL-6Headings (<h1> .. <h6>)
    CTRL-XCut selection
    CTRL-CCopy selection
    CTRL-VPaste from clipboard
    +
    + +
    + + \ No newline at end of file diff --git a/xinha/popups/popup.css b/xinha/popups/popup.css new file mode 100644 index 0000000..7bf9358 --- /dev/null +++ b/xinha/popups/popup.css @@ -0,0 +1,39 @@ +html, body, .dialog { + background: ButtonFace; + color: ButtonText; + font: 11px Tahoma,Verdana,sans-serif; + margin: 0px; + padding: 0px; +} +body { padding: 5px; } +form { padding: 0px; margin: 0px; } +form p { + margin-top: 5px; + margin-bottom: 5px; +} +table { + font: 11px Tahoma,Verdana,sans-serif; +} +select, input, button { font: 11px Tahoma,Verdana,sans-serif; } +button { width: 70px; } +table .label { text-align: right; width: 8em; } + +.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; } +.fr { width: 7em; float: left; padding: 2px 5px; text-align: right; } +fieldset { padding: 0px 10px 5px 5px; } +.space { padding: 2px; } +.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px; +border-bottom: 1px solid black; letter-spacing: 2px; +} +.buttonColor { + padding: 1px; + cursor: default; + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} +#buttons { + margin-top: 1em; + border-top: 1px solid #999; + padding: 1em; + text-align: right; +} \ No newline at end of file diff --git a/xinha/popups/popup.js b/xinha/popups/popup.js new file mode 100644 index 0000000..ef2b4bb --- /dev/null +++ b/xinha/popups/popup.js @@ -0,0 +1,101 @@ +Xinha=window.opener.Xinha; +HTMLArea=window.opener.Xinha; +function getAbsolutePos(el){ +var r={x:el.offsetLeft,y:el.offsetTop}; +if(el.offsetParent){ +var _3=getAbsolutePos(el.offsetParent); +r.x+=_3.x; +r.y+=_3.y; +} +return r; +} +function comboSelectValue(c,_5){ +var _6=c.getElementsByTagName("option"); +for(var i=_6.length;--i>=0;){ +var op=_6[i]; +op.selected=(op.value==_5); +} +c.value=_5; +} +function __dlg_onclose(){ +opener.Dialog._return(null); +} +function __dlg_init(_9,_a){ +__xinha_dlg_init(_a); +} +function __xinha_dlg_init(_b){ +if(window.__dlg_init_done){ +return true; +} +if(window.opener._editor_skin){ +var _c=document.getElementsByTagName("head")[0]; +var _d=document.createElement("link"); +_d.type="text/css"; +_d.href=window.opener._editor_url+"skins/"+window.opener._editor_skin+"/skin.css"; +_d.rel="stylesheet"; +_c.appendChild(_d); +} +window.dialogArguments=opener.Dialog._arguments; +var _e=Xinha.pageSize(window); +if(!_b){ +_b={width:_e.x,height:_e.y}; +} +window.resizeTo(_b.width,_b.height); +var _f=Xinha.viewportSize(window); +window.resizeBy(0,_e.y-_f.y); +if(_b.top&&_b.left){ +window.moveTo(_b.left,_b.top); +}else{ +if(!Xinha.is_ie){ +var x=opener.screenX+(opener.outerWidth-_b.width)/2; +var y=opener.screenY+(opener.outerHeight-_b.height)/2; +}else{ +var x=(self.screen.availWidth-_b.width)/2; +var y=(self.screen.availHeight-_b.height)/2; +} +window.moveTo(x,y); +} +Xinha.addDom0Event(document.body,"keypress",__dlg_close_on_esc); +window.__dlg_init_done=true; +} +function __dlg_translate(_12){ +var _13=["input","select","legend","span","option","td","th","button","div","label","a","img"]; +for(var _14=0;_14<_13.length;++_14){ +var _15=document.getElementsByTagName(_13[_14]); +for(var i=_15.length;--i>=0;){ +var _17=_15[i]; +if(_17.firstChild&&_17.firstChild.data){ +var txt=Xinha._lc(_17.firstChild.data,_12); +if(txt){ +_17.firstChild.data=txt; +} +} +if(_17.title){ +var txt=Xinha._lc(_17.title,_12); +if(txt){ +_17.title=txt; +} +} +if(_17.tagName.toLowerCase()=="input"&&(/^(button|submit|reset)$/i.test(_17.type))){ +var txt=Xinha._lc(_17.value,_12); +if(txt){ +_17.value=txt; +} +} +} +} +document.title=Xinha._lc(document.title,_12); +} +function __dlg_close(val){ +opener.Dialog._return(val); +window.close(); +} +function __dlg_close_on_esc(ev){ +ev||(ev=window.event); +if(ev.keyCode==27){ +__dlg_close(null); +return false; +} +return true; +} + diff --git a/xinha/popups/select_color.html b/xinha/popups/select_color.html new file mode 100644 index 0000000..b64a484 --- /dev/null +++ b/xinha/popups/select_color.html @@ -0,0 +1,359 @@ + +Select Color + + + + + + + +
    + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + \ No newline at end of file diff --git a/xinha/release-notes.txt b/xinha/release-notes.txt new file mode 100644 index 0000000..8bd19b3 --- /dev/null +++ b/xinha/release-notes.txt @@ -0,0 +1,98 @@ +Xinha - The Community-Built Online HTML Editor + +For bug reports, forum, and updates go to +http://xinha.org + +Release History + +Xinha 0.93 + - fixed Ticket #967 Font Color Picker stops working after using one of ImageManager, ExtendedFileManager, FullPage, or HorizontalRule + - fixed Ticket #965 When switching between Xinhas in the same page, in textmode toolbar stays disabled + - fixwd Ticket #963 DOMwalk IE: head tag attributes without quotes and closing slash + - Ticket #962 DOMwalk Mozilla: improved source indentation + - fixed Ticket #957 If item in in xinha_editors is not a textarea: skip gracefully + - fixed Ticket #900: catch an fatal error that occured sometimes when switching between modes in fullpage mode in Mozilla + - fixed Ticket #969 DOMwalk Gecko: line breaks rendered as
    s inside
     blocks
    + - fixed Ticket #976 Loading message misplaced in IE7
    + - fixed Ticket #977 TableOperations toolbar off-place in ext_example.html
    + - fixed Ticket #978 defining a padding for s in global css affects Xinha framework
    + - Ticket #979 improve checking for non-supported browsers
    + - fixed Ticket #934 SuperClean plugin returns just quotation when executed on localhost
    + - Ticket #929 Save changes on page unload fixed for Mozilla 
    + - fixed Ticket #980 ImageManager color format bug
    + - fixed Ticket #981 No doctype in iframe content document/ editor always in quirks mode
    + - fixed Ticket #543 Stylist Panel overflow broken
    + - Ticket #983 added id for iframe
    + - fixed Ticket #984 !ExtendedFileManager produces php warning
    + - optimized icon file size
    + - fixed !JavaScript error in !ImageManager/!ExtendedFileManager image editor
    + - Ticket #908* Prompts broken in IE7: fixed for EFM, !ImageManager & !TableOperations
    + - Fixes for TableOperations, tickets #82, #908*, #912 and #947
    + - fixed Ticket #998* whitespace added before and/or after content (in non-fullpage mode)
    + - fixed slow unloading in Mozilla
    + - Fix focus problem when switching from html to wysiwyg in Gecko. See ticket #900.
    + - fixed toolbar floating issue
    + - fixed #1003 HTML length limited to 1024 characters with plugin CharCounter
    + - Ticket #1000 new public methods for getting/setting editor content
    + - fixed #735 - IE eating scripts and comments at the beginning of pages.
    + - Added new config variables to set iframe width if less than editor width (ticket:322) and set alignment of toolbar buttons.
    + - added Basque translation for XinhaCore
    + - prevent an error if server is set to parse .js files as PHP
    + - Ticket #127 plugin HtmlEntities: Entities.js  file corrupt
    +
    +Xinha 0.92beta
    + - fixed Ticket #831 stop empty anchors from being removed
    + - Make htmlarea.js just load XinhaCore.js instead of being a copy of it.
    + - fixed Ticket #445 Toggle TableBorder doesn't work if this.fullpage=true or using FullPage plugin
    + - fixed Ticket #551 shape and coord attributes of area element are ignored by IE
    + - fixed Ticket #650 SpellChecker is not compatible with FullPage plugin
    + - fixed Ticket #816 CharacterMap and ListType panel modes make editor jump to top in IE
    + - fixed Ticket #570 change behaviour of justify when an image is selected to make the image float left/right, 
    +   click the justify button again to undo it
    + - fixed Ticket #891 noscript content got escaped
    + - fixed Ticket #857 Firefox fails to load in fullpage mode when  tag in wrong place.
    + - fixed Ticket #841 Spell Checker - Won't return to xinha.
    + - fixed Ticket #914 All buttons stay grey & this.getParentElement is not a function message when not calling
    +   Xinha.loadPlugins() in xinha_init function
    + - fixed Ticket #911 Background color does not work in Firefox
    + - fixed Ticket #912 an error is thrown in Mozilla when clicking merge cells button and fewer than 2 cells are selected
    + - fixed Ticket #816 CharacterMap and ListType panel modes make editor jump to top in IE
    + - fixed Ticket #917 getHTMLWrapper in IE renders attributes like _stylist_usedtobe="[object Object]"
    + - fixed Ticket #556 stripBaseHref didn't work without baseHref defined explicitly.
    + - Update InsertPicture plugin Update
    + - fixed Ticket #921 EFM extended file manager - iframe height problem (IE)
    + - Ticket #923 colorPicker face lift & localisation
    + - fixed Ticket #924 EFM + ImageManager re-transforming of url to original image after automatic resize broken
    + - Ticket #900- retain editing position position between modes
    + - fixed Ticket #928 ImageManager fails if (another) Files.php exists in include path
    + - fixed Ticket #935 EFM demo_images php upload allowed: possible security risk
    + - Ticket #939 Japanese langage support 
    + - fixed Ticket #3 Horizontal Rule Selection
    + - Plugin ExtendedFileManager: added doc to allowed upload extensions
    + - Plugin PasteText update
    + - Plugin HtmlEntities: default preset iso-8859-1
    + - fixed Ticket #948 IE: inline styles are not rendered by DOMwalk getHTML()
    + - Plugin HorizontalRule update
    + - Plugin SaveSubmit update
    + - Plugin Linker update
    + - fixed Ticket #823 editor contents was not submitted when using JavaScript form.submit() without prior form.onsubmit()
    + - fixed Ticket #459 all body attributes removed in full page mode in FireFox
    + - _editor_url is now converted to absolute if it is relative. 
    + - fixed Ticket #594 IE: insertHTML() inserts HTML outside editor when editor is not focussed
    + - Ticket #954 FullScreen mode can now be called programmatically or on startup with or without button
    + - fixed Ticket #321 FullScreen : select elements show through in IE6 
    + - fixed Ticket #953 Statusbar has ugly white gap at the bottom when switching back from full screen in IE 
    + - fixed Ticket #952 FullScreen: scrollbars don't disappear in IE in QuirksMode
    + - fixed Ticket #603 Popop Dialog Height problems
    + - fixed Ticket #955 DOMwalk getHTML outputs empty attribute with value "true" instead of attribute name and some are skipped at all
    + 
    +Xinha 0.91beta
    + - changed namespace from HTMLArea to Xinha
    + - the core file is now named XinhaCore.js instead of htmlarea.js,
    +   please change your pages accordingly (the htmlarea.js will be removed!)
    + - the color picker script is now loaded on demand to reduce initial loading time
    + 
    +Xinha 0.9beta
    +This equals Xinha revision 635 of Jan 11 2007
    + - All JavaScript files over 2kb have been compressed using the dojo JavaScript compressor
    + - All gifs have been optimized using Trout's GIF Optimizer version 2.3
    \ No newline at end of file
    diff --git a/xinha/skins/blue-look/button-background.png b/xinha/skins/blue-look/button-background.png
    new file mode 100644
    index 0000000..9680684
    Binary files /dev/null and b/xinha/skins/blue-look/button-background.png differ
    diff --git a/xinha/skins/blue-look/separator.gif b/xinha/skins/blue-look/separator.gif
    new file mode 100644
    index 0000000..5ae3d59
    Binary files /dev/null and b/xinha/skins/blue-look/separator.gif differ
    diff --git a/xinha/skins/blue-look/skin.css b/xinha/skins/blue-look/skin.css
    new file mode 100644
    index 0000000..9f22add
    --- /dev/null
    +++ b/xinha/skins/blue-look/skin.css
    @@ -0,0 +1,98 @@
    +.htmlarea .toolbar, .htmlarea .toolbar .button
    +{
    +  background-color:#f7f8fd;
    +}
    +
    +.htmlarea .toolbarRow
    +{
    +  margin-top:2px;
    +  margin-bottom:2px;
    +  border:1px dotted #DEDEDE;
    +  padding:2px;
    +  -moz-border-radius:3px;
    +  margin:4px;
    +  height:25px;
    +}
    +
    +.htmlarea .toolbar .button
    +{
    +  background-image: url(button-background.png);
    +  width:20px;
    +  height:20px;
    +  padding:0px;
    +  border:1px solid #f7f8fd;
    +}
    +
    +.buttonImageContainer
    +{
    +  position:relative;
    +  left:1px;
    +  top :1px;
    +}
    +
    +.htmlarea .toolbar .separator {
    +  margin:0px;
    +  background-image: url(separator.gif);
    +  border:1px #f7f8fd;
    +  width:   7px;
    +  height: 20px;
    +  padding: 0px;
    +}
    +
    +.htmlarea .toolbar a.button:hover
    +{
    +  border: 1px solid;
    +  border-color: white #CCC #CCC white;
    +}
    +
    +.htmlarea .toolbar a.buttonDisabled:hover
    +{
    +  border-color: #f7f8fd;
    +}
    +
    +.htmlarea .toolbar .button.buttonActive,
    +.htmlarea .toolbar .button.buttonPressed
    +{
    +  border: 1px solid;
    +  border-color: #CCC white white #CCC;
    +}
    +
    +.htmlarea .statusBar {
    +  border-color: #CCC white white #CCC;
    +  padding: 0px;
    +  height:20px;
    +  background-image: url(button-background.png);
    +  background-repeat: repeat-x;
    +  background-color: #f7f8fd;
    +  color: ButtonText;
    +  font: 11px helvetica,arial,sans-serif;
    +}
    +
    +.htmlarea .statusBar .statusBarTree
    +{
    +  display:block;
    +  margin: 3px;
    +}
    +
    +.htmlarea .statusBar .statusBarTree a
    +{
    +  padding: 2px 5px;
    +  color: #00f;
    +  text-decoration:none;
    +}
    +
    +.htmlarea .panel h1
    +{
    +  background-image: url('button-background.png');
    +  background-repeat: repeat-x;
    +  background-color: #f7f8fd;
    +}
    +.dialog {
    +  background-color:#f7f8fd;
    +}
    +.dialog .title {
    +  background-image: url(button-background.png);
    +}  
    +.dialog button{
    +  background-image: url(button-background.png);
    +}
    \ No newline at end of file
    diff --git a/xinha/skins/blue-metallic/button-background.png b/xinha/skins/blue-metallic/button-background.png
    new file mode 100644
    index 0000000..41c18db
    Binary files /dev/null and b/xinha/skins/blue-metallic/button-background.png differ
    diff --git a/xinha/skins/blue-metallic/separator.gif b/xinha/skins/blue-metallic/separator.gif
    new file mode 100644
    index 0000000..bc9297a
    Binary files /dev/null and b/xinha/skins/blue-metallic/separator.gif differ
    diff --git a/xinha/skins/blue-metallic/skin.css b/xinha/skins/blue-metallic/skin.css
    new file mode 100644
    index 0000000..e798e47
    --- /dev/null
    +++ b/xinha/skins/blue-metallic/skin.css
    @@ -0,0 +1,96 @@
    +.htmlarea .toolbar { background-color:#f7f8fd;}
    +
    +.htmlarea .toolbarRow
    +{
    +  /*background-image: url(button-background.png);*/
    +  background-color: #C5DCEC;
    +  margin-top:2px;
    +  margin-bottom:2px;
    +  border:1px solid #7A8A99;
    +  padding:2px;
    +  -moz-border-radius:4px;
    +  margin:4px;
    +  height:25px;
    +}
    +
    +.htmlarea .toolbar .button {
    +  background-image: url(button-background.png);
    +  width:20px;
    +  height:21px;
    +  padding:1px;
    +  border:0px;
    +}
    +
    +.buttonImageContainer
    +{
    +  position:relative;
    +  left:1px;
    +  top :1px;
    +}
    +
    +.htmlarea .toolbar .separator
    +{
    +  margin:0px;
    +  background-image: url(separator.gif);
    +  border:1px #f7f8fd;
    +  width:   7px;
    +  height: 21px;
    +  padding: 0px;
    +}
    +
    +.htmlarea .toolbar a.button:hover,
    +.htmlarea .toolbar a.buttonDisabled:hover
    +{
    +  padding: 0px;
    +  border: 1px solid;
    +  border-color: #7A8A99;
    +}
    +
    +.htmlarea .toolbar .button.buttonActive,
    +.htmlarea .toolbar .button.buttonPressed
    +{
    +  padding: 0px;
    +  border: 1px solid;
    +  border-color: #79A4CC #FFFFFF #FFFFFF #79A4CC;
    +}
    +
    +.htmlarea .statusBar {
    +  border-color: #CCC white white #CCC;
    +  padding: 0px;
    +  height:20px;
    +  background-image: url(button-background.png);
    +  background-repeat: repeat-x;
    +  background-color: #f7f8fd;
    +  color: ButtonText;
    +  font: 11px helvetica,arial,sans-serif;
    +}
    +
    +.htmlarea .statusBar .statusBarTree
    +{
    +  display:block;
    +  margin: 3px;
    +}
    +
    +.htmlarea .statusBar .statusBarTree a
    +{
    +  padding: 2px 5px;
    +  color: #00f;
    +  text-decoration:none;
    +}
    +
    +.htmlarea .panel h1
    +{
    +  background-image: url('button-background.png');
    +  background-repeat: repeat-x;
    +  background-color: #f7f8fd;
    +}
    +
    +.dialog {
    +  background-color: #EEEEEE;
    +}
    +.dialog .title {
    +  background-image: url(button-background.png);
    +}
    +.dialog button{
    +  background-image: url(button-background.png);
    +}
    diff --git a/xinha/skins/green-look/button-background.gif b/xinha/skins/green-look/button-background.gif
    new file mode 100644
    index 0000000..d137119
    Binary files /dev/null and b/xinha/skins/green-look/button-background.gif differ
    diff --git a/xinha/skins/green-look/separator.gif b/xinha/skins/green-look/separator.gif
    new file mode 100644
    index 0000000..0357233
    Binary files /dev/null and b/xinha/skins/green-look/separator.gif differ
    diff --git a/xinha/skins/green-look/skin.css b/xinha/skins/green-look/skin.css
    new file mode 100644
    index 0000000..bbbec28
    --- /dev/null
    +++ b/xinha/skins/green-look/skin.css
    @@ -0,0 +1,88 @@
    +.htmlarea .toolbar, .htmlarea .toolbar .button
    +{
    +  background-color:#f8fdf8;
    +}
    +.htmlarea .toolbarRow
    +{
    +  margin-top:2px;
    +  margin-bottom:2px;
    +  border:1px dotted #DEDEDE;
    +  padding:2px;
    +  -moz-border-radius:3px;
    +  margin:4px;
    +  height:25px;
    +}
    +.htmlarea .toolbar .button
    +{
    +  background-image:url(button-background.gif);
    +  width:20px;
    +  height:20px;
    +  padding:0;
    +  border:1px solid #f8fdf8;
    +}
    +.buttonImageContainer
    +{
    +  position:relative;
    +  left:1px;
    +  top:1px;
    +}
    +.htmlarea .toolbar .separator {
    +  margin:0;
    +  background-image:url(separator.gif);
    +  border:1px #f8fdf8;
    +  width:7px;
    +  height:20px;
    +  padding:0;
    +}
    +.htmlarea .toolbar a.button:hover
    +{
    +  border:1px solid;
    +  border-color:#fff #ccc #ccc #fff;
    +}
    +.htmlarea .toolbar a.buttonDisabled:hover
    +{
    +  border-color:#f8fdf8;
    +}
    +.htmlarea .toolbar .buttonActive,
    +.htmlarea .toolbar .buttonPressed
    +{
    +  border:1px solid;
    +  border-color:#ccc #fff #fff #ccc;
    +  background:#ffb166;
    +}
    +.htmlarea .statusBar {
    +  border-color:#ccc #fff #fff #ccc;
    +  padding:0;
    +  height:20px;
    +  background-image:url(button-background.gif);
    +  background-repeat:repeat-x;
    +  background-color:#f8fdf8;
    +  color:ButtonText;
    +  font:11px helvetica,arial,sans-serif;
    +}
    +.htmlarea .statusBar .statusBarTree
    +{
    +  display:block;
    +  margin:3px;
    +}
    +.htmlarea .statusBar .statusBarTree a
    +{
    +  padding:2px 5px;
    +  color:#00f;
    +  text-decoration:none;
    +}
    +.htmlarea .panel h1
    +{
    +  background-image:url(button-background.gif);
    +  background-repeat:repeat-x;
    +  background-color:#f8fdf8;
    +}
    +.dialog {
    +  background-color:#f8fdf8;
    +}
    +.dialog .title {
    +  background-image: url(button-background.png);
    +}  
    +.dialog button{
    +  background-image: url(button-background.png);
    +}
    \ No newline at end of file
    diff --git a/xinha/skins/inditreuse/README b/xinha/skins/inditreuse/README
    new file mode 100644
    index 0000000..b66accd
    --- /dev/null
    +++ b/xinha/skins/inditreuse/README
    @@ -0,0 +1,9 @@
    +Skin inditreuse
    +Author: Kyle Kochis (http://completesiteservices.com/)
    +This work is licensed under the Creative Commons Attribution-ShareAlike License.
    +To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.0/
    +or send a letter to
    +Creative Commons,
    +559 Nathan Abbott Way
    +Stanford, California 94305
    +USA
    \ No newline at end of file
    diff --git a/xinha/skins/inditreuse/back.png b/xinha/skins/inditreuse/back.png
    new file mode 100644
    index 0000000..7a71fe6
    Binary files /dev/null and b/xinha/skins/inditreuse/back.png differ
    diff --git a/xinha/skins/inditreuse/button-background.png b/xinha/skins/inditreuse/button-background.png
    new file mode 100644
    index 0000000..5e4a827
    Binary files /dev/null and b/xinha/skins/inditreuse/button-background.png differ
    diff --git a/xinha/skins/inditreuse/hover.png b/xinha/skins/inditreuse/hover.png
    new file mode 100644
    index 0000000..5e45483
    Binary files /dev/null and b/xinha/skins/inditreuse/hover.png differ
    diff --git a/xinha/skins/inditreuse/selected.png b/xinha/skins/inditreuse/selected.png
    new file mode 100644
    index 0000000..5ade5f7
    Binary files /dev/null and b/xinha/skins/inditreuse/selected.png differ
    diff --git a/xinha/skins/inditreuse/separator.png b/xinha/skins/inditreuse/separator.png
    new file mode 100644
    index 0000000..cb77e5d
    Binary files /dev/null and b/xinha/skins/inditreuse/separator.png differ
    diff --git a/xinha/skins/inditreuse/skin.css b/xinha/skins/inditreuse/skin.css
    new file mode 100644
    index 0000000..f7c77e6
    --- /dev/null
    +++ b/xinha/skins/inditreuse/skin.css
    @@ -0,0 +1,73 @@
    +.htmlarea .toolbar {
    +	background-color:#889fc9;
    +  background-image:url(back.png);
    +  background-repeat:repeat-y;
    +}
    +.htmlarea .toolbarRow {
    +  margin-top:2px;
    +  margin-bottom:2px;
    +  background-image:url(button-background.png);
    +  height:25px;
    +}
    +.htmlarea .toolbar .button {
    +  width:20px;
    +  height:20px;
    +  padding:1px;
    +  border:none;
    +  background-image:url(button-background.png);
    +}
    +.buttonImageContainer {
    +  position:relative;
    +  left:1px;
    +  top:1px;
    +}
    +.htmlarea .toolbar .separator {
    +  margin:0;
    +  background-image: url(separator.png);
    +  width:7px;
    +  height:20px;
    +  padding:1px;
    +  border:none;
    +}
    +.htmlarea .toolbar a.button:hover {
    +  border:none !important;
    +  padding:1px;
    +  background-image:url(hover.png);
    +}
    +.htmlarea .toolbar .button.buttonPressed
    +{
    +  padding:1px;
    +  background-image:url(selected.png);
    +}
    +.htmlarea .statusBar {
    +  padding:0;
    +  height:20px;
    +  background-image:url(button-background.png);
    +  background-repeat:repeat-x;
    +  background-color:#889fc9;
    +  color:ButtonText;
    +  font:11px helvetica,arial,sans-serif;
    +}
    +.htmlarea .statusBar .statusBarTree {
    +  display:block;
    +  margin:3px;
    +}
    +.htmlarea .statusBar .statusBarTree a {
    +  padding:2px 5px;
    +  color:#00f;
    +  text-decoration:none;
    +}
    +.htmlarea .panel h1 {
    +  background-image:url(button-background.png);
    +  background-repeat:repeat-x;
    +  background-color:#889fc9;
    +}
    +.dialog {
    +  background-color:#889fc9;
    +}
    +.dialog .title {
    +  background-image: url(button-background.png);
    +}  
    +.dialog button{
    +  background-image: url(button-background.png);
    +}
    \ No newline at end of file
    diff --git a/xinha/skins/titan/README b/xinha/skins/titan/README
    new file mode 100644
    index 0000000..1272a27
    --- /dev/null
    +++ b/xinha/skins/titan/README
    @@ -0,0 +1,12 @@
    +Skin Titan, a modification of Skin inditreuse by Mike Harris (www.jonesstandard.org)
    +I simply changed the background to look more like nickel, and the dots on the separator have been replaced.  
    +Everything else is the same.
    +
    +Skin inditreuse Author: Kyle Kochis (http://completesiteservices.com/)
    +This work is licensed under the Creative Commons Attribution-ShareAlike License.
    +To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.0/
    +or send a letter to
    +Creative Commons,
    +559 Nathan Abbott Way
    +Stanford, California 94305
    +USA
    \ No newline at end of file
    diff --git a/xinha/skins/titan/back.png b/xinha/skins/titan/back.png
    new file mode 100644
    index 0000000..7a71fe6
    Binary files /dev/null and b/xinha/skins/titan/back.png differ
    diff --git a/xinha/skins/titan/button-background.png b/xinha/skins/titan/button-background.png
    new file mode 100644
    index 0000000..4ee6aae
    Binary files /dev/null and b/xinha/skins/titan/button-background.png differ
    diff --git a/xinha/skins/titan/hover.png b/xinha/skins/titan/hover.png
    new file mode 100644
    index 0000000..2e87d84
    Binary files /dev/null and b/xinha/skins/titan/hover.png differ
    diff --git a/xinha/skins/titan/selected.png b/xinha/skins/titan/selected.png
    new file mode 100644
    index 0000000..ffcf8a5
    Binary files /dev/null and b/xinha/skins/titan/selected.png differ
    diff --git a/xinha/skins/titan/separator.png b/xinha/skins/titan/separator.png
    new file mode 100644
    index 0000000..75e009f
    Binary files /dev/null and b/xinha/skins/titan/separator.png differ
    diff --git a/xinha/skins/titan/skin.css b/xinha/skins/titan/skin.css
    new file mode 100644
    index 0000000..cac3401
    --- /dev/null
    +++ b/xinha/skins/titan/skin.css
    @@ -0,0 +1,73 @@
    +.htmlarea .toolbar {
    +        background-color:#889fc9;
    +  background-image:url(back.png);
    +  background-repeat:repeat-y;
    +}
    +.htmlarea .toolbarRow {
    +  margin-top:2px;
    +  margin-bottom:2px;
    +  background-image:url(button-background.png);
    +  height:25px;
    +}
    +.htmlarea .toolbar .button {
    +  width:20px;
    +  height:20px;
    +  padding:1px;
    +  border:none;
    +  background-image:url(button-background.png);
    +}
    +.buttonImageContainer {
    +  position:relative;
    +  left:1px;
    +  top:1px;
    +}
    +.htmlarea .toolbar .separator {
    +  margin:0;
    +  background-image: url(separator.png);
    +  width:7px;
    +  height:20px;
    +  padding:1px;
    +  border:none;
    +}
    +.htmlarea .toolbar a.button:hover {
    +  border:none !important;
    +  padding:1px;
    +  background-image:url(hover.png);
    +}
    +.htmlarea .toolbar .button.buttonPressed
    +{
    +  padding:1px;
    +  background-image:url(selected.png);
    +}
    +.htmlarea .statusBar {
    +  padding:0;
    +  height:20px;
    +  background-image:url(button-background.png);
    +  background-repeat:repeat-x;
    +  background-color:#889fc9;
    +  color:ButtonText;
    +  font:11px helvetica,arial,sans-serif;
    +}
    +.htmlarea .statusBar .statusBarTree {
    +  display:block;
    +  margin:3px;
    +}
    +.htmlarea .statusBar .statusBarTree a {
    +  padding:2px 5px;
    +  color:#00f;
    +  text-decoration:none;
    +}
    +.htmlarea .panel h1 {
    +  background-image:url(button-background.png);
    +  background-repeat:repeat-x;
    +  background-color:#889fc9;
    +}
    +.dialog {
    +  background-color:#f7f8fd;
    +}
    +.dialog .title {
    +  background-image: url(button-background.png);
    +}  
    +.dialog button{
    +  background-image: url(button-background.png);
    +}
    \ No newline at end of file
    diff --git a/xinha/skins/xp-blue/back.png b/xinha/skins/xp-blue/back.png
    new file mode 100644
    index 0000000..478debb
    Binary files /dev/null and b/xinha/skins/xp-blue/back.png differ
    diff --git a/xinha/skins/xp-blue/button-background.png b/xinha/skins/xp-blue/button-background.png
    new file mode 100644
    index 0000000..69488d3
    Binary files /dev/null and b/xinha/skins/xp-blue/button-background.png differ
    diff --git a/xinha/skins/xp-blue/hover.png b/xinha/skins/xp-blue/hover.png
    new file mode 100644
    index 0000000..f55e355
    Binary files /dev/null and b/xinha/skins/xp-blue/hover.png differ
    diff --git a/xinha/skins/xp-blue/selected.png b/xinha/skins/xp-blue/selected.png
    new file mode 100644
    index 0000000..c0c3339
    Binary files /dev/null and b/xinha/skins/xp-blue/selected.png differ
    diff --git a/xinha/skins/xp-blue/separator.png b/xinha/skins/xp-blue/separator.png
    new file mode 100644
    index 0000000..02ceb37
    Binary files /dev/null and b/xinha/skins/xp-blue/separator.png differ
    diff --git a/xinha/skins/xp-blue/skin.css b/xinha/skins/xp-blue/skin.css
    new file mode 100644
    index 0000000..bd7b955
    --- /dev/null
    +++ b/xinha/skins/xp-blue/skin.css
    @@ -0,0 +1,76 @@
    +.htmlarea .toolbar {
    +	background-color:#c3daf9;
    +  background-image:url(back.png);
    +  background-repeat:repeat-y;
    +}
    +.htmlarea .toolbarRow {
    +  margin-top:2px;
    +  margin-bottom:2px;
    +  background-image:url(button-background.png);
    +  height:25px;  
    +}
    +.htmlarea .toolbar .button {
    +  width:20px;
    +  height:20px;
    +  padding:1px;
    +  border:none;
    +  background-image:url(button-background.png);
    +}
    +.buttonImageContainer {
    +  position:relative;
    +  left:1px;
    +  top:1px;
    +}
    +.htmlarea .toolbar .separator {
    +  margin:0;
    +  background-image:url(separator.png);
    +  width:7px;
    +  height:20px;
    +  padding:0;
    +}
    +.separator {
    +  border:none;
    +}
    +.htmlarea .toolbar a.button:hover {
    +  border:1px solid #003355;
    +  padding:0;
    +  background-image:url(hover.png);
    +}
    +.htmlarea .toolbar .button.buttonPressed
    +{
    +  border:1px solid #003355;
    +  padding:0;
    +  background-image:url(selected.png);
    +}
    +.htmlarea .statusBar {
    +  padding:0;
    +  height:20px;
    +  background-image:url(button-background.png);
    +  background-repeat:repeat-x;
    +  background-color:#c3daf9;
    +  color:ButtonText;
    +  font:11px helvetica,arial,sans-serif;
    +}
    +.htmlarea .statusBar .statusBarTree {
    +  display:block;
    +  margin:3px;
    +}
    +.htmlarea .statusBar .statusBarTree a {
    +  padding:2px 5px;
    +  color:#00f;
    +  text-decoration:none;
    +}
    +.htmlarea .panel h1 {
    +  background-image:url(button-background.png);
    +  background-repeat:repeat-x;
    +  background-color:#c3daf9;
    +}
    +.dialog {
    +  background-color:#c3daf9;
    +}
    +.dialog .title {
    +  background-image: url(button-background.png);
    +}  
    +.dialog button{
    +  background-image: url(button-background.png);
    +}
    \ No newline at end of file
    diff --git a/xinha/skins/xp-green/back.png b/xinha/skins/xp-green/back.png
    new file mode 100644
    index 0000000..0d0a749
    Binary files /dev/null and b/xinha/skins/xp-green/back.png differ
    diff --git a/xinha/skins/xp-green/button-background.png b/xinha/skins/xp-green/button-background.png
    new file mode 100644
    index 0000000..81a4657
    Binary files /dev/null and b/xinha/skins/xp-green/button-background.png differ
    diff --git a/xinha/skins/xp-green/hover.png b/xinha/skins/xp-green/hover.png
    new file mode 100644
    index 0000000..f55e355
    Binary files /dev/null and b/xinha/skins/xp-green/hover.png differ
    diff --git a/xinha/skins/xp-green/selected.png b/xinha/skins/xp-green/selected.png
    new file mode 100644
    index 0000000..c0c3339
    Binary files /dev/null and b/xinha/skins/xp-green/selected.png differ
    diff --git a/xinha/skins/xp-green/separator.png b/xinha/skins/xp-green/separator.png
    new file mode 100644
    index 0000000..18c5a57
    Binary files /dev/null and b/xinha/skins/xp-green/separator.png differ
    diff --git a/xinha/skins/xp-green/skin.css b/xinha/skins/xp-green/skin.css
    new file mode 100644
    index 0000000..9e4733c
    --- /dev/null
    +++ b/xinha/skins/xp-green/skin.css
    @@ -0,0 +1,76 @@
    +.htmlarea .toolbar {
    +  background-color:#f2f0e4;
    +  background-image:url(back.png);
    +  background-repeat:repeat-y;
    +}
    +.htmlarea .toolbarRow {
    +  margin-top:2px;
    +  margin-bottom:2px;
    +  background-image:url(button-background.png);
    +  height:25px;
    +}
    +.htmlarea .toolbar .button {
    +  width:20px;
    +  height:20px;
    +  padding:1px;
    +  border:none;
    +  background-image:url(button-background.png);
    +}
    +.buttonImageContainer {
    +  position:relative;
    +  left:1px;
    +  top:1px;
    +}
    +.htmlarea .toolbar .separator {
    +  margin:0;
    +  background-image:url(separator.png);
    +  width:7px;
    +  height:20px;
    +  padding:0;
    +}
    +.separator {
    +  border:none;
    +}
    +.htmlarea .toolbar a.button:hover {
    +  border:1px solid #335500;
    +  padding:0;
    +  background-image:url(hover.png);
    +}
    +.htmlarea .toolbar .button.buttonPressed
    +{
    +  border:1px solid #335500;
    +  padding:0;
    +  background-image:url(selected.png);
    +}
    +.htmlarea .statusBar {
    +  padding:0;
    +  height:20px;
    +  background-image:url(button-background.png);
    +  background-repeat:repeat-x;
    +  background-color:#f2f0e4;
    +  color:ButtonText;
    +  font:11px helvetica,arial,sans-serif;
    +}
    +.htmlarea .statusBar .statusBarTree {
    +  display:block;
    +  margin:3px;
    +}
    +.htmlarea .statusBar .statusBarTree a {
    +  padding:2px 5px;
    +  color:#00f;
    +  text-decoration:none;
    +}
    +.htmlarea .panel h1 {
    +  background-image:url(button-background.png);
    +  background-repeat:repeat-x;
    +  background-color:#f2f0e4;
    +}
    +.dialog {
    +  background-color:#f2f0e4;
    +}
    +.dialog .title {
    +  background-image: url(button-background.png);
    +}  
    +.dialog button{
    +  background-image: url(button-background.png);
    +}
    \ No newline at end of file