Compare commits
2 Commits
tags/PROD
...
tags/Makef
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5dd088d6c | ||
|
|
ca7ae759eb |
539
mozilla/security/nss/lib/freebl/GF2m_ecl.c
Normal file
@@ -0,0 +1,539 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial
|
||||
* field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
/*
|
||||
* GF2m_ecl.c: Contains an implementation of elliptic curve math library
|
||||
* for curves over GF2m.
|
||||
*
|
||||
* XXX Can be moved to a separate subdirectory later.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GF2m_ecl.h"
|
||||
#include "mpi/mplogic.h"
|
||||
#include "mpi/mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
GF2m_ec_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
GF2m_ec_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.2.
|
||||
* Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_add_aff(const mp_int *pp, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int lambda, xtemp, ytemp;
|
||||
unsigned int *p;
|
||||
int p_size;
|
||||
|
||||
p_size = mp_bpoly2arr(pp, p, 0) + 1;
|
||||
p = (unsigned int *) (malloc(sizeof(unsigned int) * p_size));
|
||||
if (p == NULL) goto cleanup;
|
||||
mp_bpoly2arr(pp, p, p_size);
|
||||
|
||||
CHECK_MPI_OK( mp_init(&lambda) );
|
||||
CHECK_MPI_OK( mp_init(&xtemp) );
|
||||
CHECK_MPI_OK( mp_init(&ytemp) );
|
||||
/* if P = inf, then R = Q */
|
||||
if (GF2m_ec_pt_is_inf_aff(px, py) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(qx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(qy, ry) );
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (GF2m_ec_pt_is_inf_aff(qx, qy) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(px, rx) );
|
||||
CHECK_MPI_OK( mp_copy(py, ry) );
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* if px != qx, then lambda = (py+qy) / (px+qx),
|
||||
* xtemp = a + lambda^2 + lambda + px + qx
|
||||
*/
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
CHECK_MPI_OK( mp_badd(py, qy, &ytemp) );
|
||||
CHECK_MPI_OK( mp_badd(px, qx, &xtemp) );
|
||||
CHECK_MPI_OK( mp_bdivmod(&ytemp, &xtemp, pp, p, &lambda) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(&lambda, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, &lambda, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, a, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, px, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, qx, &xtemp) );
|
||||
} else {
|
||||
/* if py != qy or qx = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qx) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* lambda = qx + qy / qx */
|
||||
CHECK_MPI_OK( mp_bdivmod(qy, qx, pp, p, &lambda) );
|
||||
CHECK_MPI_OK( mp_badd(&lambda, qx, &lambda) );
|
||||
/* xtemp = a + lambda^2 + lambda */
|
||||
CHECK_MPI_OK( mp_bsqrmod(&lambda, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, &lambda, &xtemp) );
|
||||
CHECK_MPI_OK( mp_badd(&xtemp, a, &xtemp) );
|
||||
}
|
||||
/* ry = (qx + xtemp) * lambda + xtemp + qy */
|
||||
CHECK_MPI_OK( mp_badd(qx, &xtemp, &ytemp) );
|
||||
CHECK_MPI_OK( mp_bmulmod(&ytemp, &lambda, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_badd(&ytemp, &xtemp, &ytemp) );
|
||||
CHECK_MPI_OK( mp_badd(&ytemp, qy, ry) );
|
||||
/* rx = xtemp */
|
||||
CHECK_MPI_OK( mp_copy(&xtemp, rx) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&xtemp);
|
||||
mp_clear(&ytemp);
|
||||
free(p);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q.
|
||||
* Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_sub_aff(const mp_int *pp, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int nqy;
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
CHECK_MPI_OK( mp_init(&nqy) );
|
||||
/* nqy = qx+qy */
|
||||
CHECK_MPI_OK( mp_badd(qx, qy, &nqy) );
|
||||
err = GF2m_ec_pt_add_aff(pp, a, px, py, qx, &nqy, rx, ry);
|
||||
cleanup:
|
||||
mp_clear(&nqy);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = 2P.
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_dbl_aff(const mp_int *pp, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
return GF2m_ec_pt_add_aff(pp, a, px, py, px, py, rx, ry);
|
||||
}
|
||||
|
||||
/* Gets the i'th bit in the binary representation of a.
|
||||
* If i >= length(a), then return 0.
|
||||
* (The above behaviour differs from mpl_get_bit, which
|
||||
* causes an error if i >= length(a).)
|
||||
*/
|
||||
#define MP_GET_BIT(a, i) \
|
||||
((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
|
||||
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3.
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_mul_aff(const mp_int *pp, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
unsigned int *p;
|
||||
int p_size;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&k3) );
|
||||
CHECK_MPI_OK( mp_init(&qx) );
|
||||
CHECK_MPI_OK( mp_init(&qy) );
|
||||
CHECK_MPI_OK( mp_init(&sx) );
|
||||
CHECK_MPI_OK( mp_init(&sy) );
|
||||
|
||||
p_size = mp_bpoly2arr(pp, p, 0) + 1;
|
||||
p = (unsigned int *) (malloc(sizeof(unsigned int) * p_size));
|
||||
if (p == NULL) goto cleanup;
|
||||
mp_bpoly2arr(pp, p, p_size);
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
CHECK_MPI_OK( mp_copy(px, &qx) );
|
||||
CHECK_MPI_OK( mp_copy(py, &qy) );
|
||||
CHECK_MPI_OK( mp_copy(n, &k) );
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
CHECK_MPI_OK( mp_badd(&qx, &qy, &qy) );
|
||||
CHECK_MPI_OK( mp_neg(&k, &k) );
|
||||
}
|
||||
#ifdef EC_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
mp_zero(&sx);
|
||||
mp_zero(&sy);
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_add_aff(pp, a, &sx, &sy, &qx, &qy, &sx, &sy) );
|
||||
}
|
||||
if (i > 0) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GF2m_ec_pt_dbl_aff(pp, a, &sx, &sy, &sx, &sy) );
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from standard */
|
||||
/* k3 = 3 * k */
|
||||
mp_set(&k3, 0x3);
|
||||
CHECK_MPI_OK( mp_mul(&k, &k3, &k3) );
|
||||
/* S = Q */
|
||||
CHECK_MPI_OK( mp_copy(&qx, &sx) );
|
||||
CHECK_MPI_OK( mp_copy(&qy, &sy) );
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GF2m_ec_pt_dbl_aff(pp, a, &sx, &sy, &sx, &sy) );
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_add_aff(pp, a, &sx, &sy, &qx, &qy, &sx, &sy) );
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_sub_aff(pp, a, &sx, &sy, &qx, &qy, &sx, &sy) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
CHECK_MPI_OK( mp_copy(&sx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(&sy, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
free(p);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
|
||||
* coordinates.
|
||||
* Uses algorithm Mdouble in appendix of
|
||||
* Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation".
|
||||
* modified to not require precomputation of c=b^{2^{m-1}}.
|
||||
*/
|
||||
static mp_err
|
||||
gf2m_Mdouble(const mp_int *pp, const unsigned int p[], const mp_int *a,
|
||||
const mp_int *b, mp_int *x, mp_int *z)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int t1;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
CHECK_MPI_OK( mp_init(&t1) );
|
||||
|
||||
CHECK_MPI_OK( mp_bsqrmod(x, p, x) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(z, p, &t1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(x, &t1, p, z) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(x, p, x) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(&t1, p, &t1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(b, &t1, p, &t1) );
|
||||
CHECK_MPI_OK( mp_badd(x, &t1, x) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&t1);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
|
||||
* projective coordinates.
|
||||
* Uses algorithm Madd in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation".
|
||||
*/
|
||||
static mp_err
|
||||
gf2m_Madd(const mp_int *pp, const unsigned int p[], const mp_int *a,
|
||||
const mp_int *b, const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2,
|
||||
mp_int *z2)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int t1, t2;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&t2) = 0;
|
||||
CHECK_MPI_OK( mp_init(&t1) );
|
||||
CHECK_MPI_OK( mp_init(&t2) );
|
||||
|
||||
CHECK_MPI_OK( mp_copy(x, &t1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(x1, z2, p, x1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(z1, x2, p, z1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(x1, z1, p, &t2) );
|
||||
CHECK_MPI_OK( mp_badd(z1, x1, z1) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(z1, p, z1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(z1, &t1, p, x1) );
|
||||
CHECK_MPI_OK( mp_badd(x1, &t2, x1) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&t1);
|
||||
mp_clear(&t2);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
|
||||
* using Montgomery point multiplication algorithm Mxy() in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation".
|
||||
* Returns:
|
||||
* 0 on error
|
||||
* 1 if return value should be the point at infinity
|
||||
* 2 otherwise
|
||||
*/
|
||||
static int
|
||||
gf2m_Mxy(const mp_int *pp, const unsigned int p[], const mp_int *a,
|
||||
const mp_int *b, const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1,
|
||||
mp_int *x2, mp_int *z2)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
int ret;
|
||||
mp_int t3, t4, t5;
|
||||
|
||||
MP_DIGITS(&t3) = 0;
|
||||
MP_DIGITS(&t4) = 0;
|
||||
MP_DIGITS(&t5) = 0;
|
||||
CHECK_MPI_OK( mp_init(&t3) );
|
||||
CHECK_MPI_OK( mp_init(&t4) );
|
||||
CHECK_MPI_OK( mp_init(&t5) );
|
||||
|
||||
if (mp_cmp_z(z1) == 0) {
|
||||
mp_zero(x2);
|
||||
mp_zero(z2);
|
||||
ret = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mp_cmp_z(z2) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(x, x2) );
|
||||
CHECK_MPI_OK( mp_badd(x, y, z2) );
|
||||
ret = 2;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mp_set(&t5, 0x1);
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(z1, z2, p, &t3) );
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(z1, x, p, z1) );
|
||||
CHECK_MPI_OK( mp_badd(z1, x1, z1) );
|
||||
CHECK_MPI_OK( mp_bmulmod(z2, x, p, z2) );
|
||||
CHECK_MPI_OK( mp_bmulmod(z2, x1, p, x1) );
|
||||
CHECK_MPI_OK( mp_badd(z2, x2, z2) );
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(z2, z1, p, z2) );
|
||||
CHECK_MPI_OK( mp_bsqrmod(x, p, &t4) );
|
||||
CHECK_MPI_OK( mp_badd(&t4, y, &t4) );
|
||||
CHECK_MPI_OK( mp_bmulmod(&t4, &t3, p, &t4) );
|
||||
CHECK_MPI_OK( mp_badd(&t4, z2, &t4) );
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(&t3, x, p, &t3) );
|
||||
CHECK_MPI_OK( mp_bdivmod(&t5, &t3, pp, p, &t3) );
|
||||
CHECK_MPI_OK( mp_bmulmod(&t3, &t4, p, &t4) );
|
||||
CHECK_MPI_OK( mp_bmulmod(x1, &t3, p, x2) );
|
||||
CHECK_MPI_OK( mp_badd(x2, x, z2) );
|
||||
|
||||
CHECK_MPI_OK( mp_bmulmod(z2, &t4, p, z2) );
|
||||
CHECK_MPI_OK( mp_badd(z2, y, z2) );
|
||||
|
||||
ret = 2;
|
||||
|
||||
cleanup:
|
||||
mp_clear(&t3);
|
||||
mp_clear(&t4);
|
||||
mp_clear(&t5);
|
||||
if (err == MP_OKAY) {
|
||||
return ret;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes R = nP based on algorithm 2P of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation".
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses Montgomery projective coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GF2m_ec_pt_mul_mont(const mp_int *pp, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int x1, x2, z1, z2;
|
||||
int i, j;
|
||||
mp_digit top_bit, mask;
|
||||
unsigned int *p;
|
||||
int p_size;
|
||||
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&x2) = 0;
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
CHECK_MPI_OK( mp_init(&x1) );
|
||||
CHECK_MPI_OK( mp_init(&x2) );
|
||||
CHECK_MPI_OK( mp_init(&z1) );
|
||||
CHECK_MPI_OK( mp_init(&z2) );
|
||||
|
||||
p_size = mp_bpoly2arr(pp, p, 0) + 1;
|
||||
p = (unsigned int *) (malloc(sizeof(unsigned int) * p_size));
|
||||
if (p == NULL) goto cleanup;
|
||||
mp_bpoly2arr(pp, p, p_size);
|
||||
|
||||
/* if result should be point at infinity */
|
||||
if ((mp_cmp_z(n) == 0) || (GF2m_ec_pt_is_inf_aff(px, py) == MP_YES)) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_set_inf_aff(rx, ry) );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
CHECK_MPI_OK( mp_copy(rx, &x2) ); /* x2 = rx */
|
||||
CHECK_MPI_OK( mp_copy(ry, &z2) ); /* z2 = ry */
|
||||
|
||||
CHECK_MPI_OK( mp_copy(px, &x1) ); /* x1 = px */
|
||||
mp_set(&z1, 0x1); /* z1 = 1 */
|
||||
CHECK_MPI_OK( mp_bsqrmod(&x1, p, &z2) ); /* z2 = x1^2 = x2^2 */
|
||||
CHECK_MPI_OK( mp_bsqrmod(&z2, p, &x2) );
|
||||
CHECK_MPI_OK( mp_badd(&x2, b, &x2) ); /* x2 = px^4 + b */
|
||||
|
||||
/* find top-most bit and go one past it */
|
||||
i = MP_USED(n) - 1;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
while (!(MP_DIGITS(n)[i] & mask)) {
|
||||
mask >>= 1;
|
||||
j--;
|
||||
}
|
||||
mask >>= 1; j--;
|
||||
|
||||
/* if top most bit was at word break, go to next word */
|
||||
if (!mask) {
|
||||
i--;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
for (; i >= 0; i--) {
|
||||
for (; j >= 0; j--) {
|
||||
if (MP_DIGITS(n)[i] & mask) {
|
||||
CHECK_MPI_OK( gf2m_Madd(pp, p, a, b, px, &x1, &z1, &x2, &z2) );
|
||||
CHECK_MPI_OK( gf2m_Mdouble(pp, p, a, b, &x2, &z2) );
|
||||
} else {
|
||||
CHECK_MPI_OK( gf2m_Madd(pp, p, a, b, px, &x2, &z2, &x1, &z1) );
|
||||
CHECK_MPI_OK( gf2m_Mdouble(pp, p, a, b, &x1, &z1) );
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
/* convert out of "projective" coordinates */
|
||||
i = gf2m_Mxy(pp, p, a, b, px, py, &x1, &z1, &x2, &z2);
|
||||
if (i == 0) {
|
||||
err = MP_BADARG;
|
||||
goto cleanup;
|
||||
} else if (i == 1) {
|
||||
CHECK_MPI_OK( GF2m_ec_pt_set_inf_aff(rx, ry) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_copy(&x2, rx) );
|
||||
CHECK_MPI_OK( mp_copy(&z2, ry) );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mp_clear(&x1);
|
||||
mp_clear(&x2);
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
free(p);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
96
mozilla/security/nss/lib/freebl/GF2m_ecl.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial
|
||||
* field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __gf2m_ecl_h_
|
||||
#define __gf2m_ecl_h_
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
#include "secmpi.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err GF2m_ec_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err GF2m_ec_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx, qy).
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err GF2m_ec_pt_add_aff(const mp_int *pp, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err GF2m_ec_pt_sub_aff(const mp_int *pp, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err GF2m_ec_pt_dbl_aff(const mp_int *pp, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses affine coordinates.
|
||||
*/
|
||||
mp_err GF2m_ec_pt_mul_aff(const mp_int *pp, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses Montgomery projective coordinates.
|
||||
*/
|
||||
mp_err GF2m_ec_pt_mul_mont(const mp_int *pp, const mp_int *a,
|
||||
const mp_int *b, const mp_int *px, const mp_int *py,
|
||||
const mp_int *n, mp_int *rx, mp_int *ry);
|
||||
|
||||
#define GF2m_ec_pt_is_inf(px, py) GF2m_ec_pt_is_inf_aff((px), (py))
|
||||
#define GF2m_ec_pt_add(p, a, px, py, qx, qy, rx, ry) \
|
||||
GF2m_ec_pt_add_aff((p), (a), (px), (py), (qx), (qy), (rx), (ry))
|
||||
|
||||
#define GF2m_ECL_MONTGOMERY
|
||||
#ifdef GF2m_ECL_AFFINE
|
||||
#define GF2m_ec_pt_mul(pp, a, b, px, py, n, rx, ry) \
|
||||
GF2m_ec_pt_mul_aff((pp), (a), (b), (px), (py), (n), (rx), (ry))
|
||||
#elif defined(GF2m_ECL_MONTGOMERY)
|
||||
#define GF2m_ec_pt_mul(pp, a, b, px, py, n, rx, ry) \
|
||||
GF2m_ec_pt_mul_mont((pp), (a), (b), (px), (py), (n), (rx), (ry))
|
||||
#endif /* GF2m_ECL_AFFINE or GF2m_ECL_MONTGOMERY */
|
||||
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
#endif /* __gf2m_ecl_h_ */
|
||||
647
mozilla/security/nss/lib/freebl/GFp_ecl.c
Normal file
@@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime
|
||||
* field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
/*
|
||||
* GFp_ecl.c: Contains an implementation of elliptic curve math library
|
||||
* for curves over GFp.
|
||||
*
|
||||
* XXX Can be moved to a separate subdirectory later.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GFp_ecl.h"
|
||||
#include "mpi/mplogic.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
GFp_ec_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
GFp_ec_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.1.
|
||||
* Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_add_aff(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int lambda, temp, xtemp, ytemp;
|
||||
|
||||
CHECK_MPI_OK( mp_init(&lambda) );
|
||||
CHECK_MPI_OK( mp_init(&temp) );
|
||||
CHECK_MPI_OK( mp_init(&xtemp) );
|
||||
CHECK_MPI_OK( mp_init(&ytemp) );
|
||||
/* if P = inf, then R = Q */
|
||||
if (GFp_ec_pt_is_inf_aff(px, py) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(qx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(qy, ry) );
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (GFp_ec_pt_is_inf_aff(qx, qy) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(px, rx) );
|
||||
CHECK_MPI_OK( mp_copy(py, ry) );
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* if px != qx, then lambda = (py-qy) / (px-qx) */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
CHECK_MPI_OK( mp_submod(py, qy, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_submod(px, qx, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_invmod(&xtemp, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_mulmod(&ytemp, &xtemp, p, &lambda) );
|
||||
} else {
|
||||
/* if py != qy or qy = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* lambda = (3qx^2+a) / (2qy) */
|
||||
CHECK_MPI_OK( mp_sqrmod(qx, p, &xtemp) );
|
||||
mp_set(&temp, 0x3);
|
||||
CHECK_MPI_OK( mp_mulmod(&xtemp, &temp, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_addmod(&xtemp, a, p, &xtemp) );
|
||||
mp_set(&temp, 0x2);
|
||||
CHECK_MPI_OK( mp_mulmod(qy, &temp, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_invmod(&ytemp, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_mulmod(&xtemp, &ytemp, p, &lambda) );
|
||||
}
|
||||
/* rx = lambda^2 - px - qx */
|
||||
CHECK_MPI_OK( mp_sqrmod(&lambda, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_submod(&xtemp, px, p, &xtemp) );
|
||||
CHECK_MPI_OK( mp_submod(&xtemp, qx, p, &xtemp) );
|
||||
/* ry = (x1-x2) * lambda - y1 */
|
||||
CHECK_MPI_OK( mp_submod(qx, &xtemp, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_mulmod(&ytemp, &lambda, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_submod(&ytemp, qy, p, &ytemp) );
|
||||
CHECK_MPI_OK( mp_copy(&xtemp, rx) );
|
||||
CHECK_MPI_OK( mp_copy(&ytemp, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&temp);
|
||||
mp_clear(&xtemp);
|
||||
mp_clear(&ytemp);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q.
|
||||
* Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_sub_aff(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int nqy;
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
CHECK_MPI_OK( mp_init(&nqy) );
|
||||
/* nqy = -qy */
|
||||
CHECK_MPI_OK( mp_neg(qy, &nqy) );
|
||||
err = GFp_ec_pt_add_aff(p, a, px, py, qx, &nqy, rx, ry);
|
||||
cleanup:
|
||||
mp_clear(&nqy);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = 2P.
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_dbl_aff(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
return GFp_ec_pt_add_aff(p, a, px, py, px, py, rx, ry);
|
||||
}
|
||||
|
||||
/* Gets the i'th bit in the binary representation of a.
|
||||
* If i >= length(a), then return 0.
|
||||
* (The above behaviour differs from mpl_get_bit, which
|
||||
* causes an error if i >= length(a).)
|
||||
*/
|
||||
#define MP_GET_BIT(a, i) \
|
||||
((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
|
||||
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3.
|
||||
* Elliptic curve points P and R can be identical.
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_mul_aff(const mp_int *p, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n, mp_int *rx,
|
||||
mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&k3) );
|
||||
CHECK_MPI_OK( mp_init(&qx) );
|
||||
CHECK_MPI_OK( mp_init(&qy) );
|
||||
CHECK_MPI_OK( mp_init(&sx) );
|
||||
CHECK_MPI_OK( mp_init(&sy) );
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
CHECK_MPI_OK( mp_copy(px, &qx) );
|
||||
CHECK_MPI_OK( mp_copy(py, &qy) );
|
||||
CHECK_MPI_OK( mp_copy(n, &k) );
|
||||
/* if n < 0 Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
CHECK_MPI_OK( mp_neg(&qy, &qy) );
|
||||
CHECK_MPI_OK( mp_mod(&qy, p, &qy) );
|
||||
CHECK_MPI_OK( mp_neg(&k, &k) );
|
||||
CHECK_MPI_OK( mp_mod(&k, p, &k) );
|
||||
}
|
||||
#ifdef EC_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
mp_zero(&sx);
|
||||
mp_zero(&sy);
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_add_aff(p, a, &sx, &sy,
|
||||
&qx, &qy, &sx, &sy) );
|
||||
}
|
||||
if (i > 0) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GFp_ec_pt_dbl_aff(p, a, &sx, &sy, &sx, &sy) );
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from standard */
|
||||
/* k3 = 3 * k */
|
||||
mp_set(&k3, 0x3);
|
||||
CHECK_MPI_OK( mp_mul(&k, &k3, &k3) );
|
||||
/* S = Q */
|
||||
CHECK_MPI_OK( mp_copy(&qx, &sx) );
|
||||
CHECK_MPI_OK( mp_copy(&qy, &sy) );
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GFp_ec_pt_dbl_aff(p, a, &sx, &sy, &sx, &sy) );
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_add_aff(p, a, &sx, &sy,
|
||||
&qx, &qy, &sx, &sy) );
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_sub_aff(p, a, &sx, &sy,
|
||||
&qx, &qy, &sx, &sy) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
CHECK_MPI_OK( mp_copy(&sx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(&sy, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). P and R can share x and y coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *p, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int z1, z2, z3;
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_DIGITS(&z3) = 0;
|
||||
CHECK_MPI_OK( mp_init(&z1) );
|
||||
CHECK_MPI_OK( mp_init(&z2) );
|
||||
CHECK_MPI_OK( mp_init(&z3) );
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (GFp_ec_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_set_inf_aff(rx, ry) );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz^2, py / pz^3) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(px, rx) );
|
||||
CHECK_MPI_OK( mp_copy(py, ry) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_invmod(pz, p, &z1) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&z1, p, &z2) );
|
||||
CHECK_MPI_OK( mp_mulmod(&z1, &z2, p, &z3) );
|
||||
CHECK_MPI_OK( mp_mulmod(px, &z2, p, rx) );
|
||||
CHECK_MPI_OK( mp_mulmod(py, &z3, p, ry) );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
mp_clear(&z3);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity.
|
||||
* Uses Jacobian coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_is_inf_jac(const mp_int *px, const mp_int *py, const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and
|
||||
* Q is (qx, qy, qz). Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses Jacobian coordinates.
|
||||
*
|
||||
* This routine implements Point Addition in the Jacobian Projective
|
||||
* space as described in the paper "Efficient elliptic curve exponentiation
|
||||
* using mixed coordinates", by H. Cohen, A Miyaji, T. Ono.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_add_jac(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, const mp_int *qz, mp_int *rx, mp_int *ry, mp_int *rz)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int n0, u1, u2, s1, s2, H, G;
|
||||
MP_DIGITS(&n0) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&s1) = 0;
|
||||
MP_DIGITS(&s2) = 0;
|
||||
MP_DIGITS(&H) = 0;
|
||||
MP_DIGITS(&G) = 0;
|
||||
CHECK_MPI_OK( mp_init(&n0) );
|
||||
CHECK_MPI_OK( mp_init(&u1) );
|
||||
CHECK_MPI_OK( mp_init(&u2) );
|
||||
CHECK_MPI_OK( mp_init(&s1) );
|
||||
CHECK_MPI_OK( mp_init(&s2) );
|
||||
CHECK_MPI_OK( mp_init(&H) );
|
||||
CHECK_MPI_OK( mp_init(&G) );
|
||||
|
||||
/* Use point double if pointers are equal. */
|
||||
if ((px == qx) && (py == qy) && (pz == qz)) {
|
||||
err = GFp_ec_pt_dbl_jac(p, a, px, py, pz, rx, ry, rz);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* If either P or Q is the point at infinity, then return
|
||||
* the other point
|
||||
*/
|
||||
if (GFp_ec_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
CHECK_MPI_OK( mp_copy(qx, rx) );
|
||||
CHECK_MPI_OK( mp_copy(qy, ry) );
|
||||
CHECK_MPI_OK( mp_copy(qz, rz) );
|
||||
goto cleanup;
|
||||
}
|
||||
if (GFp_ec_pt_is_inf_jac(qx, qy, qz) == MP_YES) {
|
||||
CHECK_MPI_OK( mp_copy(px, rx) );
|
||||
CHECK_MPI_OK( mp_copy(py, ry) );
|
||||
CHECK_MPI_OK( mp_copy(pz, rz) );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Compute u1 = px * qz^2, s1 = py * qz^3 */
|
||||
if (mp_cmp_d(qz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(px, &u1) );
|
||||
CHECK_MPI_OK( mp_copy(py, &s1) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_sqrmod(qz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(px, &n0, p, &u1) );
|
||||
CHECK_MPI_OK( mp_mulmod(&n0, qz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(py, &n0, p, &s1) );
|
||||
}
|
||||
|
||||
/* Compute u2 = qx * pz^2, s2 = qy * pz^3 */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_copy(qx, &u2) );
|
||||
CHECK_MPI_OK( mp_copy(qy, &s2) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_sqrmod(pz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(qx, &n0, p, &u2) );
|
||||
CHECK_MPI_OK( mp_mulmod(&n0, pz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(qy, &n0, p, &s2) );
|
||||
}
|
||||
|
||||
/* Compute H = u2 - u1 ; G = s2 - s1 */
|
||||
CHECK_MPI_OK( mp_submod(&u2, &u1, p, &H) );
|
||||
CHECK_MPI_OK( mp_submod(&s2, &s1, p, &G) );
|
||||
|
||||
if (mp_cmp_z(&H) == 0) {
|
||||
if (mp_cmp_z(&G) == 0) {
|
||||
/* P = Q; double */
|
||||
err = GFp_ec_pt_dbl_jac(p, a, px, py, pz,
|
||||
rx, ry, rz);
|
||||
goto cleanup;
|
||||
} else {
|
||||
/* P = -Q; return point at infinity */
|
||||
CHECK_MPI_OK( GFp_ec_pt_set_inf_jac(rx, ry, rz) );
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
if (mp_cmp_d(qz, 1) == 0) {
|
||||
/* if pz == qz == 1, then rz = H */
|
||||
CHECK_MPI_OK( mp_copy(&H, rz) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_mulmod(qz, &H, p, rz) );
|
||||
}
|
||||
} else {
|
||||
if (mp_cmp_d(qz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_mulmod(pz, &H, p, rz) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_mulmod(pz, qz, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(&n0, &H, p, rz) );
|
||||
}
|
||||
}
|
||||
|
||||
/* rx = G^2 - H^3 - 2 * u1 * H^2 */
|
||||
CHECK_MPI_OK( mp_sqrmod(&G, p, rx) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&H, p, &n0) );
|
||||
CHECK_MPI_OK( mp_mulmod(&n0, &u1, p, &u1) );
|
||||
CHECK_MPI_OK( mp_addmod(&u1, &u1, p, &u2) );
|
||||
CHECK_MPI_OK( mp_mulmod(&H, &n0, p, &H) );
|
||||
CHECK_MPI_OK( mp_submod(rx, &H, p, rx) );
|
||||
CHECK_MPI_OK( mp_submod(rx, &u2, p, rx) );
|
||||
|
||||
/* ry = - s1 * H^3 + G * (u1 * H^2 - rx) */
|
||||
/* (formula based on values of variables before block above) */
|
||||
CHECK_MPI_OK( mp_submod(&u1, rx, p, &u1) );
|
||||
CHECK_MPI_OK( mp_mulmod(&G, &u1, p, ry) );
|
||||
CHECK_MPI_OK( mp_mulmod(&s1, &H, p, &s1) );
|
||||
CHECK_MPI_OK( mp_submod(ry, &s1, p, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&n0);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&s1);
|
||||
mp_clear(&s2);
|
||||
mp_clear(&H);
|
||||
mp_clear(&G);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Jacobian coordinates.
|
||||
*
|
||||
* This routine implements Point Doubling in the Jacobian Projective
|
||||
* space as described in the paper "Efficient elliptic curve exponentiation
|
||||
* using mixed coordinates", by H. Cohen, A Miyaji, T. Ono.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_dbl_jac(const mp_int *p, const mp_int *a, const mp_int *px,
|
||||
const mp_int *py, const mp_int *pz, mp_int *rx, mp_int *ry, mp_int *rz)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int t0, t1, M, S;
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&M) = 0;
|
||||
MP_DIGITS(&S) = 0;
|
||||
CHECK_MPI_OK( mp_init(&t0) );
|
||||
CHECK_MPI_OK( mp_init(&t1) );
|
||||
CHECK_MPI_OK( mp_init(&M) );
|
||||
CHECK_MPI_OK( mp_init(&S) );
|
||||
|
||||
if (GFp_ec_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_set_inf_jac(rx, ry, rz) );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
/* M = 3 * px^2 + a */
|
||||
CHECK_MPI_OK( mp_sqrmod(px, p, &t0) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &t0, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &M, p, &t0) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, a, p, &M) );
|
||||
} else if (mp_cmp_int(a, -3) == 0) {
|
||||
/* M = 3 * (px + pz^2) * (px - pz) */
|
||||
CHECK_MPI_OK( mp_sqrmod(pz, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(px, &M, p, &t0) );
|
||||
CHECK_MPI_OK( mp_submod(px, &M, p, &t1) );
|
||||
CHECK_MPI_OK( mp_mulmod(&t0, &t1, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(&M, &M, p, &t0) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &M, p, &M) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_sqrmod(px, p, &t0) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &t0, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(&t0, &M, p, &t0) );
|
||||
CHECK_MPI_OK( mp_sqrmod(pz, p, &M) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&M, p, &M) );
|
||||
CHECK_MPI_OK( mp_mulmod(&M, a, p, &M) );
|
||||
CHECK_MPI_OK( mp_addmod(&M, &t0, p, &M) );
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
CHECK_MPI_OK( mp_addmod(py, py, p, rz) );
|
||||
CHECK_MPI_OK( mp_sqrmod(rz, p, &t0) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_addmod(py, py, p, &t0) );
|
||||
CHECK_MPI_OK( mp_mulmod(&t0, pz, p, rz) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&t0, p, &t0) );
|
||||
}
|
||||
|
||||
/* S = 4 * px * py^2 = pz * (2 * py)^2 */
|
||||
CHECK_MPI_OK( mp_mulmod(px, &t0, p, &S) );
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
CHECK_MPI_OK( mp_addmod(&S, &S, p, &t1) );
|
||||
CHECK_MPI_OK( mp_sqrmod(&M, p, rx) );
|
||||
CHECK_MPI_OK( mp_submod(rx, &t1, p, rx) );
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
CHECK_MPI_OK( mp_sqrmod(&t0, p, &t1) );
|
||||
if (mp_isodd(&t1)) {
|
||||
CHECK_MPI_OK( mp_add(&t1, p, &t1) );
|
||||
}
|
||||
CHECK_MPI_OK( mp_div_2(&t1, &t1) );
|
||||
CHECK_MPI_OK( mp_submod(&S, rx, p, &S) );
|
||||
CHECK_MPI_OK( mp_mulmod(&M, &S, p, &M) );
|
||||
CHECK_MPI_OK( mp_submod(&M, &t1, p, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
mp_clear(&M);
|
||||
mp_clear(&S);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses Jacobian coordinates.
|
||||
*/
|
||||
mp_err
|
||||
GFp_ec_pt_mul_jac(const mp_int *p, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err err = MP_OKAY;
|
||||
mp_int k, qx, qy, qz, sx, sy, sz;
|
||||
int i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&qz) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_DIGITS(&sz) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&qx) );
|
||||
CHECK_MPI_OK( mp_init(&qy) );
|
||||
CHECK_MPI_OK( mp_init(&qz) );
|
||||
CHECK_MPI_OK( mp_init(&sx) );
|
||||
CHECK_MPI_OK( mp_init(&sy) );
|
||||
CHECK_MPI_OK( mp_init(&sz) );
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
err = MP_OKAY;
|
||||
goto cleanup;
|
||||
/* if n < 0 then out of range error */
|
||||
} else if (mp_cmp_z(n) < 0) {
|
||||
err = MP_RANGE;
|
||||
goto cleanup;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
CHECK_MPI_OK( mp_copy(px, &qx) );
|
||||
CHECK_MPI_OK( mp_copy(py, &qy) );
|
||||
CHECK_MPI_OK( mp_set_int(&qz, 1) );
|
||||
CHECK_MPI_OK( mp_copy(n, &k) );
|
||||
|
||||
/* double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
mp_zero(&sx);
|
||||
mp_zero(&sy);
|
||||
mp_zero(&sz);
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (MP_GET_BIT(&k, i) != 0) {
|
||||
CHECK_MPI_OK( GFp_ec_pt_add_jac(p, a, &sx, &sy, &sz,
|
||||
&qx, &qy, &qz, &sx, &sy, &sz) );
|
||||
}
|
||||
if (i > 0) {
|
||||
/* S = 2S */
|
||||
CHECK_MPI_OK( GFp_ec_pt_dbl_jac(p, a, &sx, &sy, &sz,
|
||||
&sx, &sy, &sz) );
|
||||
}
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
CHECK_MPI_OK( GFp_ec_pt_jac2aff(&sx, &sy, &sz, p, rx, ry) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&qz);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
mp_clear(&sz);
|
||||
return err;
|
||||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
126
mozilla/security/nss/lib/freebl/GFp_ecl.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime
|
||||
* field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __gfp_ecl_h_
|
||||
#define __gfp_ecl_h_
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
#include "secmpi.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
extern mp_err GFp_ec_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
extern mp_err GFp_ec_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx, qy).
|
||||
* Uses affine coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_add_aff(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
extern mp_err GFp_ec_pt_sub_aff(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *qx, const mp_int *qy,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
extern mp_err GFp_ec_pt_dbl_aff(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses affine coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_mul_aff(const mp_int *p, const mp_int *a,
|
||||
const mp_int *b, const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry).
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_jac2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *p, mp_int *rx, mp_int *ry);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_is_inf_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and
|
||||
* Q is (qx, qy, qz). Uses Jacobian coordinates.
|
||||
*/
|
||||
extern mp_err GFp_ec_pt_add_jac(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, const mp_int *qz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz);
|
||||
|
||||
/* Computes R = 2P. Uses Jacobian coordinates. */
|
||||
extern mp_err GFp_ec_pt_dbl_jac(const mp_int *p, const mp_int *a,
|
||||
const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses Jacobian coordinates.
|
||||
*/
|
||||
mp_err GFp_ec_pt_mul_jac(const mp_int *p, const mp_int *a, const mp_int *b,
|
||||
const mp_int *px, const mp_int *py, const mp_int *n,
|
||||
mp_int *rx, mp_int *ry);
|
||||
|
||||
#define GFp_ec_pt_is_inf(px, py) GFp_ec_pt_is_inf_aff((px), (py))
|
||||
#define GFp_ec_pt_add(p, a, px, py, qx, qy, rx, ry) \
|
||||
GFp_ec_pt_add_aff((p), (a), (px), (py), (qx), (qy), (rx), (ry))
|
||||
|
||||
#define GFp_ECL_JACOBIAN
|
||||
#ifdef GFp_ECL_AFFINE
|
||||
#define GFp_ec_pt_mul(p, a, b, px, py, n, rx, ry) \
|
||||
GFp_ec_pt_mul_aff((p), (a), (b), (px), (py), (n), (rx), (ry))
|
||||
#elif defined(GFp_ECL_JACOBIAN)
|
||||
#define GFp_ec_pt_mul(p, a, b, px, py, n, rx, ry) \
|
||||
GFp_ec_pt_mul_jac((p), (a), (b), (px), (py), (n), (rx), (ry))
|
||||
#endif /* GFp_ECL_AFFINE or GFp_ECL_JACOBIAN*/
|
||||
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
#endif /* __gfp_ecl_h_ */
|
||||
339
mozilla/security/nss/lib/freebl/Makefile
Normal file
@@ -0,0 +1,339 @@
|
||||
#! gmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
-include config.mk
|
||||
|
||||
ifdef USE_64
|
||||
DEFINES += -DNSS_USE_64
|
||||
endif
|
||||
|
||||
ifdef USE_HYBRID
|
||||
DEFINES += -DNSS_USE_HYBRID
|
||||
endif
|
||||
|
||||
# des.c wants _X86_ defined for intel CPUs.
|
||||
# coreconf does this for windows, but not for Linux, FreeBSD, etc.
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
ifneq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
OS_REL_CFLAGS += -D_X86_
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),OSF1)
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_NO_MP_WORD
|
||||
MPI_SRCS += mpvalpha.c
|
||||
endif
|
||||
|
||||
ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET))) #omits WIN16 and WINCE
|
||||
ifdef NS_USE_GCC
|
||||
# Ideally, we want to use assembler
|
||||
# ASFILES = mpi_x86.s
|
||||
# DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE \
|
||||
# -DMP_ASSEMBLY_DIV_2DX1D
|
||||
# but we haven't figured out how to make it work, so we are not
|
||||
# using assembler right now.
|
||||
ASFILES =
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT
|
||||
else
|
||||
ASFILES = mpi_x86.asm
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
endif
|
||||
ifdef BUILD_OPT
|
||||
ifndef NS_USE_GCC
|
||||
OPTIMIZER += -Ox # maximum optimization for freebl
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),WINCE)
|
||||
DEFINES += -DMP_ARGCHK=0 # no assert in WinCE
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
endif
|
||||
|
||||
ifdef XP_OS2_VACPP
|
||||
ASFILES = mpi_x86.asm
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),IRIX)
|
||||
ifeq ($(USE_N32),1)
|
||||
ASFILES = mpi_mips.s
|
||||
ifeq ($(NS_USE_GCC),1)
|
||||
ASFLAGS = -Wp,-P -Wp,-traditional -O -mips3
|
||||
else
|
||||
ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3
|
||||
endif
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Linux)
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
ASFILES = mpi_x86.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),AIX)
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
ifndef USE_64
|
||||
DEFINES += -DMP_NO_DIV_WORD -DMP_NO_ADD_WORD -DMP_NO_SUB_WORD
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET), HP-UX)
|
||||
ifneq ($(OS_TEST), ia64)
|
||||
MKSHLIB += +k +vshlibunsats -u FREEBL_GetVector +e FREEBL_GetVector
|
||||
ifndef FREEBL_EXTENDED_BUILD
|
||||
ifdef USE_PURE_32
|
||||
# build for DA1.1 (HP PA 1.1) pure 32 bit model
|
||||
DEFINES += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
else
|
||||
ifdef USE_64
|
||||
# this builds for DA2.0W (HP PA 2.0 Wide), the LP64 ABI, using 32-bit digits
|
||||
MPI_SRCS += mpi_hp.c
|
||||
ASFILES += hpma512.s hppa20.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
else
|
||||
# this builds for DA2.0 (HP PA 2.0 Narrow) hybrid model
|
||||
# (the 32-bit ABI with 64-bit registers) using 32-bit digits
|
||||
MPI_SRCS += mpi_hp.c
|
||||
ASFILES += hpma512.s hppa20.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
# This is done in coreconf by defining USE_LONG_LONGS
|
||||
# OS_CFLAGS += -Aa +e +DA2.0 +DS2.0
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Note: -xarch=v8 or v9 is now done in coreconf
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
ifndef NS_USE_GCC
|
||||
ifdef USE_HYBRID
|
||||
OS_CFLAGS += -xchip=ultra2
|
||||
endif
|
||||
endif
|
||||
ifeq (5.5.1,$(firstword $(sort 5.5.1 $(OS_RELEASE))))
|
||||
SYSV_SPARC = 1
|
||||
endif
|
||||
ifeq ($(SYSV_SPARC),1)
|
||||
SOLARIS_AS = /usr/ccs/bin/as
|
||||
ifdef NS_USE_GCC
|
||||
ifdef GCC_USE_GNU_LD
|
||||
MKSHLIB += -Wl,-Bsymbolic,-z,defs,-z,now,-z,text,--version-script,mapfile.Solaris
|
||||
else
|
||||
MKSHLIB += -Wl,-B,symbolic,-z,defs,-z,now,-z,text,-M,mapfile.Solaris
|
||||
endif
|
||||
else
|
||||
MKSHLIB += -B symbolic -z defs -z now -z text -M mapfile.Solaris
|
||||
endif
|
||||
ifdef USE_PURE_32
|
||||
# this builds for Sparc v8 pure 32-bit architecture
|
||||
DEFINES += -DMP_USE_LONG_LONG_MULTIPLY -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
else
|
||||
ifdef USE_64
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
MPI_SRCS += mpi_sparc.c
|
||||
ASFILES = mpv_sparcv9.s montmulfv9.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_USING_MONT_MULF
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
# MPI_SRCS += mpv_sparc.c
|
||||
# removed -xdepend from the following line
|
||||
SOLARIS_FLAGS = -fast -xO5 -xrestrict=%all -xchip=ultra -xarch=v9a -KPIC -mt
|
||||
SOLARIS_AS_FLAGS = -xarch=v9a -K PIC
|
||||
else
|
||||
# this builds for Sparc v8+a hybrid architecture, 64-bit registers, 32-bit ABI
|
||||
MPI_SRCS += mpi_sparc.c
|
||||
ASFILES = mpv_sparcv8.s montmulfv8.s
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_ASSEMBLY_MULTIPLY -DMP_USING_MONT_MULF
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC
|
||||
# ASM_SUFFIX = .S
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
else
|
||||
# Solaris x86
|
||||
DEFINES += -D_X86_
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
ASFILES = mpi_i86pc.s
|
||||
ifdef NS_USE_GCC
|
||||
LD = gcc
|
||||
AS = gcc
|
||||
ASFLAGS =
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c mac_rand.c os2_rand.c
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
export:: private_export
|
||||
|
||||
rijndael_tables:
|
||||
$(CC) -o $(OBJDIR)/make_rijndael_tab rijndael_tables.c \
|
||||
$(DEFINES) $(INCLUDES) $(OBJDIR)/libfreebl.a
|
||||
$(OBJDIR)/make_rijndael_tab
|
||||
|
||||
ifdef MOZILLA_BSAFE_BUILD
|
||||
|
||||
private_export::
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
rm -f $(DIST)/lib/bsafe$(BSAFEVER).lib
|
||||
endif
|
||||
$(NSINSTALL) -R $(BSAFEPATH) $(DIST)/lib
|
||||
endif
|
||||
|
||||
ifdef USE_PURE_32
|
||||
vpath %.h $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
vpath %.c $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
vpath %.S $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
vpath %.s $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
vpath %.asm $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT)
|
||||
INCLUDES += -I$(FREEBL_PARENT) -I$(FREEBL_PARENT)/mpi
|
||||
else
|
||||
vpath %.h mpi
|
||||
vpath %.c mpi
|
||||
vpath %.S mpi
|
||||
vpath %.s mpi
|
||||
vpath %.asm mpi
|
||||
INCLUDES += -Impi
|
||||
endif
|
||||
|
||||
|
||||
DEFINES += -DMP_API_COMPATIBLE
|
||||
|
||||
MPI_USERS = dh.c pqg.c dsa.c rsa.c ec.c GFp_ecl.c
|
||||
|
||||
MPI_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_SRCS:.c=$(OBJ_SUFFIX)))
|
||||
MPI_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_USERS:.c=$(OBJ_SUFFIX)))
|
||||
|
||||
$(MPI_OBJS): $(MPI_HDRS)
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c
|
||||
|
||||
$(OBJDIR)/ldvector$(OBJ_SUFFIX) $(OBJDIR)/loader$(OBJ_SUFFIX) : loader.h
|
||||
|
||||
ifeq ($(SYSV_SPARC),1)
|
||||
|
||||
$(OBJDIR)/mpv_sparcv8.o $(OBJDIR)/montmulfv8.o : $(OBJDIR)/%.o : %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
|
||||
|
||||
$(OBJDIR)/mpv_sparcv9.o $(OBJDIR)/montmulfv9.o : $(OBJDIR)/%.o : %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
|
||||
|
||||
$(OBJDIR)/mpmontg.o: mpmontg.c montmulf.h
|
||||
|
||||
endif
|
||||
|
||||
ifdef FREEBL_EXTENDED_BUILD
|
||||
|
||||
PURE32DIR = $(OBJDIR)/$(OS_TARGET)pure32
|
||||
ALL_TRASH += $(PURE32DIR)
|
||||
|
||||
FILES2LN = \
|
||||
$(wildcard *.tab) \
|
||||
$(wildcard mapfile.*) \
|
||||
Makefile manifest.mn config.mk
|
||||
|
||||
LINKEDFILES = $(addprefix $(PURE32DIR)/, $(FILES2LN))
|
||||
|
||||
CDDIR := $(shell pwd)
|
||||
|
||||
$(PURE32DIR):
|
||||
-mkdir $(PURE32DIR)
|
||||
-ln -s $(CDDIR)/mpi $(PURE32DIR)
|
||||
|
||||
$(LINKEDFILES) : $(PURE32DIR)/% : %
|
||||
ln -s $(CDDIR)/$* $(PURE32DIR)
|
||||
|
||||
libs::
|
||||
$(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_HYBRID=1 libs
|
||||
|
||||
libs:: $(PURE32DIR) $(LINKEDFILES)
|
||||
cd $(PURE32DIR) && $(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_PURE_32=1 FREEBL_PARENT=$(CDDIR) CORE_DEPTH=$(CDDIR)/$(CORE_DEPTH) libs
|
||||
|
||||
release_md::
|
||||
$(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_HYBRID=1 $@
|
||||
cd $(PURE32DIR) && $(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_PURE_32=1 FREEBL_PARENT=$(CDDIR) CORE_DEPTH=$(CDDIR)/$(CORE_DEPTH) $@
|
||||
|
||||
endif
|
||||
383
mozilla/security/nss/lib/freebl/aeskeywrap.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* aeskeywrap.c - implement AES Key Wrap algorithm from RFC 3394
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2002, 2003 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: aeskeywrap.c,v 1.1 2003-01-14 22:16:04 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "prcpucfg.h"
|
||||
#if defined(IS_LITTLE_ENDIAN) || defined(SHA_NO_LONG_LONG)
|
||||
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 0
|
||||
#else
|
||||
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 1
|
||||
#endif
|
||||
#include "prtypes.h" /* for PRUintXX */
|
||||
#include "secport.h" /* for PORT_XXX */
|
||||
#include "secerr.h"
|
||||
#include "blapi.h" /* for AES_ functions */
|
||||
|
||||
|
||||
struct AESKeyWrapContextStr {
|
||||
AESContext * aescx;
|
||||
unsigned char iv[AES_KEY_WRAP_IV_BYTES];
|
||||
};
|
||||
|
||||
/******************************************/
|
||||
/*
|
||||
** AES key wrap algorithm, RFC 3394
|
||||
*/
|
||||
|
||||
/*
|
||||
** Create a new AES context suitable for AES encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "keylen" the number of bytes of key data (16, 24, or 32)
|
||||
*/
|
||||
extern AESKeyWrapContext *
|
||||
AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv,
|
||||
int encrypt, unsigned int keylen)
|
||||
{
|
||||
AESKeyWrapContext * cx = PORT_ZNew(AESKeyWrapContext);
|
||||
if (!cx)
|
||||
return NULL; /* error is already set */
|
||||
cx->aescx = AES_CreateContext(key, NULL, NSS_AES, encrypt, keylen,
|
||||
AES_BLOCK_SIZE);
|
||||
if (!cx->aescx) {
|
||||
PORT_Free(cx);
|
||||
return NULL; /* error should already be set */
|
||||
}
|
||||
if (iv) {
|
||||
memcpy(cx->iv, iv, AES_KEY_WRAP_IV_BYTES);
|
||||
} else {
|
||||
memset(cx->iv, 0xA6, AES_KEY_WRAP_IV_BYTES);
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy a AES KeyWrap context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void
|
||||
AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
if (cx->aescx)
|
||||
AES_DestroyContext(cx->aescx, PR_TRUE);
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
#if !BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
|
||||
/* The AES Key Wrap algorithm has 64-bit values that are ALWAYS big-endian
|
||||
** (Most significant byte first) in memory. The only ALU operations done
|
||||
** on them are increment, decrement, and XOR. So, on little-endian CPUs,
|
||||
** and on CPUs that lack 64-bit registers, these big-endian 64-bit operations
|
||||
** are simulated in the following code. This is thought to be faster and
|
||||
** simpler than trying to convert the data to little-endian and back.
|
||||
*/
|
||||
|
||||
/* A and T point to two 64-bit values stored most signficant byte first
|
||||
** (big endian). This function increments the 64-bit value T, and then
|
||||
** XORs it with A, changing A.
|
||||
*/
|
||||
static void
|
||||
increment_and_xor(unsigned char *A, unsigned char *T)
|
||||
{
|
||||
if (!++T[7])
|
||||
if (!++T[6])
|
||||
if (!++T[5])
|
||||
if (!++T[4])
|
||||
if (!++T[3])
|
||||
if (!++T[2])
|
||||
if (!++T[1])
|
||||
++T[0];
|
||||
|
||||
A[0] ^= T[0];
|
||||
A[1] ^= T[1];
|
||||
A[2] ^= T[2];
|
||||
A[3] ^= T[3];
|
||||
A[4] ^= T[4];
|
||||
A[5] ^= T[5];
|
||||
A[6] ^= T[6];
|
||||
A[7] ^= T[7];
|
||||
}
|
||||
|
||||
/* A and T point to two 64-bit values stored most signficant byte first
|
||||
** (big endian). This function XORs T with A, giving a new A, then
|
||||
** decrements the 64-bit value T.
|
||||
*/
|
||||
static void
|
||||
xor_and_decrement(unsigned char *A, unsigned char *T)
|
||||
{
|
||||
A[0] ^= T[0];
|
||||
A[1] ^= T[1];
|
||||
A[2] ^= T[2];
|
||||
A[3] ^= T[3];
|
||||
A[4] ^= T[4];
|
||||
A[5] ^= T[5];
|
||||
A[6] ^= T[6];
|
||||
A[7] ^= T[7];
|
||||
|
||||
if (!T[7]--)
|
||||
if (!T[6]--)
|
||||
if (!T[5]--)
|
||||
if (!T[4]--)
|
||||
if (!T[3]--)
|
||||
if (!T[2]--)
|
||||
if (!T[1]--)
|
||||
T[0]--;
|
||||
|
||||
}
|
||||
|
||||
/* Given an unsigned long t (in host byte order), store this value as a
|
||||
** 64-bit big-endian value (MSB first) in *pt.
|
||||
*/
|
||||
static void
|
||||
set_t(unsigned char *pt, unsigned long t)
|
||||
{
|
||||
pt[7] = (unsigned char)t; t >>= 8;
|
||||
pt[6] = (unsigned char)t; t >>= 8;
|
||||
pt[5] = (unsigned char)t; t >>= 8;
|
||||
pt[4] = (unsigned char)t; t >>= 8;
|
||||
pt[3] = (unsigned char)t; t >>= 8;
|
||||
pt[2] = (unsigned char)t; t >>= 8;
|
||||
pt[1] = (unsigned char)t; t >>= 8;
|
||||
pt[0] = (unsigned char)t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Perform AES key wrap.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
extern SECStatus
|
||||
AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
|
||||
unsigned int *pOutputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint64 * R = NULL;
|
||||
unsigned int nBlocks;
|
||||
unsigned int i, j;
|
||||
unsigned int aesLen = AES_BLOCK_SIZE;
|
||||
unsigned int outLen = inputLen + AES_KEY_WRAP_BLOCK_SIZE;
|
||||
SECStatus s = SECFailure;
|
||||
/* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
||||
PRUint64 t;
|
||||
PRUint64 B[2];
|
||||
|
||||
#define A B[0]
|
||||
|
||||
/* Check args */
|
||||
if (!inputLen || 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
#ifdef maybe
|
||||
if (!output && pOutputLen) { /* caller is asking for output size */
|
||||
*pOutputLen = outLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
if (maxOutputLen < outLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
if (cx == NULL || output == NULL || input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return s;
|
||||
}
|
||||
nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
||||
R = PORT_NewArray(PRUint64, nBlocks + 1);
|
||||
if (!R)
|
||||
return s; /* error is already set. */
|
||||
/*
|
||||
** 1) Initialize variables.
|
||||
*/
|
||||
memcpy(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
||||
memcpy(&R[1], input, inputLen);
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
t = 0;
|
||||
#else
|
||||
memset(&t, 0, sizeof t);
|
||||
#endif
|
||||
/*
|
||||
** 2) Calculate intermediate values.
|
||||
*/
|
||||
for (j = 0; j < 6; ++j) {
|
||||
for (i = 1; i <= nBlocks; ++i) {
|
||||
B[1] = R[i];
|
||||
s = AES_Encrypt(cx->aescx, (unsigned char *)B, &aesLen,
|
||||
sizeof B, (unsigned char *)B, sizeof B);
|
||||
if (s != SECSuccess)
|
||||
break;
|
||||
R[i] = B[1];
|
||||
/* here, increment t and XOR A with t (in big endian order); */
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
A ^= ++t;
|
||||
#else
|
||||
increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 3) Output the results.
|
||||
*/
|
||||
if (s == SECSuccess) {
|
||||
R[0] = A;
|
||||
memcpy(output, &R[0], outLen);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = outLen;
|
||||
} else if (pOutputLen) {
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
PORT_ZFree(R, outLen);
|
||||
return s;
|
||||
}
|
||||
#undef A
|
||||
|
||||
/*
|
||||
** Perform AES key unwrap.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
extern SECStatus
|
||||
AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
|
||||
unsigned int *pOutputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint64 * R = NULL;
|
||||
unsigned int nBlocks;
|
||||
unsigned int i, j;
|
||||
unsigned int aesLen = AES_BLOCK_SIZE;
|
||||
unsigned int outLen;
|
||||
SECStatus s = SECFailure;
|
||||
/* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
||||
PRUint64 t;
|
||||
PRUint64 B[2];
|
||||
|
||||
#define A B[0]
|
||||
|
||||
/* Check args */
|
||||
if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
|
||||
0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
outLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
|
||||
#ifdef maybe
|
||||
if (!output && pOutputLen) { /* caller is asking for output size */
|
||||
*pOutputLen = outLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
if (maxOutputLen < outLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
if (cx == NULL || output == NULL || input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return s;
|
||||
}
|
||||
nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
||||
R = PORT_NewArray(PRUint64, nBlocks);
|
||||
if (!R)
|
||||
return s; /* error is already set. */
|
||||
nBlocks--;
|
||||
/*
|
||||
** 1) Initialize variables.
|
||||
*/
|
||||
memcpy(&R[0], input, inputLen);
|
||||
A = R[0];
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
t = 6UL * nBlocks;
|
||||
#else
|
||||
set_t((unsigned char *)&t, 6UL * nBlocks);
|
||||
#endif
|
||||
/*
|
||||
** 2) Calculate intermediate values.
|
||||
*/
|
||||
for (j = 0; j < 6; ++j) {
|
||||
for (i = nBlocks; i; --i) {
|
||||
/* here, XOR A with t (in big endian order) and decrement t; */
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
A ^= t--;
|
||||
#else
|
||||
xor_and_decrement((unsigned char *)&A, (unsigned char *)&t);
|
||||
#endif
|
||||
B[1] = R[i];
|
||||
s = AES_Decrypt(cx->aescx, (unsigned char *)B, &aesLen,
|
||||
sizeof B, (unsigned char *)B, sizeof B);
|
||||
if (s != SECSuccess)
|
||||
break;
|
||||
R[i] = B[1];
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 3) Output the results.
|
||||
*/
|
||||
if (s == SECSuccess) {
|
||||
int bad = memcmp(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
||||
if (!bad) {
|
||||
memcpy(output, &R[1], outLen);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = outLen;
|
||||
} else {
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
} else if (pOutputLen) {
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
PORT_ZFree(R, inputLen);
|
||||
return s;
|
||||
}
|
||||
#undef A
|
||||
493
mozilla/security/nss/lib/freebl/alg2268.c
Normal file
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* alg2268.c - implementation of the algorithm in RFC 2268
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: alg2268.c,v 1.4 2002-11-16 06:09:57 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secerr.h"
|
||||
#ifdef XP_UNIX_XXX
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** RC2 symmetric block cypher
|
||||
*/
|
||||
|
||||
typedef SECStatus (rc2Func)(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
/* forward declarations */
|
||||
static rc2Func rc2_EncryptECB;
|
||||
static rc2Func rc2_DecryptECB;
|
||||
static rc2Func rc2_EncryptCBC;
|
||||
static rc2Func rc2_DecryptCBC;
|
||||
|
||||
typedef union {
|
||||
PRUint32 l[2];
|
||||
PRUint16 s[4];
|
||||
PRUint8 b[8];
|
||||
} RC2Block;
|
||||
|
||||
struct RC2ContextStr {
|
||||
union {
|
||||
PRUint8 Kb[128];
|
||||
PRUint16 Kw[64];
|
||||
} u;
|
||||
RC2Block iv;
|
||||
rc2Func *enc;
|
||||
rc2Func *dec;
|
||||
};
|
||||
|
||||
#define B u.Kb
|
||||
#define K u.Kw
|
||||
#define BYTESWAP(x) ((x) << 8 | (x) >> 8)
|
||||
#define SWAPK(i) cx->K[i] = (tmpS = cx->K[i], BYTESWAP(tmpS))
|
||||
#define RC2_BLOCK_SIZE 8
|
||||
|
||||
#define LOAD_HARD(R) \
|
||||
R[0] = (PRUint16)input[1] << 8 | input[0]; \
|
||||
R[1] = (PRUint16)input[3] << 8 | input[2]; \
|
||||
R[2] = (PRUint16)input[5] << 8 | input[4]; \
|
||||
R[3] = (PRUint16)input[7] << 8 | input[6];
|
||||
#define LOAD_EASY(R) \
|
||||
R[0] = ((PRUint16 *)input)[0]; \
|
||||
R[1] = ((PRUint16 *)input)[1]; \
|
||||
R[2] = ((PRUint16 *)input)[2]; \
|
||||
R[3] = ((PRUint16 *)input)[3];
|
||||
#define STORE_HARD(R) \
|
||||
output[0] = (PRUint8)(R[0]); output[1] = (PRUint8)(R[0] >> 8); \
|
||||
output[2] = (PRUint8)(R[1]); output[3] = (PRUint8)(R[1] >> 8); \
|
||||
output[4] = (PRUint8)(R[2]); output[5] = (PRUint8)(R[2] >> 8); \
|
||||
output[6] = (PRUint8)(R[3]); output[7] = (PRUint8)(R[3] >> 8);
|
||||
#define STORE_EASY(R) \
|
||||
((PRUint16 *)output)[0] = R[0]; \
|
||||
((PRUint16 *)output)[1] = R[1]; \
|
||||
((PRUint16 *)output)[2] = R[2]; \
|
||||
((PRUint16 *)output)[3] = R[3];
|
||||
|
||||
#if defined (_X86_)
|
||||
#define LOAD(R) LOAD_EASY(R)
|
||||
#define STORE(R) STORE_EASY(R)
|
||||
#elif !defined(IS_LITTLE_ENDIAN)
|
||||
#define LOAD(R) LOAD_HARD(R)
|
||||
#define STORE(R) STORE_HARD(R)
|
||||
#else
|
||||
#define LOAD(R) if ((ptrdiff_t)input & 1) { LOAD_HARD(R) } else { LOAD_EASY(R) }
|
||||
#define STORE(R) if ((ptrdiff_t)input & 1) { STORE_HARD(R) } else { STORE_EASY(R) }
|
||||
#endif
|
||||
|
||||
static const PRUint8 S[256] = {
|
||||
0331,0170,0371,0304,0031,0335,0265,0355,0050,0351,0375,0171,0112,0240,0330,0235,
|
||||
0306,0176,0067,0203,0053,0166,0123,0216,0142,0114,0144,0210,0104,0213,0373,0242,
|
||||
0027,0232,0131,0365,0207,0263,0117,0023,0141,0105,0155,0215,0011,0201,0175,0062,
|
||||
0275,0217,0100,0353,0206,0267,0173,0013,0360,0225,0041,0042,0134,0153,0116,0202,
|
||||
0124,0326,0145,0223,0316,0140,0262,0034,0163,0126,0300,0024,0247,0214,0361,0334,
|
||||
0022,0165,0312,0037,0073,0276,0344,0321,0102,0075,0324,0060,0243,0074,0266,0046,
|
||||
0157,0277,0016,0332,0106,0151,0007,0127,0047,0362,0035,0233,0274,0224,0103,0003,
|
||||
0370,0021,0307,0366,0220,0357,0076,0347,0006,0303,0325,0057,0310,0146,0036,0327,
|
||||
0010,0350,0352,0336,0200,0122,0356,0367,0204,0252,0162,0254,0065,0115,0152,0052,
|
||||
0226,0032,0322,0161,0132,0025,0111,0164,0113,0237,0320,0136,0004,0030,0244,0354,
|
||||
0302,0340,0101,0156,0017,0121,0313,0314,0044,0221,0257,0120,0241,0364,0160,0071,
|
||||
0231,0174,0072,0205,0043,0270,0264,0172,0374,0002,0066,0133,0045,0125,0227,0061,
|
||||
0055,0135,0372,0230,0343,0212,0222,0256,0005,0337,0051,0020,0147,0154,0272,0311,
|
||||
0323,0000,0346,0317,0341,0236,0250,0054,0143,0026,0001,0077,0130,0342,0211,0251,
|
||||
0015,0070,0064,0033,0253,0063,0377,0260,0273,0110,0014,0137,0271,0261,0315,0056,
|
||||
0305,0363,0333,0107,0345,0245,0234,0167,0012,0246,0040,0150,0376,0177,0301,0255
|
||||
};
|
||||
|
||||
/*
|
||||
** Create a new RC2 context suitable for RC2 encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "len" the number of bytes of key data
|
||||
** "iv" is the CBC initialization vector (if mode is NSS_RC2_CBC)
|
||||
** "mode" one of NSS_RC2 or NSS_RC2_CBC
|
||||
** "effectiveKeyLen" in bytes, not bits.
|
||||
**
|
||||
** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block
|
||||
** chaining" mode.
|
||||
*/
|
||||
RC2Context *
|
||||
RC2_CreateContext(const unsigned char *key, unsigned int len,
|
||||
const unsigned char *input, int mode, unsigned efLen8)
|
||||
{
|
||||
RC2Context *cx;
|
||||
PRUint8 *L,*L2;
|
||||
int i;
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
PRUint16 tmpS;
|
||||
#endif
|
||||
PRUint8 tmpB;
|
||||
|
||||
if (!key || len == 0 || len > (sizeof cx->B) || efLen8 > (sizeof cx->B)) {
|
||||
return NULL;
|
||||
}
|
||||
if (mode == NSS_RC2) {
|
||||
/* groovy */
|
||||
} else if (mode == NSS_RC2_CBC) {
|
||||
if (!input) {
|
||||
return NULL; /* not groovy */
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cx = PORT_ZNew(RC2Context);
|
||||
if (!cx)
|
||||
return cx;
|
||||
|
||||
if (mode == NSS_RC2_CBC) {
|
||||
cx->enc = & rc2_EncryptCBC;
|
||||
cx->dec = & rc2_DecryptCBC;
|
||||
LOAD(cx->iv.s);
|
||||
} else {
|
||||
cx->enc = & rc2_EncryptECB;
|
||||
cx->dec = & rc2_DecryptECB;
|
||||
}
|
||||
|
||||
/* Step 0. Copy key into table. */
|
||||
memcpy(cx->B, key, len);
|
||||
|
||||
/* Step 1. Compute all values to the right of the key. */
|
||||
L2 = cx->B;
|
||||
L = L2 + len;
|
||||
tmpB = L[-1];
|
||||
for (i = (sizeof cx->B) - len; i > 0; --i) {
|
||||
*L++ = tmpB = S[ (PRUint8)(tmpB + *L2++) ];
|
||||
}
|
||||
|
||||
/* step 2. Adjust left most byte of effective key. */
|
||||
i = (sizeof cx->B) - efLen8;
|
||||
L = cx->B + i;
|
||||
*L = tmpB = S[*L]; /* mask is always 0xff */
|
||||
|
||||
/* step 3. Recompute all values to the left of effective key. */
|
||||
L2 = --L + efLen8;
|
||||
while(L >= cx->B) {
|
||||
*L-- = tmpB = S[ tmpB ^ *L2-- ];
|
||||
}
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
for (i = 63; i >= 0; --i) {
|
||||
SWAPK(i); /* candidate for unrolling */
|
||||
}
|
||||
#endif
|
||||
return cx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy an RC2 encryption/decryption context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
void
|
||||
RC2_DestroyContext(RC2Context *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit) {
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ROL(x,k) (x << k | x >> (16-k))
|
||||
#define MIX(j) \
|
||||
R0 = R0 + cx->K[ 4*j+0] + (R3 & R2) + (~R3 & R1); R0 = ROL(R0,1);\
|
||||
R1 = R1 + cx->K[ 4*j+1] + (R0 & R3) + (~R0 & R2); R1 = ROL(R1,2);\
|
||||
R2 = R2 + cx->K[ 4*j+2] + (R1 & R0) + (~R1 & R3); R2 = ROL(R2,3);\
|
||||
R3 = R3 + cx->K[ 4*j+3] + (R2 & R1) + (~R2 & R0); R3 = ROL(R3,5)
|
||||
#define MASH \
|
||||
R0 = R0 + cx->K[R3 & 63];\
|
||||
R1 = R1 + cx->K[R0 & 63];\
|
||||
R2 = R2 + cx->K[R1 & 63];\
|
||||
R3 = R3 + cx->K[R2 & 63]
|
||||
|
||||
/* Encrypt one block */
|
||||
static void
|
||||
rc2_Encrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
|
||||
{
|
||||
register PRUint16 R0, R1, R2, R3;
|
||||
|
||||
/* step 1. Initialize input. */
|
||||
R0 = input->s[0];
|
||||
R1 = input->s[1];
|
||||
R2 = input->s[2];
|
||||
R3 = input->s[3];
|
||||
|
||||
/* step 2. Expand Key (already done, in context) */
|
||||
/* step 3. j = 0 */
|
||||
/* step 4. Perform 5 mixing rounds. */
|
||||
|
||||
MIX(0);
|
||||
MIX(1);
|
||||
MIX(2);
|
||||
MIX(3);
|
||||
MIX(4);
|
||||
|
||||
/* step 5. Perform 1 mashing round. */
|
||||
MASH;
|
||||
|
||||
/* step 6. Perform 6 mixing rounds. */
|
||||
|
||||
MIX(5);
|
||||
MIX(6);
|
||||
MIX(7);
|
||||
MIX(8);
|
||||
MIX(9);
|
||||
MIX(10);
|
||||
|
||||
/* step 7. Perform 1 mashing round. */
|
||||
MASH;
|
||||
|
||||
/* step 8. Perform 5 mixing rounds. */
|
||||
|
||||
MIX(11);
|
||||
MIX(12);
|
||||
MIX(13);
|
||||
MIX(14);
|
||||
MIX(15);
|
||||
|
||||
/* output results */
|
||||
output->s[0] = R0;
|
||||
output->s[1] = R1;
|
||||
output->s[2] = R2;
|
||||
output->s[3] = R3;
|
||||
}
|
||||
|
||||
#define ROR(x,k) (x >> k | x << (16-k))
|
||||
#define R_MIX(j) \
|
||||
R3 = ROR(R3,5); R3 = R3 - cx->K[ 4*j+3] - (R2 & R1) - (~R2 & R0); \
|
||||
R2 = ROR(R2,3); R2 = R2 - cx->K[ 4*j+2] - (R1 & R0) - (~R1 & R3); \
|
||||
R1 = ROR(R1,2); R1 = R1 - cx->K[ 4*j+1] - (R0 & R3) - (~R0 & R2); \
|
||||
R0 = ROR(R0,1); R0 = R0 - cx->K[ 4*j+0] - (R3 & R2) - (~R3 & R1)
|
||||
#define R_MASH \
|
||||
R3 = R3 - cx->K[R2 & 63];\
|
||||
R2 = R2 - cx->K[R1 & 63];\
|
||||
R1 = R1 - cx->K[R0 & 63];\
|
||||
R0 = R0 - cx->K[R3 & 63]
|
||||
|
||||
/* Encrypt one block */
|
||||
static void
|
||||
rc2_Decrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
|
||||
{
|
||||
register PRUint16 R0, R1, R2, R3;
|
||||
|
||||
/* step 1. Initialize input. */
|
||||
R0 = input->s[0];
|
||||
R1 = input->s[1];
|
||||
R2 = input->s[2];
|
||||
R3 = input->s[3];
|
||||
|
||||
/* step 2. Expand Key (already done, in context) */
|
||||
/* step 3. j = 63 */
|
||||
/* step 4. Perform 5 r_mixing rounds. */
|
||||
R_MIX(15);
|
||||
R_MIX(14);
|
||||
R_MIX(13);
|
||||
R_MIX(12);
|
||||
R_MIX(11);
|
||||
|
||||
/* step 5. Perform 1 r_mashing round. */
|
||||
R_MASH;
|
||||
|
||||
/* step 6. Perform 6 r_mixing rounds. */
|
||||
R_MIX(10);
|
||||
R_MIX(9);
|
||||
R_MIX(8);
|
||||
R_MIX(7);
|
||||
R_MIX(6);
|
||||
R_MIX(5);
|
||||
|
||||
/* step 7. Perform 1 r_mashing round. */
|
||||
R_MASH;
|
||||
|
||||
/* step 8. Perform 5 r_mixing rounds. */
|
||||
R_MIX(4);
|
||||
R_MIX(3);
|
||||
R_MIX(2);
|
||||
R_MIX(1);
|
||||
R_MIX(0);
|
||||
|
||||
/* output results */
|
||||
output->s[0] = R0;
|
||||
output->s[1] = R1;
|
||||
output->s[2] = R2;
|
||||
output->s[3] = R3;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_EncryptECB(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Encrypt1Block(cx, &iBlock, &iBlock);
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_DecryptECB(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Decrypt1Block(cx, &iBlock, &iBlock);
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_EncryptCBC(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
|
||||
LOAD(iBlock.s)
|
||||
iBlock.l[0] ^= cx->iv.l[0];
|
||||
iBlock.l[1] ^= cx->iv.l[1];
|
||||
rc2_Encrypt1Block(cx, &iBlock, &iBlock);
|
||||
cx->iv = iBlock;
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_DecryptCBC(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
RC2Block oBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Decrypt1Block(cx, &oBlock, &iBlock);
|
||||
oBlock.l[0] ^= cx->iv.l[0];
|
||||
oBlock.l[1] ^= cx->iv.l[1];
|
||||
cx->iv = iBlock;
|
||||
STORE(oBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Perform RC2 encryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus RC2_Encrypt(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
if (inputLen) {
|
||||
if (inputLen % RC2_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = (*cx->enc)(cx, output, input, inputLen);
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*outputLen = inputLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC2 decryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus RC2_Decrypt(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
if (inputLen) {
|
||||
if (inputLen % RC2_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = (*cx->dec)(cx, output, input, inputLen);
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*outputLen = inputLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
114
mozilla/security/nss/lib/freebl/arcfive.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* arcfive.c - stubs for RC5 - NOT a working implementation!
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: arcfive.c,v 1.3 2002-11-16 06:09:57 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "blapi.h"
|
||||
#include "prerror.h"
|
||||
|
||||
/******************************************/
|
||||
/*
|
||||
** RC5 symmetric block cypher -- 64-bit block size
|
||||
*/
|
||||
|
||||
/*
|
||||
** Create a new RC5 context suitable for RC5 encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "len" the number of bytes of key data
|
||||
** "iv" is the CBC initialization vector (if mode is NSS_RC5_CBC)
|
||||
** "mode" one of NSS_RC5 or NSS_RC5_CBC
|
||||
**
|
||||
** When mode is set to NSS_RC5_CBC the RC5 cipher is run in "cipher block
|
||||
** chaining" mode.
|
||||
*/
|
||||
RC5Context *
|
||||
RC5_CreateContext(const SECItem *key, unsigned int rounds,
|
||||
unsigned int wordSize, const unsigned char *iv, int mode)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy an RC5 encryption/decryption context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
void
|
||||
RC5_DestroyContext(RC5Context *cx, PRBool freeit)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC5 encryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus
|
||||
RC5_Encrypt(RC5Context *cx, unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC5 decryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus
|
||||
RC5_Decrypt(RC5Context *cx, unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
567
mozilla/security/nss/lib/freebl/arcfour.c
Normal file
@@ -0,0 +1,567 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "blapi.h"
|
||||
|
||||
/* Architecture-dependent defines */
|
||||
|
||||
#if defined(SOLARIS) || defined(HPUX) || defined(i386) || defined(IRIX)
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
#define CONVERT_TO_WORDS
|
||||
#endif
|
||||
|
||||
#if defined(AIX) || defined(OSF1)
|
||||
/* Treat array variables as longs, not bytes */
|
||||
#define USE_LONG
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
#undef WORD
|
||||
#define WORD ARC4WORD
|
||||
#endif
|
||||
|
||||
#if defined(NSS_USE_HYBRID) && !defined(SOLARIS) && !defined(NSS_USE_64)
|
||||
typedef unsigned long long WORD;
|
||||
#else
|
||||
typedef unsigned long WORD;
|
||||
#endif
|
||||
#define WORDSIZE sizeof(WORD)
|
||||
|
||||
#ifdef USE_LONG
|
||||
typedef unsigned long Stype;
|
||||
#else
|
||||
typedef PRUint8 Stype;
|
||||
#endif
|
||||
|
||||
#define ARCFOUR_STATE_SIZE 256
|
||||
|
||||
#define MASK1BYTE (WORD)(0xff)
|
||||
|
||||
#define SWAP(a, b) \
|
||||
tmp = a; \
|
||||
a = b; \
|
||||
b = tmp;
|
||||
|
||||
/*
|
||||
* State information for stream cipher.
|
||||
*/
|
||||
struct RC4ContextStr
|
||||
{
|
||||
Stype S[ARCFOUR_STATE_SIZE];
|
||||
PRUint8 i;
|
||||
PRUint8 j;
|
||||
};
|
||||
|
||||
/*
|
||||
* array indices [0..255] to initialize cx->S array (faster than loop).
|
||||
*/
|
||||
static const Stype Kinit[256] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize a new generator.
|
||||
*/
|
||||
RC4Context *
|
||||
RC4_CreateContext(const unsigned char *key, int len)
|
||||
{
|
||||
int i;
|
||||
PRUint8 j, tmp;
|
||||
RC4Context *cx;
|
||||
PRUint8 K[256];
|
||||
PRUint8 *L;
|
||||
/* verify the key length. */
|
||||
PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
|
||||
if (len < 0 || len >= ARCFOUR_STATE_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
/* Create space for the context. */
|
||||
cx = (RC4Context *)PORT_ZAlloc(sizeof(RC4Context));
|
||||
if (cx == NULL) {
|
||||
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
/* Initialize the state using array indices. */
|
||||
memcpy(cx->S, Kinit, sizeof cx->S);
|
||||
/* Fill in K repeatedly with values from key. */
|
||||
L = K;
|
||||
for (i = sizeof K; i > len; i-= len) {
|
||||
memcpy(L, key, len);
|
||||
L += len;
|
||||
}
|
||||
memcpy(L, key, i);
|
||||
/* Stir the state of the generator. At this point it is assumed
|
||||
* that the key is the size of the state buffer. If this is not
|
||||
* the case, the key bytes are repeated to fill the buffer.
|
||||
*/
|
||||
j = 0;
|
||||
#define ARCFOUR_STATE_STIR(ii) \
|
||||
j = j + cx->S[ii] + K[ii]; \
|
||||
SWAP(cx->S[ii], cx->S[j]);
|
||||
for (i=0; i<ARCFOUR_STATE_SIZE; i++) {
|
||||
ARCFOUR_STATE_STIR(i);
|
||||
}
|
||||
cx->i = 0;
|
||||
cx->j = 0;
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
RC4_DestroyContext(RC4Context *cx, PRBool freeit)
|
||||
{
|
||||
if (freeit)
|
||||
PORT_ZFree(cx, sizeof(*cx));
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the next byte in the stream.
|
||||
*/
|
||||
#define ARCFOUR_NEXT_BYTE() \
|
||||
tmpSi = cx->S[++tmpi]; \
|
||||
tmpj += tmpSi; \
|
||||
tmpSj = cx->S[tmpj]; \
|
||||
cx->S[tmpi] = tmpSj; \
|
||||
cx->S[tmpj] = tmpSi; \
|
||||
t = tmpSi + tmpSj;
|
||||
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Straight RC4 op. No optimization.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_no_opt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint8 t;
|
||||
Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
unsigned int index;
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
for (index=0; index < inputLen; index++) {
|
||||
/* Generate next byte from stream. */
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
/* output = next stream byte XOR next input byte */
|
||||
output[index] = cx->S[t] ^ input[index];
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Byte-at-a-time RC4, unrolling the loop into 8 pieces.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_unrolled(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint8 t;
|
||||
Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
int index;
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
for (index = inputLen / 8; index-- > 0; input += 8, output += 8) {
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[0] = cx->S[t] ^ input[0];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[1] = cx->S[t] ^ input[1];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[2] = cx->S[t] ^ input[2];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[3] = cx->S[t] ^ input[3];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[4] = cx->S[t] ^ input[4];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[5] = cx->S[t] ^ input[5];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[6] = cx->S[t] ^ input[6];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[7] = cx->S[t] ^ input[7];
|
||||
}
|
||||
index = inputLen % 8;
|
||||
if (index) {
|
||||
input += index;
|
||||
output += index;
|
||||
switch (index) {
|
||||
case 7:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-7] = cx->S[t] ^ input[-7]; /* FALLTHRU */
|
||||
case 6:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-6] = cx->S[t] ^ input[-6]; /* FALLTHRU */
|
||||
case 5:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-5] = cx->S[t] ^ input[-5]; /* FALLTHRU */
|
||||
case 4:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-4] = cx->S[t] ^ input[-4]; /* FALLTHRU */
|
||||
case 3:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-3] = cx->S[t] ^ input[-3]; /* FALLTHRU */
|
||||
case 2:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-2] = cx->S[t] ^ input[-2]; /* FALLTHRU */
|
||||
case 1:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-1] = cx->S[t] ^ input[-1]; /* FALLTHRU */
|
||||
default:
|
||||
/* FALLTHRU */
|
||||
; /* hp-ux build breaks without this */
|
||||
}
|
||||
}
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT4BYTES_L(n) \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n ); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 8); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24);
|
||||
#else
|
||||
#define ARCFOUR_NEXT4BYTES_B(n) \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 8); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n );
|
||||
#endif
|
||||
|
||||
#if (defined(NSS_USE_HYBRID) && !defined(SOLARIS)) || defined(NSS_USE_64)
|
||||
/* 64-bit wordsize */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); ARCFOUR_NEXT4BYTES_L(32); }
|
||||
#else
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(32); ARCFOUR_NEXT4BYTES_B(0); }
|
||||
#endif
|
||||
#else
|
||||
/* 32-bit wordsize */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); }
|
||||
#else
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(0); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define RSH <<
|
||||
#define LSH >>
|
||||
#else
|
||||
#define RSH >>
|
||||
#define LSH <<
|
||||
#endif
|
||||
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Convert input and output buffers to words before performing
|
||||
* RC4 operations.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_wordconv(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
ptrdiff_t inOffset = (ptrdiff_t)input % WORDSIZE;
|
||||
ptrdiff_t outOffset = (ptrdiff_t)output % WORDSIZE;
|
||||
register WORD streamWord, mask;
|
||||
register WORD *pInWord, *pOutWord;
|
||||
register WORD inWord, nextInWord;
|
||||
PRUint8 t;
|
||||
register Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
unsigned int byteCount;
|
||||
unsigned int bufShift, invBufShift;
|
||||
int i;
|
||||
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (inputLen < 2*WORDSIZE) {
|
||||
/* Ignore word conversion, do byte-at-a-time */
|
||||
return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
pInWord = (WORD *)(input - inOffset);
|
||||
if (inOffset < outOffset) {
|
||||
bufShift = 8*(outOffset - inOffset);
|
||||
invBufShift = 8*WORDSIZE - bufShift;
|
||||
} else {
|
||||
invBufShift = 8*(inOffset - outOffset);
|
||||
bufShift = 8*WORDSIZE - invBufShift;
|
||||
}
|
||||
/*****************************************************************/
|
||||
/* Step 1: */
|
||||
/* If the first output word is partial, consume the bytes in the */
|
||||
/* first partial output word by loading one or two words of */
|
||||
/* input and shifting them accordingly. Otherwise, just load */
|
||||
/* in the first word of input. At the end of this block, at */
|
||||
/* least one partial word of input should ALWAYS be loaded. */
|
||||
/*****************************************************************/
|
||||
if (outOffset) {
|
||||
/* Generate input and stream words aligned relative to the
|
||||
* partial output buffer.
|
||||
*/
|
||||
byteCount = WORDSIZE - outOffset;
|
||||
pOutWord = (WORD *)(output - outOffset);
|
||||
mask = streamWord = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
for (i = WORDSIZE - byteCount; i < WORDSIZE; i++) {
|
||||
#else
|
||||
for (i = byteCount - 1; i >= 0; --i) {
|
||||
#endif
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
streamWord |= (WORD)(cx->S[t]) << 8*i;
|
||||
mask |= MASK1BYTE << 8*i;
|
||||
} /* } */
|
||||
inWord = *pInWord++;
|
||||
/* If buffers are relatively misaligned, shift the bytes in inWord
|
||||
* to be aligned to the output buffer.
|
||||
*/
|
||||
nextInWord = 0;
|
||||
if (inOffset < outOffset) {
|
||||
/* Have more bytes than needed, shift remainder into nextInWord */
|
||||
nextInWord = inWord LSH 8*(inOffset + byteCount);
|
||||
inWord = inWord RSH bufShift;
|
||||
} else if (inOffset > outOffset) {
|
||||
/* Didn't get enough bytes from current input word, load another
|
||||
* word and then shift remainder into nextInWord.
|
||||
*/
|
||||
nextInWord = *pInWord++;
|
||||
inWord = (inWord LSH invBufShift) |
|
||||
(nextInWord RSH bufShift);
|
||||
nextInWord = nextInWord LSH invBufShift;
|
||||
}
|
||||
/* Store output of first partial word */
|
||||
*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
|
||||
/* Consumed byteCount bytes of input */
|
||||
inputLen -= byteCount;
|
||||
/* move to next word of output */
|
||||
pOutWord++;
|
||||
/* inWord has been consumed, but there may be bytes in nextInWord */
|
||||
inWord = nextInWord;
|
||||
} else {
|
||||
/* output is word-aligned */
|
||||
pOutWord = (WORD *)output;
|
||||
if (inOffset) {
|
||||
/* Input is not word-aligned. The first word load of input
|
||||
* will not produce a full word of input bytes, so one word
|
||||
* must be pre-loaded. The main loop below will load in the
|
||||
* next input word and shift some of its bytes into inWord
|
||||
* in order to create a full input word. Note that the main
|
||||
* loop must execute at least once because the input must
|
||||
* be at least two words.
|
||||
*/
|
||||
inWord = *pInWord++;
|
||||
inWord = inWord LSH invBufShift;
|
||||
} else {
|
||||
/* Input is word-aligned. The first word load of input
|
||||
* will produce a full word of input bytes, so nothing
|
||||
* needs to be loaded here.
|
||||
*/
|
||||
inWord = 0;
|
||||
}
|
||||
}
|
||||
/* Output buffer is aligned, inOffset is now measured relative to
|
||||
* outOffset (and not a word boundary).
|
||||
*/
|
||||
inOffset = (inOffset + WORDSIZE - outOffset) % WORDSIZE;
|
||||
/*****************************************************************/
|
||||
/* Step 2: main loop */
|
||||
/* At this point the output buffer is word-aligned. Any unused */
|
||||
/* bytes from above will be in inWord (shifted correctly). If */
|
||||
/* the input buffer is unaligned relative to the output buffer, */
|
||||
/* shifting has to be done. */
|
||||
/*****************************************************************/
|
||||
if (inOffset) {
|
||||
for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
|
||||
nextInWord = *pInWord++;
|
||||
inWord |= nextInWord RSH bufShift;
|
||||
nextInWord = nextInWord LSH invBufShift;
|
||||
ARCFOUR_NEXT_WORD();
|
||||
*pOutWord++ = inWord ^ streamWord;
|
||||
inWord = nextInWord;
|
||||
}
|
||||
if (inputLen == 0) {
|
||||
/* Nothing left to do. */
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
/* If the amount of remaining input is greater than the amount
|
||||
* bytes pulled from the current input word, need to do another
|
||||
* word load. What's left in inWord will be consumed in step 3.
|
||||
*/
|
||||
if (inputLen > WORDSIZE - inOffset)
|
||||
inWord |= *pInWord RSH bufShift;
|
||||
} else {
|
||||
for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
|
||||
inWord = *pInWord++;
|
||||
ARCFOUR_NEXT_WORD();
|
||||
*pOutWord++ = inWord ^ streamWord;
|
||||
}
|
||||
if (inputLen == 0) {
|
||||
/* Nothing left to do. */
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
} else {
|
||||
/* A partial input word remains at the tail. Load it. The
|
||||
* relevant bytes will be consumed in step 3.
|
||||
*/
|
||||
inWord = *pInWord;
|
||||
}
|
||||
}
|
||||
/*****************************************************************/
|
||||
/* Step 3: */
|
||||
/* A partial word of input remains, and it is already loaded */
|
||||
/* into nextInWord. Shift appropriately and consume the bytes */
|
||||
/* used in the partial word. */
|
||||
/*****************************************************************/
|
||||
mask = streamWord = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
for (i = 0; i < inputLen; ++i) {
|
||||
#else
|
||||
for (i = WORDSIZE - 1; i >= WORDSIZE - inputLen; --i) {
|
||||
#endif
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
streamWord |= (WORD)(cx->S[t]) << 8*i;
|
||||
mask |= MASK1BYTE << 8*i;
|
||||
} /* } */
|
||||
*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
SECStatus
|
||||
RC4_Encrypt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#else
|
||||
/* Operate on bytes, but unroll the main loop */
|
||||
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* decrypt and encrypt are same operation. */
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#else
|
||||
/* Operate on bytes, but unroll the main loop */
|
||||
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef CONVERT_TO_WORDS
|
||||
#undef USE_LONG
|
||||
1002
mozilla/security/nss/lib/freebl/blapi.h
Normal file
2114
mozilla/security/nss/lib/freebl/blapi_bsf.c
Normal file
336
mozilla/security/nss/lib/freebl/blapit.h
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* blapit.h - public data structures for the crypto library
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: blapit.h,v 1.10 2003-03-29 00:18:18 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _BLAPIT_H_
|
||||
#define _BLAPIT_H_
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "prlink.h"
|
||||
#include "plarena.h"
|
||||
|
||||
|
||||
/* RC2 operation modes */
|
||||
#define NSS_RC2 0
|
||||
#define NSS_RC2_CBC 1
|
||||
|
||||
/* RC5 operation modes */
|
||||
#define NSS_RC5 0
|
||||
#define NSS_RC5_CBC 1
|
||||
|
||||
/* DES operation modes */
|
||||
#define NSS_DES 0
|
||||
#define NSS_DES_CBC 1
|
||||
#define NSS_DES_EDE3 2
|
||||
#define NSS_DES_EDE3_CBC 3
|
||||
|
||||
#define DES_KEY_LENGTH 8 /* Bytes */
|
||||
|
||||
/* AES operation modes */
|
||||
#define NSS_AES 0
|
||||
#define NSS_AES_CBC 1
|
||||
|
||||
#define DSA_SIGNATURE_LEN 40 /* Bytes */
|
||||
#define DSA_SUBPRIME_LEN 20 /* Bytes */
|
||||
|
||||
/* XXX We shouldn't have to hard code this limit. For
|
||||
* now, this is the quickest way to support ECDSA signature
|
||||
* processing (ECDSA signature lengths depend on curve
|
||||
* size). This limit is sufficient for curves upto
|
||||
* 576 bits.
|
||||
*/
|
||||
#define MAX_ECKEY_LEN 72 /* Bytes */
|
||||
|
||||
/*
|
||||
* Number of bytes each hash algorithm produces
|
||||
*/
|
||||
#define MD2_LENGTH 16 /* Bytes */
|
||||
#define MD5_LENGTH 16 /* Bytes */
|
||||
#define SHA1_LENGTH 20 /* Bytes */
|
||||
#define SHA256_LENGTH 32 /* bytes */
|
||||
#define SHA384_LENGTH 48 /* bytes */
|
||||
#define SHA512_LENGTH 64 /* bytes */
|
||||
#define HASH_LENGTH_MAX SHA512_LENGTH
|
||||
|
||||
/*
|
||||
* Input block size for each hash algorithm.
|
||||
*/
|
||||
|
||||
#define SHA256_BLOCK_LENGTH 64 /* bytes */
|
||||
#define SHA384_BLOCK_LENGTH 128 /* bytes */
|
||||
#define SHA512_BLOCK_LENGTH 128 /* bytes */
|
||||
|
||||
#define AES_KEY_WRAP_IV_BYTES 8
|
||||
#define AES_KEY_WRAP_BLOCK_SIZE 8 /* bytes */
|
||||
#define AES_BLOCK_SIZE 16 /* bytes */
|
||||
|
||||
#define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
/*
|
||||
* The FIPS 186 algorithm for generating primes P and Q allows only 9
|
||||
* distinct values for the length of P, and only one value for the
|
||||
* length of Q.
|
||||
* The algorithm uses a variable j to indicate which of the 9 lengths
|
||||
* of P is to be used.
|
||||
* The following table relates j to the lengths of P and Q in bits.
|
||||
*
|
||||
* j bits in P bits in Q
|
||||
* _ _________ _________
|
||||
* 0 512 160
|
||||
* 1 576 160
|
||||
* 2 640 160
|
||||
* 3 704 160
|
||||
* 4 768 160
|
||||
* 5 832 160
|
||||
* 6 896 160
|
||||
* 7 960 160
|
||||
* 8 1024 160
|
||||
*
|
||||
* The FIPS-186 compliant PQG generator takes j as an input parameter.
|
||||
*/
|
||||
|
||||
#define DSA_Q_BITS 160
|
||||
#define DSA_MAX_P_BITS 1024
|
||||
#define DSA_MIN_P_BITS 512
|
||||
|
||||
/*
|
||||
* function takes desired number of bits in P,
|
||||
* returns index (0..8) or -1 if number of bits is invalid.
|
||||
*/
|
||||
#define PQG_PBITS_TO_INDEX(bits) ((((bits)-512) % 64) ? -1 : (int)((bits)-512)/64)
|
||||
|
||||
/*
|
||||
* function takes index (0-8)
|
||||
* returns number of bits in P for that index, or -1 if index is invalid.
|
||||
*/
|
||||
#define PQG_INDEX_TO_PBITS(j) (((unsigned)(j) > 8) ? -1 : (512 + 64 * (j)))
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Opaque objects
|
||||
*/
|
||||
|
||||
struct DESContextStr ;
|
||||
struct RC2ContextStr ;
|
||||
struct RC4ContextStr ;
|
||||
struct RC5ContextStr ;
|
||||
struct AESContextStr ;
|
||||
struct MD2ContextStr ;
|
||||
struct MD5ContextStr ;
|
||||
struct SHA1ContextStr ;
|
||||
struct SHA256ContextStr ;
|
||||
struct SHA512ContextStr ;
|
||||
struct AESKeyWrapContextStr ;
|
||||
|
||||
typedef struct DESContextStr DESContext;
|
||||
typedef struct RC2ContextStr RC2Context;
|
||||
typedef struct RC4ContextStr RC4Context;
|
||||
typedef struct RC5ContextStr RC5Context;
|
||||
typedef struct AESContextStr AESContext;
|
||||
typedef struct MD2ContextStr MD2Context;
|
||||
typedef struct MD5ContextStr MD5Context;
|
||||
typedef struct SHA1ContextStr SHA1Context;
|
||||
typedef struct SHA256ContextStr SHA256Context;
|
||||
typedef struct SHA512ContextStr SHA512Context;
|
||||
/* SHA384Context is really a SHA512ContextStr. This is not a mistake. */
|
||||
typedef struct SHA512ContextStr SHA384Context;
|
||||
typedef struct AESKeyWrapContextStr AESKeyWrapContext;
|
||||
|
||||
/***************************************************************************
|
||||
** RSA Public and Private Key structures
|
||||
*/
|
||||
|
||||
/* member names from PKCS#1, section 7.1 */
|
||||
struct RSAPublicKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem modulus;
|
||||
SECItem publicExponent;
|
||||
};
|
||||
typedef struct RSAPublicKeyStr RSAPublicKey;
|
||||
|
||||
/* member names from PKCS#1, section 7.2 */
|
||||
struct RSAPrivateKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem version;
|
||||
SECItem modulus;
|
||||
SECItem publicExponent;
|
||||
SECItem privateExponent;
|
||||
SECItem prime1;
|
||||
SECItem prime2;
|
||||
SECItem exponent1;
|
||||
SECItem exponent2;
|
||||
SECItem coefficient;
|
||||
};
|
||||
typedef struct RSAPrivateKeyStr RSAPrivateKey;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** DSA Public and Private Key and related structures
|
||||
*/
|
||||
|
||||
struct PQGParamsStr {
|
||||
PRArenaPool *arena;
|
||||
SECItem prime; /* p */
|
||||
SECItem subPrime; /* q */
|
||||
SECItem base; /* g */
|
||||
/* XXX chrisk: this needs to be expanded to hold j and validationParms (RFC2459 7.3.2) */
|
||||
};
|
||||
typedef struct PQGParamsStr PQGParams;
|
||||
|
||||
struct PQGVerifyStr {
|
||||
PRArenaPool * arena; /* includes this struct, seed, & h. */
|
||||
unsigned int counter;
|
||||
SECItem seed;
|
||||
SECItem h;
|
||||
};
|
||||
typedef struct PQGVerifyStr PQGVerify;
|
||||
|
||||
struct DSAPublicKeyStr {
|
||||
PQGParams params;
|
||||
SECItem publicValue;
|
||||
};
|
||||
typedef struct DSAPublicKeyStr DSAPublicKey;
|
||||
|
||||
struct DSAPrivateKeyStr {
|
||||
PQGParams params;
|
||||
SECItem publicValue;
|
||||
SECItem privateValue;
|
||||
};
|
||||
typedef struct DSAPrivateKeyStr DSAPrivateKey;
|
||||
|
||||
/***************************************************************************
|
||||
** Diffie-Hellman Public and Private Key and related structures
|
||||
** Structure member names suggested by PKCS#3.
|
||||
*/
|
||||
|
||||
struct DHParamsStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime; /* p */
|
||||
SECItem base; /* g */
|
||||
};
|
||||
typedef struct DHParamsStr DHParams;
|
||||
|
||||
struct DHPublicKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime;
|
||||
SECItem base;
|
||||
SECItem publicValue;
|
||||
};
|
||||
typedef struct DHPublicKeyStr DHPublicKey;
|
||||
|
||||
struct DHPrivateKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime;
|
||||
SECItem base;
|
||||
SECItem publicValue;
|
||||
SECItem privateValue;
|
||||
};
|
||||
typedef struct DHPrivateKeyStr DHPrivateKey;
|
||||
|
||||
/***************************************************************************
|
||||
** Data structures used for elliptic curve parameters and
|
||||
** public and private keys.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The ECParams data structures can encode elliptic curve
|
||||
** parameters for both GFp and GF2m curves.
|
||||
*/
|
||||
|
||||
typedef enum { ec_params_explicit,
|
||||
ec_params_named
|
||||
} ECParamsType;
|
||||
|
||||
typedef enum { ec_field_GFp = 1,
|
||||
ec_field_GF2m
|
||||
} ECFieldType;
|
||||
|
||||
struct ECFieldIDStr {
|
||||
int size; /* field size in bits */
|
||||
ECFieldType type;
|
||||
union {
|
||||
SECItem prime; /* prime p for (GFp) */
|
||||
SECItem poly; /* irreducible binary polynomial for (GF2m) */
|
||||
} u;
|
||||
int k1; /* first coefficient of pentanomial or
|
||||
* the only coefficient of trinomial
|
||||
*/
|
||||
int k2; /* two remaining coefficients of pentanomial */
|
||||
int k3;
|
||||
};
|
||||
typedef struct ECFieldIDStr ECFieldID;
|
||||
|
||||
struct ECCurveStr {
|
||||
SECItem a; /* contains octet stream encoding of
|
||||
* field element (X9.62 section 4.3.3)
|
||||
*/
|
||||
SECItem b;
|
||||
SECItem seed;
|
||||
};
|
||||
typedef struct ECCurveStr ECCurve;
|
||||
|
||||
struct ECParamsStr {
|
||||
PRArenaPool * arena;
|
||||
ECParamsType type;
|
||||
ECFieldID fieldID;
|
||||
ECCurve curve;
|
||||
SECItem base;
|
||||
SECItem order;
|
||||
int cofactor;
|
||||
SECItem DEREncoding;
|
||||
};
|
||||
typedef struct ECParamsStr ECParams;
|
||||
|
||||
struct ECPublicKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* elliptic curve point encoded as
|
||||
* octet stream.
|
||||
*/
|
||||
};
|
||||
typedef struct ECPublicKeyStr ECPublicKey;
|
||||
|
||||
struct ECPrivateKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* encoded ec point */
|
||||
SECItem privateValue; /* private big integer */
|
||||
};
|
||||
typedef struct ECPrivateKeyStr ECPrivateKey;
|
||||
|
||||
#endif /* _BLAPIT_H_ */
|
||||
103
mozilla/security/nss/lib/freebl/config.mk
Normal file
@@ -0,0 +1,103 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
# only do this in the outermost freebl build.
|
||||
ifndef FREEBL_RECURSIVE_BUILD
|
||||
# we only do this stuff for some of the 32-bit builds, no 64-bit builds
|
||||
ifndef USE_64
|
||||
|
||||
ifeq ($(OS_TARGET), HP-UX)
|
||||
ifneq ($(OS_TEST), ia64)
|
||||
FREEBL_EXTENDED_BUILD = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
FREEBL_EXTENDED_BUILD = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef FREEBL_EXTENDED_BUILD
|
||||
# We're going to change this build so that it builds libfreebl.a with
|
||||
# just loader.c. Then we have to build this directory twice again to
|
||||
# build the two DSOs.
|
||||
# To build libfreebl.a with just loader.c, we must now override many
|
||||
# of the make variables setup by the prior inclusion of CORECONF's config.mk
|
||||
|
||||
CSRCS = loader.c sysrand.c
|
||||
SIMPLE_OBJS = $(CSRCS:.c=$(OBJ_SUFFIX))
|
||||
OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(SIMPLE_OBJS))
|
||||
ALL_TRASH := $(TARGETS) $(OBJS) $(OBJDIR) LOGS TAGS $(GARBAGE) \
|
||||
$(NOSUCHFILE) so_locations
|
||||
endif
|
||||
|
||||
#end of 32-bit only stuff.
|
||||
endif
|
||||
|
||||
# Override the values defined in coreconf's ruleset.mk.
|
||||
#
|
||||
# - (1) LIBRARY: a static (archival) library
|
||||
# - (2) SHARED_LIBRARY: a shared (dynamic link) library
|
||||
# - (3) IMPORT_LIBRARY: an import library, used only on Windows
|
||||
# - (4) PROGRAM: an executable binary
|
||||
#
|
||||
# override these variables to prevent building a DSO/DLL.
|
||||
TARGETS = $(LIBRARY)
|
||||
SHARED_LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
else
|
||||
# This is a recursive build.
|
||||
|
||||
TARGETS = $(SHARED_LIBRARY)
|
||||
LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
#ifeq ($(OS_TARGET), HP-UX)
|
||||
EXTRA_LIBS += \
|
||||
$(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
|
||||
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(DIST)/lib/ \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
-lc
|
||||
#endif
|
||||
|
||||
endif
|
||||
683
mozilla/security/nss/lib/freebl/des.c
Normal file
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
* des.c
|
||||
*
|
||||
* core source file for DES-150 library
|
||||
* Make key schedule from DES key.
|
||||
* Encrypt/Decrypt one 8-byte block.
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Nelson B. Bolyard,
|
||||
* nelsonb@iname.com. Portions created by Nelson B. Bolyard are
|
||||
* Copyright (C) 1990, 2000 Nelson B. Bolyard, All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
#include "des.h"
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
/* #define USE_INDEXING 1 */
|
||||
|
||||
/*
|
||||
* The tables below are the 8 sbox functions, with the 6-bit input permutation
|
||||
* and the 32-bit output permutation pre-computed.
|
||||
* They are shifted circularly to the left 3 bits, which removes 2 shifts
|
||||
* and an or from each round by reducing the number of sboxes whose
|
||||
* indices cross word broundaries from 2 to 1.
|
||||
*/
|
||||
|
||||
static const HALF SP[8][64] = {
|
||||
/* Box S1 */ {
|
||||
0x04041000, 0x00000000, 0x00040000, 0x04041010,
|
||||
0x04040010, 0x00041010, 0x00000010, 0x00040000,
|
||||
0x00001000, 0x04041000, 0x04041010, 0x00001000,
|
||||
0x04001010, 0x04040010, 0x04000000, 0x00000010,
|
||||
0x00001010, 0x04001000, 0x04001000, 0x00041000,
|
||||
0x00041000, 0x04040000, 0x04040000, 0x04001010,
|
||||
0x00040010, 0x04000010, 0x04000010, 0x00040010,
|
||||
0x00000000, 0x00001010, 0x00041010, 0x04000000,
|
||||
0x00040000, 0x04041010, 0x00000010, 0x04040000,
|
||||
0x04041000, 0x04000000, 0x04000000, 0x00001000,
|
||||
0x04040010, 0x00040000, 0x00041000, 0x04000010,
|
||||
0x00001000, 0x00000010, 0x04001010, 0x00041010,
|
||||
0x04041010, 0x00040010, 0x04040000, 0x04001010,
|
||||
0x04000010, 0x00001010, 0x00041010, 0x04041000,
|
||||
0x00001010, 0x04001000, 0x04001000, 0x00000000,
|
||||
0x00040010, 0x00041000, 0x00000000, 0x04040010
|
||||
},
|
||||
/* Box S2 */ {
|
||||
0x00420082, 0x00020002, 0x00020000, 0x00420080,
|
||||
0x00400000, 0x00000080, 0x00400082, 0x00020082,
|
||||
0x00000082, 0x00420082, 0x00420002, 0x00000002,
|
||||
0x00020002, 0x00400000, 0x00000080, 0x00400082,
|
||||
0x00420000, 0x00400080, 0x00020082, 0x00000000,
|
||||
0x00000002, 0x00020000, 0x00420080, 0x00400002,
|
||||
0x00400080, 0x00000082, 0x00000000, 0x00420000,
|
||||
0x00020080, 0x00420002, 0x00400002, 0x00020080,
|
||||
0x00000000, 0x00420080, 0x00400082, 0x00400000,
|
||||
0x00020082, 0x00400002, 0x00420002, 0x00020000,
|
||||
0x00400002, 0x00020002, 0x00000080, 0x00420082,
|
||||
0x00420080, 0x00000080, 0x00020000, 0x00000002,
|
||||
0x00020080, 0x00420002, 0x00400000, 0x00000082,
|
||||
0x00400080, 0x00020082, 0x00000082, 0x00400080,
|
||||
0x00420000, 0x00000000, 0x00020002, 0x00020080,
|
||||
0x00000002, 0x00400082, 0x00420082, 0x00420000
|
||||
},
|
||||
/* Box S3 */ {
|
||||
0x00000820, 0x20080800, 0x00000000, 0x20080020,
|
||||
0x20000800, 0x00000000, 0x00080820, 0x20000800,
|
||||
0x00080020, 0x20000020, 0x20000020, 0x00080000,
|
||||
0x20080820, 0x00080020, 0x20080000, 0x00000820,
|
||||
0x20000000, 0x00000020, 0x20080800, 0x00000800,
|
||||
0x00080800, 0x20080000, 0x20080020, 0x00080820,
|
||||
0x20000820, 0x00080800, 0x00080000, 0x20000820,
|
||||
0x00000020, 0x20080820, 0x00000800, 0x20000000,
|
||||
0x20080800, 0x20000000, 0x00080020, 0x00000820,
|
||||
0x00080000, 0x20080800, 0x20000800, 0x00000000,
|
||||
0x00000800, 0x00080020, 0x20080820, 0x20000800,
|
||||
0x20000020, 0x00000800, 0x00000000, 0x20080020,
|
||||
0x20000820, 0x00080000, 0x20000000, 0x20080820,
|
||||
0x00000020, 0x00080820, 0x00080800, 0x20000020,
|
||||
0x20080000, 0x20000820, 0x00000820, 0x20080000,
|
||||
0x00080820, 0x00000020, 0x20080020, 0x00080800
|
||||
},
|
||||
/* Box S4 */ {
|
||||
0x02008004, 0x00008204, 0x00008204, 0x00000200,
|
||||
0x02008200, 0x02000204, 0x02000004, 0x00008004,
|
||||
0x00000000, 0x02008000, 0x02008000, 0x02008204,
|
||||
0x00000204, 0x00000000, 0x02000200, 0x02000004,
|
||||
0x00000004, 0x00008000, 0x02000000, 0x02008004,
|
||||
0x00000200, 0x02000000, 0x00008004, 0x00008200,
|
||||
0x02000204, 0x00000004, 0x00008200, 0x02000200,
|
||||
0x00008000, 0x02008200, 0x02008204, 0x00000204,
|
||||
0x02000200, 0x02000004, 0x02008000, 0x02008204,
|
||||
0x00000204, 0x00000000, 0x00000000, 0x02008000,
|
||||
0x00008200, 0x02000200, 0x02000204, 0x00000004,
|
||||
0x02008004, 0x00008204, 0x00008204, 0x00000200,
|
||||
0x02008204, 0x00000204, 0x00000004, 0x00008000,
|
||||
0x02000004, 0x00008004, 0x02008200, 0x02000204,
|
||||
0x00008004, 0x00008200, 0x02000000, 0x02008004,
|
||||
0x00000200, 0x02000000, 0x00008000, 0x02008200
|
||||
},
|
||||
/* Box S5 */ {
|
||||
0x00000400, 0x08200400, 0x08200000, 0x08000401,
|
||||
0x00200000, 0x00000400, 0x00000001, 0x08200000,
|
||||
0x00200401, 0x00200000, 0x08000400, 0x00200401,
|
||||
0x08000401, 0x08200001, 0x00200400, 0x00000001,
|
||||
0x08000000, 0x00200001, 0x00200001, 0x00000000,
|
||||
0x00000401, 0x08200401, 0x08200401, 0x08000400,
|
||||
0x08200001, 0x00000401, 0x00000000, 0x08000001,
|
||||
0x08200400, 0x08000000, 0x08000001, 0x00200400,
|
||||
0x00200000, 0x08000401, 0x00000400, 0x08000000,
|
||||
0x00000001, 0x08200000, 0x08000401, 0x00200401,
|
||||
0x08000400, 0x00000001, 0x08200001, 0x08200400,
|
||||
0x00200401, 0x00000400, 0x08000000, 0x08200001,
|
||||
0x08200401, 0x00200400, 0x08000001, 0x08200401,
|
||||
0x08200000, 0x00000000, 0x00200001, 0x08000001,
|
||||
0x00200400, 0x08000400, 0x00000401, 0x00200000,
|
||||
0x00000000, 0x00200001, 0x08200400, 0x00000401
|
||||
},
|
||||
/* Box S6 */ {
|
||||
0x80000040, 0x81000000, 0x00010000, 0x81010040,
|
||||
0x81000000, 0x00000040, 0x81010040, 0x01000000,
|
||||
0x80010000, 0x01010040, 0x01000000, 0x80000040,
|
||||
0x01000040, 0x80010000, 0x80000000, 0x00010040,
|
||||
0x00000000, 0x01000040, 0x80010040, 0x00010000,
|
||||
0x01010000, 0x80010040, 0x00000040, 0x81000040,
|
||||
0x81000040, 0x00000000, 0x01010040, 0x81010000,
|
||||
0x00010040, 0x01010000, 0x81010000, 0x80000000,
|
||||
0x80010000, 0x00000040, 0x81000040, 0x01010000,
|
||||
0x81010040, 0x01000000, 0x00010040, 0x80000040,
|
||||
0x01000000, 0x80010000, 0x80000000, 0x00010040,
|
||||
0x80000040, 0x81010040, 0x01010000, 0x81000000,
|
||||
0x01010040, 0x81010000, 0x00000000, 0x81000040,
|
||||
0x00000040, 0x00010000, 0x81000000, 0x01010040,
|
||||
0x00010000, 0x01000040, 0x80010040, 0x00000000,
|
||||
0x81010000, 0x80000000, 0x01000040, 0x80010040
|
||||
},
|
||||
/* Box S7 */ {
|
||||
0x00800000, 0x10800008, 0x10002008, 0x00000000,
|
||||
0x00002000, 0x10002008, 0x00802008, 0x10802000,
|
||||
0x10802008, 0x00800000, 0x00000000, 0x10000008,
|
||||
0x00000008, 0x10000000, 0x10800008, 0x00002008,
|
||||
0x10002000, 0x00802008, 0x00800008, 0x10002000,
|
||||
0x10000008, 0x10800000, 0x10802000, 0x00800008,
|
||||
0x10800000, 0x00002000, 0x00002008, 0x10802008,
|
||||
0x00802000, 0x00000008, 0x10000000, 0x00802000,
|
||||
0x10000000, 0x00802000, 0x00800000, 0x10002008,
|
||||
0x10002008, 0x10800008, 0x10800008, 0x00000008,
|
||||
0x00800008, 0x10000000, 0x10002000, 0x00800000,
|
||||
0x10802000, 0x00002008, 0x00802008, 0x10802000,
|
||||
0x00002008, 0x10000008, 0x10802008, 0x10800000,
|
||||
0x00802000, 0x00000000, 0x00000008, 0x10802008,
|
||||
0x00000000, 0x00802008, 0x10800000, 0x00002000,
|
||||
0x10000008, 0x10002000, 0x00002000, 0x00800008
|
||||
},
|
||||
/* Box S8 */ {
|
||||
0x40004100, 0x00004000, 0x00100000, 0x40104100,
|
||||
0x40000000, 0x40004100, 0x00000100, 0x40000000,
|
||||
0x00100100, 0x40100000, 0x40104100, 0x00104000,
|
||||
0x40104000, 0x00104100, 0x00004000, 0x00000100,
|
||||
0x40100000, 0x40000100, 0x40004000, 0x00004100,
|
||||
0x00104000, 0x00100100, 0x40100100, 0x40104000,
|
||||
0x00004100, 0x00000000, 0x00000000, 0x40100100,
|
||||
0x40000100, 0x40004000, 0x00104100, 0x00100000,
|
||||
0x00104100, 0x00100000, 0x40104000, 0x00004000,
|
||||
0x00000100, 0x40100100, 0x00004000, 0x00104100,
|
||||
0x40004000, 0x00000100, 0x40000100, 0x40100000,
|
||||
0x40100100, 0x40000000, 0x00100000, 0x40004100,
|
||||
0x00000000, 0x40104100, 0x00100100, 0x40000100,
|
||||
0x40100000, 0x40004000, 0x40004100, 0x00000000,
|
||||
0x40104100, 0x00104000, 0x00104000, 0x00004100,
|
||||
0x00004100, 0x00100100, 0x40000000, 0x40104000
|
||||
}
|
||||
};
|
||||
|
||||
static const HALF PC2[8][64] = {
|
||||
/* table 0 */ {
|
||||
0x00000000, 0x00001000, 0x04000000, 0x04001000,
|
||||
0x00100000, 0x00101000, 0x04100000, 0x04101000,
|
||||
0x00008000, 0x00009000, 0x04008000, 0x04009000,
|
||||
0x00108000, 0x00109000, 0x04108000, 0x04109000,
|
||||
0x00000004, 0x00001004, 0x04000004, 0x04001004,
|
||||
0x00100004, 0x00101004, 0x04100004, 0x04101004,
|
||||
0x00008004, 0x00009004, 0x04008004, 0x04009004,
|
||||
0x00108004, 0x00109004, 0x04108004, 0x04109004,
|
||||
0x08000000, 0x08001000, 0x0c000000, 0x0c001000,
|
||||
0x08100000, 0x08101000, 0x0c100000, 0x0c101000,
|
||||
0x08008000, 0x08009000, 0x0c008000, 0x0c009000,
|
||||
0x08108000, 0x08109000, 0x0c108000, 0x0c109000,
|
||||
0x08000004, 0x08001004, 0x0c000004, 0x0c001004,
|
||||
0x08100004, 0x08101004, 0x0c100004, 0x0c101004,
|
||||
0x08008004, 0x08009004, 0x0c008004, 0x0c009004,
|
||||
0x08108004, 0x08109004, 0x0c108004, 0x0c109004
|
||||
},
|
||||
/* table 1 */ {
|
||||
0x00000000, 0x00002000, 0x80000000, 0x80002000,
|
||||
0x00000008, 0x00002008, 0x80000008, 0x80002008,
|
||||
0x00200000, 0x00202000, 0x80200000, 0x80202000,
|
||||
0x00200008, 0x00202008, 0x80200008, 0x80202008,
|
||||
0x20000000, 0x20002000, 0xa0000000, 0xa0002000,
|
||||
0x20000008, 0x20002008, 0xa0000008, 0xa0002008,
|
||||
0x20200000, 0x20202000, 0xa0200000, 0xa0202000,
|
||||
0x20200008, 0x20202008, 0xa0200008, 0xa0202008,
|
||||
0x00000400, 0x00002400, 0x80000400, 0x80002400,
|
||||
0x00000408, 0x00002408, 0x80000408, 0x80002408,
|
||||
0x00200400, 0x00202400, 0x80200400, 0x80202400,
|
||||
0x00200408, 0x00202408, 0x80200408, 0x80202408,
|
||||
0x20000400, 0x20002400, 0xa0000400, 0xa0002400,
|
||||
0x20000408, 0x20002408, 0xa0000408, 0xa0002408,
|
||||
0x20200400, 0x20202400, 0xa0200400, 0xa0202400,
|
||||
0x20200408, 0x20202408, 0xa0200408, 0xa0202408
|
||||
},
|
||||
/* table 2 */ {
|
||||
0x00000000, 0x00004000, 0x00000020, 0x00004020,
|
||||
0x00080000, 0x00084000, 0x00080020, 0x00084020,
|
||||
0x00000800, 0x00004800, 0x00000820, 0x00004820,
|
||||
0x00080800, 0x00084800, 0x00080820, 0x00084820,
|
||||
0x00000010, 0x00004010, 0x00000030, 0x00004030,
|
||||
0x00080010, 0x00084010, 0x00080030, 0x00084030,
|
||||
0x00000810, 0x00004810, 0x00000830, 0x00004830,
|
||||
0x00080810, 0x00084810, 0x00080830, 0x00084830,
|
||||
0x00400000, 0x00404000, 0x00400020, 0x00404020,
|
||||
0x00480000, 0x00484000, 0x00480020, 0x00484020,
|
||||
0x00400800, 0x00404800, 0x00400820, 0x00404820,
|
||||
0x00480800, 0x00484800, 0x00480820, 0x00484820,
|
||||
0x00400010, 0x00404010, 0x00400030, 0x00404030,
|
||||
0x00480010, 0x00484010, 0x00480030, 0x00484030,
|
||||
0x00400810, 0x00404810, 0x00400830, 0x00404830,
|
||||
0x00480810, 0x00484810, 0x00480830, 0x00484830
|
||||
},
|
||||
/* table 3 */ {
|
||||
0x00000000, 0x40000000, 0x00000080, 0x40000080,
|
||||
0x00040000, 0x40040000, 0x00040080, 0x40040080,
|
||||
0x00000040, 0x40000040, 0x000000c0, 0x400000c0,
|
||||
0x00040040, 0x40040040, 0x000400c0, 0x400400c0,
|
||||
0x10000000, 0x50000000, 0x10000080, 0x50000080,
|
||||
0x10040000, 0x50040000, 0x10040080, 0x50040080,
|
||||
0x10000040, 0x50000040, 0x100000c0, 0x500000c0,
|
||||
0x10040040, 0x50040040, 0x100400c0, 0x500400c0,
|
||||
0x00800000, 0x40800000, 0x00800080, 0x40800080,
|
||||
0x00840000, 0x40840000, 0x00840080, 0x40840080,
|
||||
0x00800040, 0x40800040, 0x008000c0, 0x408000c0,
|
||||
0x00840040, 0x40840040, 0x008400c0, 0x408400c0,
|
||||
0x10800000, 0x50800000, 0x10800080, 0x50800080,
|
||||
0x10840000, 0x50840000, 0x10840080, 0x50840080,
|
||||
0x10800040, 0x50800040, 0x108000c0, 0x508000c0,
|
||||
0x10840040, 0x50840040, 0x108400c0, 0x508400c0
|
||||
},
|
||||
/* table 4 */ {
|
||||
0x00000000, 0x00000008, 0x08000000, 0x08000008,
|
||||
0x00040000, 0x00040008, 0x08040000, 0x08040008,
|
||||
0x00002000, 0x00002008, 0x08002000, 0x08002008,
|
||||
0x00042000, 0x00042008, 0x08042000, 0x08042008,
|
||||
0x80000000, 0x80000008, 0x88000000, 0x88000008,
|
||||
0x80040000, 0x80040008, 0x88040000, 0x88040008,
|
||||
0x80002000, 0x80002008, 0x88002000, 0x88002008,
|
||||
0x80042000, 0x80042008, 0x88042000, 0x88042008,
|
||||
0x00080000, 0x00080008, 0x08080000, 0x08080008,
|
||||
0x000c0000, 0x000c0008, 0x080c0000, 0x080c0008,
|
||||
0x00082000, 0x00082008, 0x08082000, 0x08082008,
|
||||
0x000c2000, 0x000c2008, 0x080c2000, 0x080c2008,
|
||||
0x80080000, 0x80080008, 0x88080000, 0x88080008,
|
||||
0x800c0000, 0x800c0008, 0x880c0000, 0x880c0008,
|
||||
0x80082000, 0x80082008, 0x88082000, 0x88082008,
|
||||
0x800c2000, 0x800c2008, 0x880c2000, 0x880c2008
|
||||
},
|
||||
/* table 5 */ {
|
||||
0x00000000, 0x00400000, 0x00008000, 0x00408000,
|
||||
0x40000000, 0x40400000, 0x40008000, 0x40408000,
|
||||
0x00000020, 0x00400020, 0x00008020, 0x00408020,
|
||||
0x40000020, 0x40400020, 0x40008020, 0x40408020,
|
||||
0x00001000, 0x00401000, 0x00009000, 0x00409000,
|
||||
0x40001000, 0x40401000, 0x40009000, 0x40409000,
|
||||
0x00001020, 0x00401020, 0x00009020, 0x00409020,
|
||||
0x40001020, 0x40401020, 0x40009020, 0x40409020,
|
||||
0x00100000, 0x00500000, 0x00108000, 0x00508000,
|
||||
0x40100000, 0x40500000, 0x40108000, 0x40508000,
|
||||
0x00100020, 0x00500020, 0x00108020, 0x00508020,
|
||||
0x40100020, 0x40500020, 0x40108020, 0x40508020,
|
||||
0x00101000, 0x00501000, 0x00109000, 0x00509000,
|
||||
0x40101000, 0x40501000, 0x40109000, 0x40509000,
|
||||
0x00101020, 0x00501020, 0x00109020, 0x00509020,
|
||||
0x40101020, 0x40501020, 0x40109020, 0x40509020
|
||||
},
|
||||
/* table 6 */ {
|
||||
0x00000000, 0x00000040, 0x04000000, 0x04000040,
|
||||
0x00000800, 0x00000840, 0x04000800, 0x04000840,
|
||||
0x00800000, 0x00800040, 0x04800000, 0x04800040,
|
||||
0x00800800, 0x00800840, 0x04800800, 0x04800840,
|
||||
0x10000000, 0x10000040, 0x14000000, 0x14000040,
|
||||
0x10000800, 0x10000840, 0x14000800, 0x14000840,
|
||||
0x10800000, 0x10800040, 0x14800000, 0x14800040,
|
||||
0x10800800, 0x10800840, 0x14800800, 0x14800840,
|
||||
0x00000080, 0x000000c0, 0x04000080, 0x040000c0,
|
||||
0x00000880, 0x000008c0, 0x04000880, 0x040008c0,
|
||||
0x00800080, 0x008000c0, 0x04800080, 0x048000c0,
|
||||
0x00800880, 0x008008c0, 0x04800880, 0x048008c0,
|
||||
0x10000080, 0x100000c0, 0x14000080, 0x140000c0,
|
||||
0x10000880, 0x100008c0, 0x14000880, 0x140008c0,
|
||||
0x10800080, 0x108000c0, 0x14800080, 0x148000c0,
|
||||
0x10800880, 0x108008c0, 0x14800880, 0x148008c0
|
||||
},
|
||||
/* table 7 */ {
|
||||
0x00000000, 0x00000010, 0x00000400, 0x00000410,
|
||||
0x00000004, 0x00000014, 0x00000404, 0x00000414,
|
||||
0x00004000, 0x00004010, 0x00004400, 0x00004410,
|
||||
0x00004004, 0x00004014, 0x00004404, 0x00004414,
|
||||
0x20000000, 0x20000010, 0x20000400, 0x20000410,
|
||||
0x20000004, 0x20000014, 0x20000404, 0x20000414,
|
||||
0x20004000, 0x20004010, 0x20004400, 0x20004410,
|
||||
0x20004004, 0x20004014, 0x20004404, 0x20004414,
|
||||
0x00200000, 0x00200010, 0x00200400, 0x00200410,
|
||||
0x00200004, 0x00200014, 0x00200404, 0x00200414,
|
||||
0x00204000, 0x00204010, 0x00204400, 0x00204410,
|
||||
0x00204004, 0x00204014, 0x00204404, 0x00204414,
|
||||
0x20200000, 0x20200010, 0x20200400, 0x20200410,
|
||||
0x20200004, 0x20200014, 0x20200404, 0x20200414,
|
||||
0x20204000, 0x20204010, 0x20204400, 0x20204410,
|
||||
0x20204004, 0x20204014, 0x20204404, 0x20204414
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The PC-1 Permutation
|
||||
* If we number the bits of the 8 bytes of key input like this (in octal):
|
||||
* 00 01 02 03 04 05 06 07
|
||||
* 10 11 12 13 14 15 16 17
|
||||
* 20 21 22 23 24 25 26 27
|
||||
* 30 31 32 33 34 35 36 37
|
||||
* 40 41 42 43 44 45 46 47
|
||||
* 50 51 52 53 54 55 56 57
|
||||
* 60 61 62 63 64 65 66 67
|
||||
* 70 71 72 73 74 75 76 77
|
||||
* then after the PC-1 permutation,
|
||||
* C0 is
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 73 63 53 43
|
||||
* D0 is
|
||||
* 76 66 56 46 36 26 16 06
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* 33 23 13 03
|
||||
* and these parity bits have been discarded:
|
||||
* 77 67 57 47 37 27 17 07
|
||||
*
|
||||
* We achieve this by flipping the input matrix about the diagonal from 70-07,
|
||||
* getting left =
|
||||
* 77 67 57 47 37 27 17 07 (these are the parity bits)
|
||||
* 76 66 56 46 36 26 16 06
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* right =
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* then byte swap right, ala htonl() on a little endian machine.
|
||||
* right =
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 71 67 57 47 37 27 11 07
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* then
|
||||
* c0 = right >> 4;
|
||||
* d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
|
||||
*/
|
||||
|
||||
#define FLIP_RIGHT_DIAGONAL(word, temp) \
|
||||
temp = (word ^ (word >> 18)) & 0x00003333; \
|
||||
word ^= temp | (temp << 18); \
|
||||
temp = (word ^ (word >> 9)) & 0x00550055; \
|
||||
word ^= temp | (temp << 9);
|
||||
|
||||
#define BYTESWAP(word, temp) \
|
||||
word = (word >> 16) | (word << 16); \
|
||||
temp = 0x00ff00ff; \
|
||||
word = ((word & temp) << 8) | ((word >> 8) & temp);
|
||||
|
||||
#define PC1(left, right, c0, d0, temp) \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4; \
|
||||
FLIP_RIGHT_DIAGONAL(left, temp); \
|
||||
FLIP_RIGHT_DIAGONAL(right, temp); \
|
||||
BYTESWAP(right, temp); \
|
||||
c0 = right >> 4; \
|
||||
d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
|
||||
|
||||
#define LEFT_SHIFT_1( reg ) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)
|
||||
#define LEFT_SHIFT_2( reg ) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)
|
||||
|
||||
/*
|
||||
* setup key schedules from key
|
||||
*/
|
||||
|
||||
void
|
||||
DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction)
|
||||
{
|
||||
register HALF left, right;
|
||||
register HALF c0, d0;
|
||||
register HALF temp;
|
||||
int delta;
|
||||
unsigned int ls;
|
||||
|
||||
#if defined(_X86_)
|
||||
left = HALFPTR(key)[0];
|
||||
right = HALFPTR(key)[1];
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#else
|
||||
if (((ptrdiff_t)key & 0x03) == 0) {
|
||||
left = HALFPTR(key)[0];
|
||||
right = HALFPTR(key)[1];
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
} else {
|
||||
left = ((HALF)key[0] << 24) | ((HALF)key[1] << 16) |
|
||||
((HALF)key[2] << 8) | key[3];
|
||||
right = ((HALF)key[4] << 24) | ((HALF)key[5] << 16) |
|
||||
((HALF)key[6] << 8) | key[7];
|
||||
}
|
||||
#endif
|
||||
|
||||
PC1(left, right, c0, d0, temp);
|
||||
|
||||
if (direction == DES_ENCRYPT) {
|
||||
delta = 2 * (int)sizeof(HALF);
|
||||
} else {
|
||||
ks += 30;
|
||||
delta = (-2) * (int)sizeof(HALF);
|
||||
}
|
||||
|
||||
for (ls = 0x8103; ls; ls >>= 1) {
|
||||
if ( ls & 1 ) {
|
||||
c0 = LEFT_SHIFT_1( c0 );
|
||||
d0 = LEFT_SHIFT_1( d0 );
|
||||
} else {
|
||||
c0 = LEFT_SHIFT_2( c0 );
|
||||
d0 = LEFT_SHIFT_2( d0 );
|
||||
}
|
||||
|
||||
#ifdef USE_INDEXING
|
||||
#define PC2LOOKUP(b,c) PC2[b][c]
|
||||
|
||||
left = PC2LOOKUP(0, ((c0 >> 22) & 0x3F) );
|
||||
left |= PC2LOOKUP(1, ((c0 >> 13) & 0x3F) );
|
||||
left |= PC2LOOKUP(2, ((c0 >> 4) & 0x38) | (c0 & 0x7) );
|
||||
left |= PC2LOOKUP(3, ((c0>>18)&0xC) | ((c0>>11)&0x3) | (c0&0x30));
|
||||
|
||||
right = PC2LOOKUP(4, ((d0 >> 22) & 0x3F) );
|
||||
right |= PC2LOOKUP(5, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf) );
|
||||
right |= PC2LOOKUP(6, ((d0 >> 7) & 0x3F) );
|
||||
right |= PC2LOOKUP(7, ((d0 >> 1) & 0x3C) | (d0 & 0x3));
|
||||
#else
|
||||
#define PC2LOOKUP(b,c) *(HALF *)((BYTE *)&PC2[b][0]+(c))
|
||||
|
||||
left = PC2LOOKUP(0, ((c0 >> 20) & 0xFC) );
|
||||
left |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC) );
|
||||
left |= PC2LOOKUP(2, ((c0 >> 2) & 0xE0) | ((c0 << 2) & 0x1C) );
|
||||
left |= PC2LOOKUP(3, ((c0>>16)&0x30)|((c0>>9)&0xC)|((c0<<2)&0xC0));
|
||||
|
||||
right = PC2LOOKUP(4, ((d0 >> 20) & 0xFC) );
|
||||
right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C) );
|
||||
right |= PC2LOOKUP(6, ((d0 >> 5) & 0xFC) );
|
||||
right |= PC2LOOKUP(7, ((d0 << 1) & 0xF0) | ((d0 << 2) & 0x0C));
|
||||
#endif
|
||||
/* left contains key bits for S1 S3 S2 S4 */
|
||||
/* right contains key bits for S6 S8 S5 S7 */
|
||||
temp = (left << 16) /* S2 S4 XX XX */
|
||||
| (right >> 16); /* XX XX S6 S8 */
|
||||
ks[0] = temp;
|
||||
|
||||
temp = (left & 0xffff0000) /* S1 S3 XX XX */
|
||||
| (right & 0x0000ffff);/* XX XX S5 S7 */
|
||||
ks[1] = temp;
|
||||
|
||||
ks = (HALF*)((BYTE *)ks + delta);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The DES Initial Permutation
|
||||
* if we number the bits of the 8 bytes of input like this (in octal):
|
||||
* 00 01 02 03 04 05 06 07
|
||||
* 10 11 12 13 14 15 16 17
|
||||
* 20 21 22 23 24 25 26 27
|
||||
* 30 31 32 33 34 35 36 37
|
||||
* 40 41 42 43 44 45 46 47
|
||||
* 50 51 52 53 54 55 56 57
|
||||
* 60 61 62 63 64 65 66 67
|
||||
* 70 71 72 73 74 75 76 77
|
||||
* then after the initial permutation, they will be in this order.
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 77 67 57 47 37 27 17 07
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* 76 66 56 46 36 26 16 06
|
||||
*
|
||||
* One way to do this is in two steps:
|
||||
* 1. Flip this matrix about the diagonal from 70-07 as done for PC1.
|
||||
* 2. Rearrange the bytes (rows in the matrix above) with the following code.
|
||||
*
|
||||
* #define swapHiLo(word, temp) \
|
||||
* temp = (word ^ (word >> 24)) & 0x000000ff; \
|
||||
* word ^= temp | (temp << 24);
|
||||
*
|
||||
* right ^= temp = ((left << 8) ^ right) & 0xff00ff00;
|
||||
* left ^= temp >> 8;
|
||||
* swapHiLo(left, temp);
|
||||
* swapHiLo(right,temp);
|
||||
*
|
||||
* However, the two steps can be combined, so that the rows are rearranged
|
||||
* while the matrix is being flipped, reducing the number of bit exchange
|
||||
* operations from 8 ot 5.
|
||||
*
|
||||
* Initial Permutation */
|
||||
#define IP(left, right, temp) \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4; \
|
||||
right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
|
||||
left ^= temp << 16; \
|
||||
right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
|
||||
left ^= temp >> 2; \
|
||||
right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
|
||||
left ^= temp >> 8; \
|
||||
right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
|
||||
left ^= temp << 1;
|
||||
|
||||
/* The Final (Inverse Initial) permutation is done by reversing the
|
||||
** steps of the Initital Permutation
|
||||
*/
|
||||
|
||||
#define FP(left, right, temp) \
|
||||
right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
|
||||
left ^= temp << 1; \
|
||||
right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
|
||||
left ^= temp >> 8; \
|
||||
right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
|
||||
left ^= temp >> 2; \
|
||||
right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
|
||||
left ^= temp << 16; \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4;
|
||||
|
||||
void
|
||||
DES_Do1Block(HALF * ks, const BYTE * inbuf, BYTE * outbuf)
|
||||
{
|
||||
register HALF left, right;
|
||||
register HALF temp;
|
||||
|
||||
#if defined(_X86_)
|
||||
left = HALFPTR(inbuf)[0];
|
||||
right = HALFPTR(inbuf)[1];
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#else
|
||||
if (((ptrdiff_t)inbuf & 0x03) == 0) {
|
||||
left = HALFPTR(inbuf)[0];
|
||||
right = HALFPTR(inbuf)[1];
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
} else {
|
||||
left = ((HALF)inbuf[0] << 24) | ((HALF)inbuf[1] << 16) |
|
||||
((HALF)inbuf[2] << 8) | inbuf[3];
|
||||
right = ((HALF)inbuf[4] << 24) | ((HALF)inbuf[5] << 16) |
|
||||
((HALF)inbuf[6] << 8) | inbuf[7];
|
||||
}
|
||||
#endif
|
||||
|
||||
IP(left, right, temp);
|
||||
|
||||
/* shift the values left circularly 3 bits. */
|
||||
left = (left << 3) | (left >> 29);
|
||||
right = (right << 3) | (right >> 29);
|
||||
|
||||
#ifdef USE_INDEXING
|
||||
#define KSLOOKUP(s,b) SP[s][((temp >> (b+2)) & 0x3f)]
|
||||
#else
|
||||
#define KSLOOKUP(s,b) *(HALF*)((BYTE*)&SP[s][0]+((temp >> b) & 0xFC))
|
||||
#endif
|
||||
#define ROUND(out, in, r) \
|
||||
temp = in ^ ks[2*r]; \
|
||||
out ^= KSLOOKUP( 1, 24 ); \
|
||||
out ^= KSLOOKUP( 3, 16 ); \
|
||||
out ^= KSLOOKUP( 5, 8 ); \
|
||||
out ^= KSLOOKUP( 7, 0 ); \
|
||||
temp = ((in >> 4) | (in << 28)) ^ ks[2*r+1]; \
|
||||
out ^= KSLOOKUP( 0, 24 ); \
|
||||
out ^= KSLOOKUP( 2, 16 ); \
|
||||
out ^= KSLOOKUP( 4, 8 ); \
|
||||
out ^= KSLOOKUP( 6, 0 );
|
||||
|
||||
/* Do the 16 Feistel rounds */
|
||||
ROUND(left, right, 0)
|
||||
ROUND(right, left, 1)
|
||||
ROUND(left, right, 2)
|
||||
ROUND(right, left, 3)
|
||||
ROUND(left, right, 4)
|
||||
ROUND(right, left, 5)
|
||||
ROUND(left, right, 6)
|
||||
ROUND(right, left, 7)
|
||||
ROUND(left, right, 8)
|
||||
ROUND(right, left, 9)
|
||||
ROUND(left, right, 10)
|
||||
ROUND(right, left, 11)
|
||||
ROUND(left, right, 12)
|
||||
ROUND(right, left, 13)
|
||||
ROUND(left, right, 14)
|
||||
ROUND(right, left, 15)
|
||||
|
||||
/* now shift circularly right 3 bits to undo the shifting done
|
||||
** above. switch left and right here.
|
||||
*/
|
||||
temp = (left >> 3) | (left << 29);
|
||||
left = (right >> 3) | (right << 29);
|
||||
right = temp;
|
||||
|
||||
FP(left, right, temp);
|
||||
|
||||
#if defined(_X86_)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
HALFPTR(outbuf)[0] = left;
|
||||
HALFPTR(outbuf)[1] = right;
|
||||
#else
|
||||
if (((ptrdiff_t)inbuf & 0x03) == 0) {
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
HALFPTR(outbuf)[0] = left;
|
||||
HALFPTR(outbuf)[1] = right;
|
||||
} else {
|
||||
outbuf[0] = (BYTE)(left >> 24);
|
||||
outbuf[1] = (BYTE)(left >> 16);
|
||||
outbuf[2] = (BYTE)(left >> 8);
|
||||
outbuf[3] = (BYTE)(left );
|
||||
|
||||
outbuf[4] = (BYTE)(right >> 24);
|
||||
outbuf[5] = (BYTE)(right >> 16);
|
||||
outbuf[6] = (BYTE)(right >> 8);
|
||||
outbuf[7] = (BYTE)(right );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Ackowledgements:
|
||||
** Two ideas used in this implementation were shown to me by Dennis Ferguson
|
||||
** in 1990. He credits them to Richard Outerbridge and Dan Hoey. They were:
|
||||
** 1. The method of computing the Initial and Final permutations.
|
||||
** 2. Circularly rotating the SP tables and the initial values of left and
|
||||
** right to reduce the number of shifts required during the 16 rounds.
|
||||
*/
|
||||
69
mozilla/security/nss/lib/freebl/des.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* des.h
|
||||
*
|
||||
* header file for DES-150 library
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Nelson B. Bolyard,
|
||||
* nelsonb@iname.com. Portions created by Nelson B. Bolyard are
|
||||
* Copyright (C) 1990, 2000 Nelson B. Bolyard, All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
#ifndef _DES_H_
|
||||
#define _DES_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned int HALF;
|
||||
|
||||
#define HALFPTR(x) ((HALF *)(x))
|
||||
#define SHORTPTR(x) ((unsigned short *)(x))
|
||||
#define BYTEPTR(x) ((BYTE *)(x))
|
||||
|
||||
typedef enum {
|
||||
DES_ENCRYPT = 0x5555,
|
||||
DES_DECRYPT = 0xAAAA
|
||||
} DESDirection;
|
||||
|
||||
typedef void DESFunc(struct DESContextStr *cx, BYTE *out, const BYTE *in,
|
||||
unsigned int len);
|
||||
|
||||
struct DESContextStr {
|
||||
/* key schedule, 16 internal keys, each with 8 6-bit parts */
|
||||
HALF ks0 [32];
|
||||
HALF ks1 [32];
|
||||
HALF ks2 [32];
|
||||
HALF iv [2];
|
||||
DESDirection direction;
|
||||
DESFunc *worker;
|
||||
};
|
||||
|
||||
void DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction);
|
||||
void DES_Do1Block( HALF * ks, const BYTE * inbuf, BYTE * outbuf);
|
||||
|
||||
#endif
|
||||
275
mozilla/security/nss/lib/freebl/desblapi.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* desblapi.c
|
||||
*
|
||||
* core source file for DES-150 library
|
||||
* Implement DES Modes of Operation and Triple-DES.
|
||||
* Adapt DES-150 to blapi API.
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Nelson B. Bolyard,
|
||||
* nelsonb@iname.com. Portions created by Nelson B. Bolyard are
|
||||
* Copyright (C) 1990, 2000 Nelson B. Bolyard, All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
#include "des.h"
|
||||
#include <stddef.h>
|
||||
#include "secerr.h"
|
||||
|
||||
#if defined(_X86_)
|
||||
/* Intel X86 CPUs do unaligned loads and stores without complaint. */
|
||||
#define COPY8B(to, from, ptr) \
|
||||
HALFPTR(to)[0] = HALFPTR(from)[0]; \
|
||||
HALFPTR(to)[1] = HALFPTR(from)[1];
|
||||
#elif defined(USE_MEMCPY)
|
||||
#define COPY8B(to, from, ptr) memcpy(to, from, 8)
|
||||
#else
|
||||
#define COPY8B(to, from, ptr) \
|
||||
if (((ptrdiff_t)(ptr) & 0x3) == 0) { \
|
||||
HALFPTR(to)[0] = HALFPTR(from)[0]; \
|
||||
HALFPTR(to)[1] = HALFPTR(from)[1]; \
|
||||
} else if (((ptrdiff_t)(ptr) & 0x1) == 0) { \
|
||||
SHORTPTR(to)[0] = SHORTPTR(from)[0]; \
|
||||
SHORTPTR(to)[1] = SHORTPTR(from)[1]; \
|
||||
SHORTPTR(to)[2] = SHORTPTR(from)[2]; \
|
||||
SHORTPTR(to)[3] = SHORTPTR(from)[3]; \
|
||||
} else { \
|
||||
BYTEPTR(to)[0] = BYTEPTR(from)[0]; \
|
||||
BYTEPTR(to)[1] = BYTEPTR(from)[1]; \
|
||||
BYTEPTR(to)[2] = BYTEPTR(from)[2]; \
|
||||
BYTEPTR(to)[3] = BYTEPTR(from)[3]; \
|
||||
BYTEPTR(to)[4] = BYTEPTR(from)[4]; \
|
||||
BYTEPTR(to)[5] = BYTEPTR(from)[5]; \
|
||||
BYTEPTR(to)[6] = BYTEPTR(from)[6]; \
|
||||
BYTEPTR(to)[7] = BYTEPTR(from)[7]; \
|
||||
}
|
||||
#endif
|
||||
#define COPY8BTOHALF(to, from) COPY8B(to, from, from)
|
||||
#define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
|
||||
|
||||
static void
|
||||
DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
DES_Do1Block(cx->ks0, in, out);
|
||||
len -= 8;
|
||||
in += 8;
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
DES_Do1Block(cx->ks0, in, out);
|
||||
len -= 8;
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks1, out, out);
|
||||
DES_Do1Block(cx->ks2, out, out);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend = in + len;
|
||||
HALF vec[2];
|
||||
|
||||
while (in != bufend) {
|
||||
COPY8BTOHALF(vec, in);
|
||||
in += 8;
|
||||
vec[0] ^= cx->iv[0];
|
||||
vec[1] ^= cx->iv[1];
|
||||
DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
|
||||
COPY8BFROMHALF(out, cx->iv);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend;
|
||||
HALF oldciphertext[2];
|
||||
HALF plaintext [2];
|
||||
|
||||
for (bufend = in + len; in != bufend; ) {
|
||||
oldciphertext[0] = cx->iv[0];
|
||||
oldciphertext[1] = cx->iv[1];
|
||||
COPY8BTOHALF(cx->iv, in);
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
|
||||
plaintext[0] ^= oldciphertext[0];
|
||||
plaintext[1] ^= oldciphertext[1];
|
||||
COPY8BFROMHALF(out, plaintext);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend = in + len;
|
||||
HALF vec[2];
|
||||
|
||||
while (in != bufend) {
|
||||
COPY8BTOHALF(vec, in);
|
||||
in += 8;
|
||||
vec[0] ^= cx->iv[0];
|
||||
vec[1] ^= cx->iv[1];
|
||||
DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
|
||||
DES_Do1Block( cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
|
||||
DES_Do1Block( cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
|
||||
COPY8BFROMHALF(out, cx->iv);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend;
|
||||
HALF oldciphertext[2];
|
||||
HALF plaintext [2];
|
||||
|
||||
for (bufend = in + len; in != bufend; ) {
|
||||
oldciphertext[0] = cx->iv[0];
|
||||
oldciphertext[1] = cx->iv[1];
|
||||
COPY8BTOHALF(cx->iv, in);
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
|
||||
DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
|
||||
DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
|
||||
plaintext[0] ^= oldciphertext[0];
|
||||
plaintext[1] ^= oldciphertext[1];
|
||||
COPY8BFROMHALF(out, plaintext);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
DESContext *
|
||||
DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt)
|
||||
{
|
||||
DESContext *cx = PORT_ZNew(DESContext);
|
||||
DESDirection opposite;
|
||||
if (!cx)
|
||||
return 0;
|
||||
cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
|
||||
opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
|
||||
switch (mode) {
|
||||
case NSS_DES: /* DES ECB */
|
||||
DES_MakeSchedule( cx->ks0, key, cx->direction);
|
||||
cx->worker = &DES_ECB;
|
||||
break;
|
||||
|
||||
case NSS_DES_EDE3: /* DES EDE ECB */
|
||||
cx->worker = &DES_EDE3_ECB;
|
||||
if (encrypt) {
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
|
||||
} else {
|
||||
DES_MakeSchedule(cx->ks2, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
|
||||
}
|
||||
break;
|
||||
|
||||
case NSS_DES_CBC: /* DES CBC */
|
||||
COPY8BTOHALF(cx->iv, iv);
|
||||
cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
break;
|
||||
|
||||
case NSS_DES_EDE3_CBC: /* DES EDE CBC */
|
||||
COPY8BTOHALF(cx->iv, iv);
|
||||
if (encrypt) {
|
||||
cx->worker = &DES_EDE3CBCEn;
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
|
||||
} else {
|
||||
cx->worker = &DES_EDE3CBCDe;
|
||||
DES_MakeSchedule(cx->ks2, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_Free(cx);
|
||||
cx = 0;
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
break;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
DES_DestroyContext(DESContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
|
||||
unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
|
||||
{
|
||||
|
||||
if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
|
||||
cx->direction != DES_ENCRYPT) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->worker(cx, out, in, inLen);
|
||||
if (outLen)
|
||||
*outLen = inLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
|
||||
unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
|
||||
{
|
||||
|
||||
if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
|
||||
cx->direction != DES_DECRYPT) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->worker(cx, out, in, inLen);
|
||||
if (outLen)
|
||||
*outLen = inLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
385
mozilla/security/nss/lib/freebl/dh.c
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Diffie-Hellman parameter generation, key generation, and secret derivation.
|
||||
* KEA secret generation and verification.
|
||||
*
|
||||
* $Id: dh.c,v 1.6 2001-09-20 22:14:06 relyea%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secitem.h"
|
||||
#include "mpi.h"
|
||||
#include "mpprime.h"
|
||||
#include "secmpi.h"
|
||||
|
||||
#define DH_SECRET_KEY_LEN 20
|
||||
#define KEA_DERIVED_SECRET_LEN 128
|
||||
|
||||
SECStatus
|
||||
DH_GenParam(int primeLen, DHParams **params)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
DHParams *dhparams;
|
||||
unsigned char *pb = NULL;
|
||||
unsigned char *ab = NULL;
|
||||
unsigned long counter = 0;
|
||||
mp_int p, q, a, h, psub1, test;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
if (!params || primeLen < 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams));
|
||||
if (!dhparams) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
dhparams->arena = arena;
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&a) = 0;
|
||||
MP_DIGITS(&h) = 0;
|
||||
MP_DIGITS(&psub1) = 0;
|
||||
MP_DIGITS(&test) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&a) );
|
||||
CHECK_MPI_OK( mp_init(&h) );
|
||||
CHECK_MPI_OK( mp_init(&psub1) );
|
||||
CHECK_MPI_OK( mp_init(&test) );
|
||||
/* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
|
||||
pb = PORT_Alloc(primeLen);
|
||||
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) );
|
||||
pb[0] |= 0x80; /* set high-order bit */
|
||||
pb[primeLen-1] |= 0x01; /* set low-order bit */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) );
|
||||
CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter) );
|
||||
/* construct Sophie-Germain prime q = (p-1)/2. */
|
||||
CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
|
||||
CHECK_MPI_OK( mp_div_2(&psub1, &q) );
|
||||
/* construct a generator from the prime. */
|
||||
ab = PORT_Alloc(primeLen);
|
||||
/* generate a candidate number a in p's field */
|
||||
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(ab, primeLen) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&a, ab, primeLen) );
|
||||
/* force a < p (note that quot(a/p) <= 1) */
|
||||
if ( mp_cmp(&a, &p) > 0 )
|
||||
CHECK_MPI_OK( mp_sub(&a, &p, &a) );
|
||||
do {
|
||||
/* check that a is in the range [2..p-1] */
|
||||
if ( mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) {
|
||||
/* a is outside of the allowed range. Set a=3 and keep going. */
|
||||
mp_set(&a, 3);
|
||||
}
|
||||
/* if a**q mod p != 1 then a is a generator */
|
||||
CHECK_MPI_OK( mp_exptmod(&a, &q, &p, &test) );
|
||||
if ( mp_cmp_d(&test, 1) != 0 )
|
||||
break;
|
||||
/* increment the candidate and try again. */
|
||||
CHECK_MPI_OK( mp_add_d(&a, 1, &a) );
|
||||
} while (PR_TRUE);
|
||||
MPINT_TO_SECITEM(&p, &dhparams->prime, arena);
|
||||
MPINT_TO_SECITEM(&a, &dhparams->base, arena);
|
||||
*params = dhparams;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&a);
|
||||
mp_clear(&h);
|
||||
mp_clear(&psub1);
|
||||
mp_clear(&test);
|
||||
if (pb) PORT_ZFree(pb, primeLen);
|
||||
if (ab) PORT_ZFree(ab, primeLen);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_NewKey(DHParams *params, DHPrivateKey **privKey)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
DHPrivateKey *key;
|
||||
mp_int g, xa, p, Ya;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
if (!params || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey));
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
key->arena = arena;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&xa) = 0;
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Ya) = 0;
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&xa) );
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Ya) );
|
||||
/* Set private key's p */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, ¶ms->prime) );
|
||||
SECITEM_TO_MPINT(key->prime, &p);
|
||||
/* Set private key's g */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, ¶ms->base) );
|
||||
SECITEM_TO_MPINT(key->base, &g);
|
||||
/* Generate private key xa */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DH_SECRET_KEY_LEN);
|
||||
RNG_GenerateGlobalRandomBytes(key->privateValue.data,
|
||||
key->privateValue.len);
|
||||
SECITEM_TO_MPINT( key->privateValue, &xa );
|
||||
/* xa < p */
|
||||
CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
|
||||
/* Compute public key Ya = g ** xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) );
|
||||
MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena);
|
||||
*privKey = key;
|
||||
cleanup:
|
||||
mp_clear(&g);
|
||||
mp_clear(&xa);
|
||||
mp_clear(&p);
|
||||
mp_clear(&Ya);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_Derive(SECItem *publicValue,
|
||||
SECItem *prime,
|
||||
SECItem *privateValue,
|
||||
SECItem *derivedSecret,
|
||||
unsigned int maxOutBytes)
|
||||
{
|
||||
mp_int p, Xa, Yb, ZZ;
|
||||
mp_err err = MP_OKAY;
|
||||
unsigned int len = 0, nb;
|
||||
unsigned char *secret = NULL;
|
||||
if (!publicValue || !prime || !privateValue || !derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Xa) = 0;
|
||||
MP_DIGITS(&Yb) = 0;
|
||||
MP_DIGITS(&ZZ) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Xa) );
|
||||
CHECK_MPI_OK( mp_init(&Yb) );
|
||||
CHECK_MPI_OK( mp_init(&ZZ) );
|
||||
SECITEM_TO_MPINT(*publicValue, &Yb);
|
||||
SECITEM_TO_MPINT(*privateValue, &Xa);
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
/* ZZ = (Yb)**Xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&Yb, &Xa, &p, &ZZ) );
|
||||
/* number of bytes in the derived secret */
|
||||
len = mp_unsigned_octet_size(&ZZ);
|
||||
/* allocate a buffer which can hold the entire derived secret. */
|
||||
secret = PORT_Alloc(len);
|
||||
/* grab the derived secret */
|
||||
err = mp_to_unsigned_octets(&ZZ, secret, len);
|
||||
if (err >= 0) err = MP_OKAY;
|
||||
/* Take minimum of bytes requested and bytes in derived secret,
|
||||
** if maxOutBytes is 0 take all of the bytes from the derived secret.
|
||||
*/
|
||||
if (maxOutBytes > 0)
|
||||
nb = PR_MIN(len, maxOutBytes);
|
||||
else
|
||||
nb = len;
|
||||
SECITEM_AllocItem(NULL, derivedSecret, nb);
|
||||
memcpy(derivedSecret->data, secret, nb);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&Xa);
|
||||
mp_clear(&Yb);
|
||||
mp_clear(&ZZ);
|
||||
if (secret) {
|
||||
/* free the buffer allocated for the full secret. */
|
||||
PORT_ZFree(secret, len);
|
||||
}
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
if (derivedSecret->data)
|
||||
PORT_ZFree(derivedSecret->data, derivedSecret->len);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
KEA_Derive(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret)
|
||||
{
|
||||
mp_int p, Y, R, r, x, t, u, w;
|
||||
mp_err err;
|
||||
unsigned char *secret = NULL;
|
||||
unsigned int len = 0, offset;
|
||||
if (!prime || !public1 || !public2 || !private1 || !private2 ||
|
||||
!derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Y) = 0;
|
||||
MP_DIGITS(&R) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&t) = 0;
|
||||
MP_DIGITS(&u) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Y) );
|
||||
CHECK_MPI_OK( mp_init(&R) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&t) );
|
||||
CHECK_MPI_OK( mp_init(&u) );
|
||||
CHECK_MPI_OK( mp_init(&w) );
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*public1, &Y);
|
||||
SECITEM_TO_MPINT(*public2, &R);
|
||||
SECITEM_TO_MPINT(*private1, &r);
|
||||
SECITEM_TO_MPINT(*private2, &x);
|
||||
/* t = DH(Y, r, p) = Y ** r mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&Y, &r, &p, &t) );
|
||||
/* u = DH(R, x, p) = R ** x mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&R, &x, &p, &u) );
|
||||
/* w = (t + u) mod p */
|
||||
CHECK_MPI_OK( mp_addmod(&t, &u, &p, &w) );
|
||||
/* allocate a buffer for the full derived secret */
|
||||
len = mp_unsigned_octet_size(&w);
|
||||
secret = PORT_Alloc(len);
|
||||
/* grab the secret */
|
||||
err = mp_to_unsigned_octets(&w, secret, len);
|
||||
if (err > 0) err = MP_OKAY;
|
||||
/* allocate output buffer */
|
||||
SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN);
|
||||
memset(derivedSecret->data, 0, derivedSecret->len);
|
||||
/* copy in the 128 lsb of the secret */
|
||||
if (len >= KEA_DERIVED_SECRET_LEN) {
|
||||
memcpy(derivedSecret->data, secret + (len - KEA_DERIVED_SECRET_LEN),
|
||||
KEA_DERIVED_SECRET_LEN);
|
||||
} else {
|
||||
offset = KEA_DERIVED_SECRET_LEN - len;
|
||||
memcpy(derivedSecret->data + offset, secret, len);
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&Y);
|
||||
mp_clear(&R);
|
||||
mp_clear(&r);
|
||||
mp_clear(&x);
|
||||
mp_clear(&t);
|
||||
mp_clear(&u);
|
||||
mp_clear(&w);
|
||||
if (secret)
|
||||
PORT_ZFree(secret, len);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PRBool
|
||||
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
|
||||
{
|
||||
mp_int p, q, y, r;
|
||||
mp_err err;
|
||||
int cmp = 1; /* default is false */
|
||||
if (!Y || !prime || !subPrime) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*subPrime, &q);
|
||||
SECITEM_TO_MPINT(*Y, &y);
|
||||
/* compute r = y**q mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&y, &q, &p, &r) );
|
||||
/* compare to 1 */
|
||||
cmp = mp_cmp_d(&r, 1);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return PR_FALSE;
|
||||
}
|
||||
return (cmp == 0) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
82
mozilla/security/nss/lib/freebl/dh_bsf.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
SECStatus
|
||||
DH_GenParam(int primeLen, DHParams ** params)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_NewKey(DHParams * params,
|
||||
DHPrivateKey ** privKey)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_Derive(SECItem * publicValue,
|
||||
SECItem * prime,
|
||||
SECItem * privateValue,
|
||||
SECItem * derivedSecret,
|
||||
unsigned int maxOutBytes)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
KEA_Derive(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
PRBool
|
||||
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return PR_FALSE;
|
||||
}
|
||||
420
mozilla/security/nss/lib/freebl/dsa.c
Normal file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: dsa.c,v 1.11 2003-02-25 23:45:23 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prinit.h"
|
||||
#include "blapi.h"
|
||||
#include "nssilock.h"
|
||||
#include "secitem.h"
|
||||
#include "blapi.h"
|
||||
#include "mpi.h"
|
||||
|
||||
/* XXX to be replaced by define in blapit.h */
|
||||
#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
#define CHECKOK(func) if (MP_OKAY > (err = func)) goto cleanup
|
||||
|
||||
#define SECITEM_TO_MPINT(it, mp) \
|
||||
CHECKOK(mp_read_unsigned_octets((mp), (it).data, (it).len))
|
||||
|
||||
/* DSA-specific random number functions defined in prng_fips1861.c. */
|
||||
extern SECStatus
|
||||
DSA_RandomUpdate(void *data, size_t bytes, unsigned char *q);
|
||||
|
||||
extern SECStatus
|
||||
DSA_GenerateGlobalRandomBytes(void *dest, size_t len, unsigned char *q);
|
||||
|
||||
static void translate_mpi_error(mp_err err)
|
||||
{
|
||||
switch (err) {
|
||||
case MP_MEM: PORT_SetError(SEC_ERROR_NO_MEMORY); break;
|
||||
case MP_RANGE: PORT_SetError(SEC_ERROR_BAD_DATA); break;
|
||||
case MP_BADARG: PORT_SetError(SEC_ERROR_INVALID_ARGS); break;
|
||||
default: PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); break;
|
||||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey,
|
||||
const unsigned char *xb)
|
||||
{
|
||||
unsigned int y_len;
|
||||
mp_int p, g;
|
||||
mp_int x, y;
|
||||
mp_err err;
|
||||
PRArenaPool *arena;
|
||||
DSAPrivateKey *key;
|
||||
/* Check args. */
|
||||
if (!params || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize an arena for the DSA key. */
|
||||
arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
key->params.arena = arena;
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
CHECKOK( mp_init(&p) );
|
||||
CHECKOK( mp_init(&g) );
|
||||
CHECKOK( mp_init(&x) );
|
||||
CHECKOK( mp_init(&y) );
|
||||
/* Copy over the PQG params */
|
||||
CHECKOK( SECITEM_CopyItem(arena, &key->params.prime, ¶ms->prime) );
|
||||
CHECKOK( SECITEM_CopyItem(arena, &key->params.subPrime, ¶ms->subPrime));
|
||||
CHECKOK( SECITEM_CopyItem(arena, &key->params.base, ¶ms->base) );
|
||||
/* Convert stored p, g, and received x into MPI integers. */
|
||||
SECITEM_TO_MPINT(params->prime, &p);
|
||||
SECITEM_TO_MPINT(params->base, &g);
|
||||
CHECKOK( mp_read_unsigned_octets(&x, xb, DSA_SUBPRIME_LEN) );
|
||||
/* Store x in private key */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DSA_SUBPRIME_LEN);
|
||||
memcpy(key->privateValue.data, xb, DSA_SUBPRIME_LEN);
|
||||
/* Compute public key y = g**x mod p */
|
||||
CHECKOK( mp_exptmod(&g, &x, &p, &y) );
|
||||
/* Store y in public key */
|
||||
y_len = mp_unsigned_octet_size(&y);
|
||||
SECITEM_AllocItem(arena, &key->publicValue, y_len);
|
||||
err = mp_to_unsigned_octets(&y, key->publicValue.data, y_len);
|
||||
/* mp_to_unsigned_octets returns bytes written (y_len) if okay */
|
||||
if (err < 0) goto cleanup; else err = MP_OKAY;
|
||||
*privKey = key;
|
||||
key = NULL;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&y);
|
||||
if (key)
|
||||
PORT_FreeArena(key->params.arena, PR_TRUE);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate and return a new DSA public and private key pair,
|
||||
** both of which are encoded into a single DSAPrivateKey struct.
|
||||
** "params" is a pointer to the PQG parameters for the domain
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
unsigned char seed[DSA_SUBPRIME_LEN];
|
||||
/* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
|
||||
if (DSA_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN,
|
||||
params->subPrime.data))
|
||||
return SECFailure;
|
||||
/* Generate a new DSA key using random seed. */
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes long */
|
||||
SECStatus
|
||||
DSA_NewKeyFromSeed(const PQGParams *params,
|
||||
const unsigned char *seed,
|
||||
DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
|
||||
const unsigned char *kb)
|
||||
{
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int x, k; /* private key & pseudo-random integer */
|
||||
mp_int r, s; /* tuple (r, s) is signature) */
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len != DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&s) = 0;
|
||||
CHECKOK( mp_init(&p) );
|
||||
CHECKOK( mp_init(&q) );
|
||||
CHECKOK( mp_init(&g) );
|
||||
CHECKOK( mp_init(&x) );
|
||||
CHECKOK( mp_init(&k) );
|
||||
CHECKOK( mp_init(&r) );
|
||||
CHECKOK( mp_init(&s) );
|
||||
/*
|
||||
** Convert stored PQG and private key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->privateValue, &x);
|
||||
CHECKOK( mp_read_unsigned_octets(&k, kb, DSA_SUBPRIME_LEN) );
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 1
|
||||
**
|
||||
** r = (g**k mod p) mod q
|
||||
*/
|
||||
CHECKOK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
|
||||
CHECKOK( mp_mod(&r, &q, &r) ); /* r = r mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 2
|
||||
**
|
||||
** s = (k**-1 * (SHA1(M) + x*r)) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
|
||||
CHECKOK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
|
||||
CHECKOK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
|
||||
CHECKOK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
|
||||
CHECKOK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */
|
||||
/*
|
||||
** verify r != 0 and s != 0
|
||||
** mentioned as optional in FIPS 186-1.
|
||||
*/
|
||||
if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
rv = SECFailure;
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
** Step 4
|
||||
**
|
||||
** Signature is tuple (r, s)
|
||||
*/
|
||||
err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,
|
||||
DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = MP_OKAY;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&k);
|
||||
mp_clear(&r);
|
||||
mp_clear(&s);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 20 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
** On output, signature->len == size of signature in buffer.
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
|
||||
{
|
||||
SECStatus rv;
|
||||
int retries = 10;
|
||||
unsigned char kSeed[DSA_SUBPRIME_LEN];
|
||||
|
||||
PORT_SetError(0);
|
||||
do {
|
||||
rv = DSA_GenerateGlobalRandomBytes(kSeed, DSA_SUBPRIME_LEN,
|
||||
key->params.subPrime.data);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
rv = dsa_SignDigest(key, signature, digest, kSeed);
|
||||
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
|
||||
--retries > 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes. */
|
||||
SECStatus
|
||||
DSA_SignDigestWithSeed(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_SignDigest(key, signature, digest, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 20 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
|
||||
const SECItem *digest)
|
||||
{
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int r_, s_; /* tuple (r', s') is received signature) */
|
||||
mp_int u1, u2, v, w; /* intermediate values used in verification */
|
||||
mp_int y; /* public key */
|
||||
mp_err err;
|
||||
SECStatus verified = SECFailure;
|
||||
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len != DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r_) = 0;
|
||||
MP_DIGITS(&s_) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&v) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECKOK( mp_init(&p) );
|
||||
CHECKOK( mp_init(&q) );
|
||||
CHECKOK( mp_init(&g) );
|
||||
CHECKOK( mp_init(&y) );
|
||||
CHECKOK( mp_init(&r_) );
|
||||
CHECKOK( mp_init(&s_) );
|
||||
CHECKOK( mp_init(&u1) );
|
||||
CHECKOK( mp_init(&u2) );
|
||||
CHECKOK( mp_init(&v) );
|
||||
CHECKOK( mp_init(&w) );
|
||||
/*
|
||||
** Convert stored PQG and public key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->publicValue, &y);
|
||||
/*
|
||||
** Convert received signature (r', s') into MPI integers.
|
||||
*/
|
||||
CHECKOK( mp_read_unsigned_octets(&r_, signature->data, DSA_SUBPRIME_LEN) );
|
||||
CHECKOK( mp_read_unsigned_octets(&s_, signature->data + DSA_SUBPRIME_LEN,
|
||||
DSA_SUBPRIME_LEN) );
|
||||
/*
|
||||
** Verify that 0 < r' < q and 0 < s' < q
|
||||
*/
|
||||
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
|
||||
mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0)
|
||||
goto cleanup; /* will return verified == SECFailure */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 1
|
||||
**
|
||||
** w = (s')**-1 mod q
|
||||
*/
|
||||
CHECKOK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 2
|
||||
**
|
||||
** u1 = ((SHA1(M')) * w) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
|
||||
CHECKOK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 3
|
||||
**
|
||||
** u2 = ((r') * w) mod q
|
||||
*/
|
||||
CHECKOK( mp_mulmod(&r_, &w, &q, &u2) );
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 4
|
||||
**
|
||||
** v = ((g**u1 * y**u2) mod p) mod q
|
||||
*/
|
||||
CHECKOK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
|
||||
CHECKOK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
|
||||
CHECKOK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */
|
||||
CHECKOK( mp_mod(&v, &q, &v) ); /* v = v mod q */
|
||||
/*
|
||||
** Verification: v == r'
|
||||
*/
|
||||
if (mp_cmp(&v, &r_)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
verified = SECFailure; /* Signature failed to verify. */
|
||||
} else {
|
||||
verified = SECSuccess; /* Signature verified. */
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r_);
|
||||
mp_clear(&s_);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&v);
|
||||
mp_clear(&w);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
}
|
||||
return verified;
|
||||
}
|
||||
977
mozilla/security/nss/lib/freebl/ec.c
Normal file
@@ -0,0 +1,977 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Elliptic Curve Cryptography library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "blapi.h"
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
#include "secmpi.h"
|
||||
#include "secitem.h"
|
||||
#include "ec.h"
|
||||
#include "GFp_ecl.h"
|
||||
#include "GF2m_ecl.h"
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
/*
|
||||
* Returns true if pointP is the point at infinity, false otherwise
|
||||
*/
|
||||
PRBool
|
||||
ec_point_at_infinity(SECItem *pointP)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < pointP->len; i++) {
|
||||
if (pointP->data[i] != 0x00) return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes point addition R = P + Q for the curve whose
|
||||
* parameters are encoded in params. Two or more of P, Q,
|
||||
* R may point to the same memory location.
|
||||
*/
|
||||
SECStatus
|
||||
ec_point_add(ECParams *params, SECItem *pointP,
|
||||
SECItem *pointQ, SECItem *pointR)
|
||||
{
|
||||
mp_int Px, Py, Qx, Qy, Rx, Ry;
|
||||
mp_int irreducible, a;
|
||||
SECStatus rv = SECFailure;
|
||||
mp_err err = MP_OKAY;
|
||||
int len;
|
||||
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
|
||||
printf("ec_point_add: params [len=%d]:", params->DEREncoding.len);
|
||||
for (i = 0; i < params->DEREncoding.len; i++)
|
||||
printf("%02x:", params->DEREncoding.data[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("ec_point_add: pointP [len=%d]:", pointP->len);
|
||||
for (i = 0; i < pointP->len; i++)
|
||||
printf("%02x:", pointP->data[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("ec_point_add: pointQ [len=%d]:", pointQ->len);
|
||||
for (i = 0; i < pointQ->len; i++)
|
||||
printf("%02x:", pointQ->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/* NOTE: We only support prime field curves for now */
|
||||
len = (params->fieldID.size + 7) >> 3;
|
||||
if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
|
||||
(pointP->len != (2 * len + 1)) ||
|
||||
(pointQ->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
|
||||
(pointQ->len != (2 * len + 1))) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
MP_DIGITS(&Px) = 0;
|
||||
MP_DIGITS(&Py) = 0;
|
||||
MP_DIGITS(&Qx) = 0;
|
||||
MP_DIGITS(&Qy) = 0;
|
||||
MP_DIGITS(&Rx) = 0;
|
||||
MP_DIGITS(&Ry) = 0;
|
||||
MP_DIGITS(&irreducible) = 0;
|
||||
MP_DIGITS(&a) = 0;
|
||||
CHECK_MPI_OK( mp_init(&Px) );
|
||||
CHECK_MPI_OK( mp_init(&Py) );
|
||||
CHECK_MPI_OK( mp_init(&Qx) );
|
||||
CHECK_MPI_OK( mp_init(&Qy) );
|
||||
CHECK_MPI_OK( mp_init(&Rx) );
|
||||
CHECK_MPI_OK( mp_init(&Ry) );
|
||||
CHECK_MPI_OK( mp_init(&irreducible) );
|
||||
CHECK_MPI_OK( mp_init(&a) );
|
||||
|
||||
/* Initialize Px and Py */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
|
||||
/* Initialize Qx and Qy */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Qx, pointQ->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Qy, pointQ->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
|
||||
/* Set up the curve coefficient */
|
||||
SECITEM_TO_MPINT( params->curve.a, &a );
|
||||
|
||||
/* Compute R = P + Q */
|
||||
if (params->fieldID.type == ec_field_GFp) {
|
||||
SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
|
||||
if (GFp_ec_pt_add(&irreducible, &a, &Px, &Py, &Qx, &Qy,
|
||||
&Rx, &Ry) != SECSuccess)
|
||||
goto cleanup;
|
||||
} else {
|
||||
SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
|
||||
if (GF2m_ec_pt_add(&irreducible, &a, &Px, &Py, &Qx, &Qy, &Rx, &Ry)
|
||||
!= SECSuccess)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Construct the SECItem representation of the result */
|
||||
pointR->data[0] = EC_POINT_FORM_UNCOMPRESSED;
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Rx, pointR->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Ry, pointR->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
rv = SECSuccess;
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ec_point_add: pointR [len=%d]:", pointR->len);
|
||||
for (i = 0; i < pointR->len; i++)
|
||||
printf("%02x:", pointR->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mp_clear(&Px);
|
||||
mp_clear(&Py);
|
||||
mp_clear(&Qx);
|
||||
mp_clear(&Qy);
|
||||
mp_clear(&Rx);
|
||||
mp_clear(&Ry);
|
||||
mp_clear(&irreducible);
|
||||
mp_clear(&a);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes scalar point multiplication pointQ = k * pointP for
|
||||
* the curve whose parameters are encoded in params.
|
||||
*/
|
||||
SECStatus
|
||||
ec_point_mul(ECParams *params, mp_int *k,
|
||||
SECItem *pointP, SECItem *pointQ)
|
||||
{
|
||||
mp_int Px, Py, Qx, Qy;
|
||||
mp_int irreducible, a, b;
|
||||
SECStatus rv = SECFailure;
|
||||
mp_err err = MP_OKAY;
|
||||
int len;
|
||||
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
char mpstr[256];
|
||||
|
||||
printf("ec_point_mul: params [len=%d]:", params->DEREncoding.len);
|
||||
for (i = 0; i < params->DEREncoding.len; i++)
|
||||
printf("%02x:", params->DEREncoding.data[i]);
|
||||
printf("\n");
|
||||
|
||||
mp_tohex(k, mpstr);
|
||||
printf("ec_point_mul: scalar : %s\n", mpstr);
|
||||
mp_todecimal(k, mpstr);
|
||||
printf("ec_point_mul: scalar : %s (dec)\n", mpstr);
|
||||
|
||||
printf("ec_point_mul: pointP [len=%d]:", pointP->len);
|
||||
for (i = 0; i < pointP->len; i++)
|
||||
printf("%02x:", pointP->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/* NOTE: We only support prime field curves for now */
|
||||
len = (params->fieldID.size + 7) >> 3;
|
||||
if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
|
||||
(pointP->len != (2 * len + 1))) {
|
||||
return SECFailure;
|
||||
};
|
||||
|
||||
MP_DIGITS(&Px) = 0;
|
||||
MP_DIGITS(&Py) = 0;
|
||||
MP_DIGITS(&Qx) = 0;
|
||||
MP_DIGITS(&Qy) = 0;
|
||||
MP_DIGITS(&irreducible) = 0;
|
||||
MP_DIGITS(&a) = 0;
|
||||
MP_DIGITS(&b) = 0;
|
||||
CHECK_MPI_OK( mp_init(&Px) );
|
||||
CHECK_MPI_OK( mp_init(&Py) );
|
||||
CHECK_MPI_OK( mp_init(&Qx) );
|
||||
CHECK_MPI_OK( mp_init(&Qy) );
|
||||
CHECK_MPI_OK( mp_init(&irreducible) );
|
||||
CHECK_MPI_OK( mp_init(&a) );
|
||||
CHECK_MPI_OK( mp_init(&b) );
|
||||
|
||||
/* Initialize Px and Py */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
|
||||
/* Set up mp_ints containing the curve coefficients */
|
||||
SECITEM_TO_MPINT( params->curve.a, &a );
|
||||
SECITEM_TO_MPINT( params->curve.b, &b );
|
||||
|
||||
/* Compute Q = k * P */
|
||||
if (params->fieldID.type == ec_field_GFp) {
|
||||
SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
|
||||
if (GFp_ec_pt_mul(&irreducible, &a, &b, &Px, &Py, k, &Qx, &Qy)
|
||||
!= SECSuccess)
|
||||
goto cleanup;
|
||||
} else {
|
||||
SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
|
||||
if (GF2m_ec_pt_mul(&irreducible, &a, &b, &Px, &Py, k, &Qx, &Qy)
|
||||
!= SECSuccess) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct the SECItem representation of point Q */
|
||||
pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
|
||||
(mp_size) len) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
|
||||
(mp_size) len) );
|
||||
|
||||
rv = SECSuccess;
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ec_point_mul: pointQ [len=%d]:", pointQ->len);
|
||||
for (i = 0; i < pointQ->len; i++)
|
||||
printf("%02x:", pointQ->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mp_clear(&Px);
|
||||
mp_clear(&Py);
|
||||
mp_clear(&Qx);
|
||||
mp_clear(&Qy);
|
||||
mp_clear(&irreducible);
|
||||
mp_clear(&a);
|
||||
mp_clear(&b);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static unsigned char bitmask[] = {
|
||||
0xff, 0x7f, 0x3f, 0x1f,
|
||||
0x0f, 0x07, 0x03, 0x01
|
||||
};
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
/* Generates a new EC key pair. The private key is a supplied
|
||||
* random value (in seed) and the public key is the result of
|
||||
* performing a scalar point multiplication of that value with
|
||||
* the curve's base point.
|
||||
*/
|
||||
SECStatus
|
||||
EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
|
||||
const unsigned char *seed, int seedlen)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
PRArenaPool *arena;
|
||||
ECPrivateKey *key;
|
||||
mp_int k;
|
||||
mp_err err = MP_OKAY;
|
||||
int len;
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("EC_NewKeyFromSeed called\n");
|
||||
#endif
|
||||
|
||||
if (!ecParams || !privKey || !seed || (seedlen < 0)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Initialize an arena for the EC key. */
|
||||
if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
|
||||
return SECFailure;
|
||||
|
||||
key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
|
||||
if (!key) {
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
|
||||
/* Copy all of the fields from the ECParams argument to the
|
||||
* ECParams structure within the private key.
|
||||
*/
|
||||
key->ecParams.arena = arena;
|
||||
key->ecParams.type = ecParams->type;
|
||||
key->ecParams.fieldID.size = ecParams->fieldID.size;
|
||||
key->ecParams.fieldID.type = ecParams->fieldID.type;
|
||||
if (ecParams->fieldID.type == ec_field_GFp) {
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
|
||||
&ecParams->fieldID.u.prime));
|
||||
} else {
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
|
||||
&ecParams->fieldID.u.poly));
|
||||
}
|
||||
key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
|
||||
key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
|
||||
key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
|
||||
&ecParams->curve.a));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
|
||||
&ecParams->curve.b));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
|
||||
&ecParams->curve.seed));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
|
||||
&ecParams->base));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
|
||||
&ecParams->order));
|
||||
key->ecParams.cofactor = ecParams->cofactor;
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
|
||||
&ecParams->DEREncoding));
|
||||
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
SECITEM_AllocItem(arena, &key->privateValue, len);
|
||||
SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1);
|
||||
|
||||
/* Copy private key */
|
||||
if (seedlen >= len) {
|
||||
memcpy(key->privateValue.data, seed, len);
|
||||
} else {
|
||||
memset(key->privateValue.data, 0, (len - seedlen));
|
||||
memcpy(key->privateValue.data + (len - seedlen), seed, seedlen);
|
||||
}
|
||||
|
||||
/* Compute corresponding public key */
|
||||
MP_DIGITS(&k) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
|
||||
(mp_size) len) );
|
||||
|
||||
rv = ec_point_mul(ecParams, &k, &(ecParams->base), &(key->publicValue));
|
||||
if (rv != SECSuccess) goto cleanup;
|
||||
*privKey = key;
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("EC_NewKeyFromSeed returning %s\n",
|
||||
(rv == SECSuccess) ? "success" : "failure");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
/* Generates a new EC key pair. The private key is a random value and
|
||||
* the public key is the result of performing a scalar point multiplication
|
||||
* of that value with the curve's base point.
|
||||
*/
|
||||
SECStatus
|
||||
EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
int len;
|
||||
unsigned char *seed;
|
||||
|
||||
if (!ecParams || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Generate random private key */
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
if ((seed = PORT_Alloc(len)) == NULL) goto cleanup;
|
||||
if (RNG_GenerateGlobalRandomBytes(seed, len) != SECSuccess) goto cleanup;
|
||||
|
||||
/* Fit private key to the field size */
|
||||
seed[0] &= bitmask[len * 8 - ecParams->fieldID.size];
|
||||
rv = EC_NewKeyFromSeed(ecParams, privKey, seed, len);
|
||||
|
||||
cleanup:
|
||||
if (!seed) {
|
||||
PORT_ZFree(seed, len);
|
||||
}
|
||||
#if EC_DEBUG
|
||||
printf("EC_NewKey returning %s\n",
|
||||
(rv == SECSuccess) ? "success" : "failure");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of
|
||||
* X9.63. The ECDH primitive when used without the cofactor does
|
||||
* not address small subgroup attacks, which may occur when the
|
||||
* public key is not valid. These attacks can be prevented by
|
||||
* validating the public key before using ECDH.
|
||||
*/
|
||||
SECStatus
|
||||
EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
|
||||
{
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
if (!ecParams || !publicValue) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* XXX Add actual checks here. */
|
||||
return SECSuccess;
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
return SECFailure;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
}
|
||||
|
||||
/*
|
||||
** Performs an ECDH key derivation by computing the scalar point
|
||||
** multiplication of privateValue and publicValue (with or without the
|
||||
** cofactor) and returns the x-coordinate of the resulting elliptic
|
||||
** curve point in derived secret. If successful, derivedSecret->data
|
||||
** is set to the address of the newly allocated buffer containing the
|
||||
** derived secret, and derivedSecret->len is the size of the secret
|
||||
** produced. It is the caller's responsibility to free the allocated
|
||||
** buffer containing the derived secret.
|
||||
*/
|
||||
SECStatus
|
||||
ECDH_Derive(SECItem *publicValue,
|
||||
ECParams *ecParams,
|
||||
SECItem *privateValue,
|
||||
PRBool withCofactor,
|
||||
SECItem *derivedSecret)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
unsigned int len = 0;
|
||||
SECItem pointQ = {siBuffer, NULL, 0};
|
||||
mp_int k; /* to hold the private value */
|
||||
mp_int cofactor;
|
||||
mp_err err = MP_OKAY;
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (!publicValue || !ecParams || !privateValue ||
|
||||
!derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
pointQ.len = 2*len + 1;
|
||||
if ((pointQ.data = PORT_Alloc(2*len + 1)) == NULL) goto cleanup;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
|
||||
(mp_size) privateValue->len) );
|
||||
|
||||
if (withCofactor && (ecParams->cofactor != 1)) {
|
||||
/* multiply k with the cofactor */
|
||||
MP_DIGITS(&cofactor) = 0;
|
||||
CHECK_MPI_OK( mp_init(&cofactor) );
|
||||
mp_set(&cofactor, ecParams->cofactor);
|
||||
CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
|
||||
}
|
||||
|
||||
/* Multiply our private key and peer's public point */
|
||||
if ((ec_point_mul(ecParams, &k, publicValue, &pointQ) != SECSuccess) ||
|
||||
ec_point_at_infinity(&pointQ))
|
||||
goto cleanup;
|
||||
|
||||
/* Allocate memory for the derived secret and copy
|
||||
* the x co-ordinate of pointQ into it.
|
||||
*/
|
||||
SECITEM_AllocItem(NULL, derivedSecret, len);
|
||||
memcpy(derivedSecret->data, pointQ.data + 1, len);
|
||||
|
||||
rv = SECSuccess;
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("derived_secret:\n");
|
||||
for (i = 0; i < derivedSecret->len; i++)
|
||||
printf("%02x:", derivedSecret->data[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mp_clear(&k);
|
||||
|
||||
if (pointQ.data) {
|
||||
PORT_ZFree(pointQ.data, 2*len + 1);
|
||||
}
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Computes the ECDSA signature (a concatenation of two values r and s)
|
||||
* on the digest using the given key and the random value kb (used in
|
||||
* computing s).
|
||||
*/
|
||||
SECStatus
|
||||
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
|
||||
const SECItem *digest, const unsigned char *kb, const int kblen)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
mp_int x1;
|
||||
mp_int d, k; /* private key, random integer */
|
||||
mp_int r, s; /* tuple (r, s) is the signature */
|
||||
mp_int n;
|
||||
mp_err err = MP_OKAY;
|
||||
ECParams *ecParams = NULL;
|
||||
SECItem kGpoint = { siBuffer, NULL, 0};
|
||||
int len = 0;
|
||||
|
||||
#if EC_DEBUG
|
||||
char mpstr[256];
|
||||
#endif
|
||||
|
||||
/* Check args */
|
||||
if (!key || !signature || !digest || !kb || (kblen < 0) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ecParams = &(key->ecParams);
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
if (signature->len < 2*len) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&d) = 0;
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&s) = 0;
|
||||
MP_DIGITS(&n) = 0;
|
||||
CHECK_MPI_OK( mp_init(&x1) );
|
||||
CHECK_MPI_OK( mp_init(&d) );
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&s) );
|
||||
CHECK_MPI_OK( mp_init(&n) );
|
||||
|
||||
SECITEM_TO_MPINT( ecParams->order, &n );
|
||||
SECITEM_TO_MPINT( key->privateValue, &d );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
|
||||
/* Make sure k is in the interval [1, n-1] */
|
||||
if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.2, Step 2
|
||||
**
|
||||
** Compute kG
|
||||
*/
|
||||
kGpoint.len = 2*len + 1;
|
||||
kGpoint.data = PORT_Alloc(2*len + 1);
|
||||
if ((kGpoint.data == NULL) ||
|
||||
(ec_point_mul(ecParams, &k, &(ecParams->base), &kGpoint)
|
||||
!= SECSuccess))
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 1
|
||||
**
|
||||
** Extract the x co-ordinate of kG into x1
|
||||
*/
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
|
||||
(mp_size) len) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 2
|
||||
**
|
||||
** r = x1 mod n NOTE: n is the order of the curve
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 3
|
||||
**
|
||||
** verify r != 0
|
||||
*/
|
||||
if (mp_cmp_z(&r) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 4
|
||||
**
|
||||
** s = (k**-1 * (SHA1(M) + d*r)) mod n
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
|
||||
|
||||
#if EC_DEBUG
|
||||
mp_todecimal(&n, mpstr);
|
||||
printf("n : %s (dec)\n", mpstr);
|
||||
mp_todecimal(&d, mpstr);
|
||||
printf("d : %s (dec)\n", mpstr);
|
||||
mp_tohex(&x1, mpstr);
|
||||
printf("x1: %s\n", mpstr);
|
||||
mp_todecimal(&s, mpstr);
|
||||
printf("digest: %s (decimal)\n", mpstr);
|
||||
mp_todecimal(&r, mpstr);
|
||||
printf("r : %s (dec)\n", mpstr);
|
||||
#endif
|
||||
|
||||
CHECK_MPI_OK( mp_invmod(&k, &n, &k) ); /* k = k**-1 mod n */
|
||||
CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) ); /* d = d * r mod n */
|
||||
CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) ); /* s = s + d mod n */
|
||||
CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) ); /* s = s * k mod n */
|
||||
|
||||
#if EC_DEBUG
|
||||
mp_todecimal(&s, mpstr);
|
||||
printf("s : %s (dec)\n", mpstr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.3.3, Step 5
|
||||
**
|
||||
** verify s != 0
|
||||
*/
|
||||
if (mp_cmp_z(&s) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Signature is tuple (r, s)
|
||||
*/
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, len) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + len, len) );
|
||||
signature->len = 2*len;
|
||||
|
||||
rv = SECSuccess;
|
||||
err = MP_OKAY;
|
||||
cleanup:
|
||||
mp_clear(&x1);
|
||||
mp_clear(&d);
|
||||
mp_clear(&k);
|
||||
mp_clear(&r);
|
||||
mp_clear(&s);
|
||||
mp_clear(&n);
|
||||
|
||||
if (kGpoint.data) {
|
||||
PORT_ZFree(kGpoint.data, 2*len + 1);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ECDSA signing with seed %s\n",
|
||||
(rv == SECSuccess) ? "succeeded" : "failed");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Computes the ECDSA signature on the digest using the given key
|
||||
** and a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
int prerr = 0;
|
||||
int n = (key->ecParams.fieldID.size + 7) >> 3;
|
||||
unsigned char mask = bitmask[n * 8 - key->ecParams.fieldID.size];
|
||||
unsigned char *kseed = NULL;
|
||||
|
||||
/* Generate random seed of appropriate size as dictated
|
||||
* by field size.
|
||||
*/
|
||||
if ((kseed = PORT_Alloc(n)) == NULL) return SECFailure;
|
||||
|
||||
do {
|
||||
if (RNG_GenerateGlobalRandomBytes(kseed, n) != SECSuccess)
|
||||
goto cleanup;
|
||||
*kseed &= mask;
|
||||
rv = ECDSA_SignDigestWithSeed(key, signature, digest, kseed, n);
|
||||
if (rv) prerr = PORT_GetError();
|
||||
} while ((rv != SECSuccess) && (prerr == SEC_ERROR_NEED_RANDOM));
|
||||
|
||||
cleanup:
|
||||
if (kseed) PORT_ZFree(kseed, n);
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ECDSA signing %s\n",
|
||||
(rv == SECSuccess) ? "succeeded" : "failed");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Checks the signature on the given digest using the key provided.
|
||||
*/
|
||||
SECStatus
|
||||
ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
|
||||
const SECItem *digest)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
mp_int r_, s_; /* tuple (r', s') is received signature) */
|
||||
mp_int c, u1, u2, v; /* intermediate values used in verification */
|
||||
mp_int x1, y1;
|
||||
mp_int x2, y2;
|
||||
mp_int n;
|
||||
mp_err err = MP_OKAY;
|
||||
PRArenaPool *arena = NULL;
|
||||
ECParams *ecParams = NULL;
|
||||
SECItem pointA = { siBuffer, NULL, 0 };
|
||||
SECItem pointB = { siBuffer, NULL, 0 };
|
||||
SECItem pointC = { siBuffer, NULL, 0 };
|
||||
int len;
|
||||
|
||||
#if EC_DEBUG
|
||||
char mpstr[256];
|
||||
printf("ECDSA verification called\n");
|
||||
#endif
|
||||
|
||||
/* Check args */
|
||||
if (!key || !signature || !digest ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ecParams = &(key->ecParams);
|
||||
len = (ecParams->fieldID.size + 7) >> 3;
|
||||
if (signature->len < 2*len) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Initialize an arena for pointA, pointB and pointC */
|
||||
if ((arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)) == NULL)
|
||||
goto cleanup;
|
||||
|
||||
SECITEM_AllocItem(arena, &pointA, 2*len + 1);
|
||||
SECITEM_AllocItem(arena, &pointB, 2*len + 1);
|
||||
SECITEM_AllocItem(arena, &pointC, 2*len + 1);
|
||||
if (pointA.data == NULL || pointB.data == NULL || pointC.data == NULL)
|
||||
goto cleanup;
|
||||
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&r_) = 0;
|
||||
MP_DIGITS(&s_) = 0;
|
||||
MP_DIGITS(&c) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&y1) = 0;
|
||||
MP_DIGITS(&x2) = 0;
|
||||
MP_DIGITS(&y2) = 0;
|
||||
MP_DIGITS(&v) = 0;
|
||||
MP_DIGITS(&n) = 0;
|
||||
CHECK_MPI_OK( mp_init(&r_) );
|
||||
CHECK_MPI_OK( mp_init(&s_) );
|
||||
CHECK_MPI_OK( mp_init(&c) );
|
||||
CHECK_MPI_OK( mp_init(&u1) );
|
||||
CHECK_MPI_OK( mp_init(&u2) );
|
||||
CHECK_MPI_OK( mp_init(&x1) );
|
||||
CHECK_MPI_OK( mp_init(&y1) );
|
||||
CHECK_MPI_OK( mp_init(&x2) );
|
||||
CHECK_MPI_OK( mp_init(&y2) );
|
||||
CHECK_MPI_OK( mp_init(&v) );
|
||||
CHECK_MPI_OK( mp_init(&n) );
|
||||
|
||||
/*
|
||||
** Convert received signature (r', s') into MPI integers.
|
||||
*/
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, len) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + len, len) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.2, Steps 1 and 2
|
||||
**
|
||||
** Verify that 0 < r' < n and 0 < s' < n
|
||||
*/
|
||||
SECITEM_TO_MPINT(ecParams->order, &n);
|
||||
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
|
||||
mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0)
|
||||
goto cleanup; /* will return rv == SECFailure */
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.2, Step 3
|
||||
**
|
||||
** c = (s')**-1 mod n
|
||||
*/
|
||||
CHECK_MPI_OK( mp_invmod(&s_, &n, &c) ); /* c = (s')**-1 mod n */
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.2, Step 4
|
||||
**
|
||||
** u1 = ((SHA1(M')) * c) mod n
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
|
||||
|
||||
#if EC_DEBUG
|
||||
mp_todecimal(&r_, mpstr);
|
||||
printf("r_: %s (dec)\n", mpstr);
|
||||
mp_todecimal(&s_, mpstr);
|
||||
printf("s_: %s (dec)\n", mpstr);
|
||||
mp_todecimal(&c, mpstr);
|
||||
printf("c : %s (dec)\n", mpstr);
|
||||
mp_todecimal(&u1, mpstr);
|
||||
printf("digest: %s (dec)\n", mpstr);
|
||||
#endif
|
||||
|
||||
CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) ); /* u1 = u1 * c mod n */
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.2, Step 4
|
||||
**
|
||||
** u2 = ((r') * c) mod n
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.3, Step 1
|
||||
**
|
||||
** Compute u1*G + u2*Q
|
||||
** Here, A = u1.G B = u2.Q and C = A + B
|
||||
** If the result, C, is the point at infinity, reject the signature
|
||||
*/
|
||||
if ((ec_point_mul(ecParams, &u1, &ecParams->base, &pointA)
|
||||
== SECFailure) ||
|
||||
(ec_point_mul(ecParams, &u2, &key->publicValue, &pointB)
|
||||
== SECFailure) ||
|
||||
(ec_point_add(ecParams, &pointA, &pointB, &pointC) == SECFailure) ||
|
||||
ec_point_at_infinity(&pointC)) {
|
||||
rv = SECFailure;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, len) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.4, Step 2
|
||||
**
|
||||
** v = x1 mod n
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mod(&x1, &n, &v) );
|
||||
|
||||
/*
|
||||
** ANSI X9.62, Section 5.4.4, Step 3
|
||||
**
|
||||
** Verification: v == r'
|
||||
*/
|
||||
if (mp_cmp(&v, &r_)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
rv = SECFailure; /* Signature failed to verify. */
|
||||
} else {
|
||||
rv = SECSuccess; /* Signature verified. */
|
||||
}
|
||||
|
||||
#if EC_DEBUG
|
||||
mp_todecimal(&u1, mpstr);
|
||||
printf("u1: %s (dec)\n", mpstr);
|
||||
mp_todecimal(&u2, mpstr);
|
||||
printf("u2: %s (dec)\n", mpstr);
|
||||
mp_tohex(&x1, mpstr);
|
||||
printf("x1: %s\n", mpstr);
|
||||
mp_todecimal(&v, mpstr);
|
||||
printf("v : %s (dec)\n", mpstr);
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mp_clear(&r_);
|
||||
mp_clear(&s_);
|
||||
mp_clear(&c);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&x1);
|
||||
mp_clear(&y1);
|
||||
mp_clear(&x2);
|
||||
mp_clear(&y2);
|
||||
mp_clear(&v);
|
||||
mp_clear(&n);
|
||||
|
||||
if (arena) PORT_FreeArena(arena, PR_TRUE);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("ECDSA verification %s\n",
|
||||
(rv == SECSuccess) ? "succeeded" : "failed");
|
||||
#endif
|
||||
#else
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
50
mozilla/security/nss/lib/freebl/ec.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Elliptic Curve Cryptography library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ec_h_
|
||||
#define __ec_h_
|
||||
|
||||
#define EC_DEBUG 0
|
||||
#define EC_POINT_FORM_COMPRESSED_Y0 0x02
|
||||
#define EC_POINT_FORM_COMPRESSED_Y1 0x03
|
||||
#define EC_POINT_FORM_UNCOMPRESSED 0x04
|
||||
#define EC_POINT_FORM_HYBRID_Y0 0x06
|
||||
#define EC_POINT_FORM_HYBRID_Y1 0x07
|
||||
|
||||
#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
|
||||
#define SECG_CURVE_OID_TOTAL_LEN 7
|
||||
|
||||
#endif /* __ec_h_ */
|
||||
120
mozilla/security/nss/lib/freebl/fblstdlib.c
Executable file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <plstr.h>
|
||||
#include "aglobal.h"
|
||||
#include "bsafe.h"
|
||||
#include "secport.h"
|
||||
|
||||
void CALL_CONV T_memset (p, c, count)
|
||||
POINTER p;
|
||||
int c;
|
||||
unsigned int count;
|
||||
{
|
||||
if (count >= 0)
|
||||
memset(p, c, count);
|
||||
}
|
||||
|
||||
void CALL_CONV T_memcpy (d, s, count)
|
||||
POINTER d, s;
|
||||
unsigned int count;
|
||||
{
|
||||
if (count >= 0)
|
||||
memcpy(d, s, count);
|
||||
}
|
||||
|
||||
void CALL_CONV T_memmove (d, s, count)
|
||||
POINTER d, s;
|
||||
unsigned int count;
|
||||
{
|
||||
if (count >= 0)
|
||||
PORT_Memmove(d, s, count);
|
||||
}
|
||||
|
||||
int CALL_CONV T_memcmp (s1, s2, count)
|
||||
POINTER s1, s2;
|
||||
unsigned int count;
|
||||
{
|
||||
if (count == 0)
|
||||
return (0);
|
||||
else
|
||||
return(memcmp(s1, s2, count));
|
||||
}
|
||||
|
||||
POINTER CALL_CONV T_malloc (size)
|
||||
unsigned int size;
|
||||
{
|
||||
return((POINTER)PORT_Alloc(size == 0 ? 1 : size));
|
||||
}
|
||||
|
||||
POINTER CALL_CONV T_realloc (p, size)
|
||||
POINTER p;
|
||||
unsigned int size;
|
||||
{
|
||||
POINTER result;
|
||||
|
||||
if (p == NULL_PTR)
|
||||
return (T_malloc(size));
|
||||
|
||||
if ((result = (POINTER)PORT_Realloc(p, size == 0 ? 1 : size)) == NULL_PTR)
|
||||
PORT_Free(p);
|
||||
return (result);
|
||||
}
|
||||
|
||||
void CALL_CONV T_free (p)
|
||||
POINTER p;
|
||||
{
|
||||
if (p != NULL_PTR)
|
||||
PORT_Free(p);
|
||||
}
|
||||
|
||||
unsigned int CALL_CONV T_strlen(p)
|
||||
char *p;
|
||||
{
|
||||
return PL_strlen(p);
|
||||
}
|
||||
|
||||
void CALL_CONV T_strcpy(dest, src)
|
||||
char *dest;
|
||||
char *src;
|
||||
{
|
||||
PL_strcpy(dest, src);
|
||||
}
|
||||
|
||||
int CALL_CONV T_strcmp (a, b)
|
||||
char *a, *b;
|
||||
{
|
||||
return (PL_strcmp (a, b));
|
||||
}
|
||||
196
mozilla/security/nss/lib/freebl/ldvector.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* ldvector.c - platform dependent DSO containing freebl implementation.
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: ldvector.c,v 1.6 2003-02-27 01:31:13 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "loader.h"
|
||||
|
||||
static const struct FREEBLVectorStr vector = {
|
||||
|
||||
sizeof vector,
|
||||
FREEBL_VERSION,
|
||||
|
||||
RSA_NewKey,
|
||||
RSA_PublicKeyOp,
|
||||
RSA_PrivateKeyOp,
|
||||
DSA_NewKey,
|
||||
DSA_SignDigest,
|
||||
DSA_VerifyDigest,
|
||||
DSA_NewKeyFromSeed,
|
||||
DSA_SignDigestWithSeed,
|
||||
DH_GenParam,
|
||||
DH_NewKey,
|
||||
DH_Derive,
|
||||
KEA_Derive,
|
||||
KEA_Verify,
|
||||
RC4_CreateContext,
|
||||
RC4_DestroyContext,
|
||||
RC4_Encrypt,
|
||||
RC4_Decrypt,
|
||||
RC2_CreateContext,
|
||||
RC2_DestroyContext,
|
||||
RC2_Encrypt,
|
||||
RC2_Decrypt,
|
||||
RC5_CreateContext,
|
||||
RC5_DestroyContext,
|
||||
RC5_Encrypt,
|
||||
RC5_Decrypt,
|
||||
DES_CreateContext,
|
||||
DES_DestroyContext,
|
||||
DES_Encrypt,
|
||||
DES_Decrypt,
|
||||
AES_CreateContext,
|
||||
AES_DestroyContext,
|
||||
AES_Encrypt,
|
||||
AES_Decrypt,
|
||||
MD5_Hash,
|
||||
MD5_HashBuf,
|
||||
MD5_NewContext,
|
||||
MD5_DestroyContext,
|
||||
MD5_Begin,
|
||||
MD5_Update,
|
||||
MD5_End,
|
||||
MD5_FlattenSize,
|
||||
MD5_Flatten,
|
||||
MD5_Resurrect,
|
||||
MD5_TraceState,
|
||||
MD2_Hash,
|
||||
MD2_NewContext,
|
||||
MD2_DestroyContext,
|
||||
MD2_Begin,
|
||||
MD2_Update,
|
||||
MD2_End,
|
||||
MD2_FlattenSize,
|
||||
MD2_Flatten,
|
||||
MD2_Resurrect,
|
||||
SHA1_Hash,
|
||||
SHA1_HashBuf,
|
||||
SHA1_NewContext,
|
||||
SHA1_DestroyContext,
|
||||
SHA1_Begin,
|
||||
SHA1_Update,
|
||||
SHA1_End,
|
||||
SHA1_TraceState,
|
||||
SHA1_FlattenSize,
|
||||
SHA1_Flatten,
|
||||
SHA1_Resurrect,
|
||||
RNG_RNGInit,
|
||||
RNG_RandomUpdate,
|
||||
RNG_GenerateGlobalRandomBytes,
|
||||
RNG_RNGShutdown,
|
||||
PQG_ParamGen,
|
||||
PQG_ParamGenSeedLen,
|
||||
PQG_VerifyParams,
|
||||
|
||||
/* End of Version 3.001. */
|
||||
|
||||
RSA_PrivateKeyOpDoubleChecked,
|
||||
RSA_PrivateKeyCheck,
|
||||
BL_Cleanup,
|
||||
|
||||
/* End of Version 3.002. */
|
||||
|
||||
SHA256_NewContext,
|
||||
SHA256_DestroyContext,
|
||||
SHA256_Begin,
|
||||
SHA256_Update,
|
||||
SHA256_End,
|
||||
SHA256_HashBuf,
|
||||
SHA256_Hash,
|
||||
SHA256_TraceState,
|
||||
SHA256_FlattenSize,
|
||||
SHA256_Flatten,
|
||||
SHA256_Resurrect,
|
||||
|
||||
SHA512_NewContext,
|
||||
SHA512_DestroyContext,
|
||||
SHA512_Begin,
|
||||
SHA512_Update,
|
||||
SHA512_End,
|
||||
SHA512_HashBuf,
|
||||
SHA512_Hash,
|
||||
SHA512_TraceState,
|
||||
SHA512_FlattenSize,
|
||||
SHA512_Flatten,
|
||||
SHA512_Resurrect,
|
||||
|
||||
SHA384_NewContext,
|
||||
SHA384_DestroyContext,
|
||||
SHA384_Begin,
|
||||
SHA384_Update,
|
||||
SHA384_End,
|
||||
SHA384_HashBuf,
|
||||
SHA384_Hash,
|
||||
SHA384_TraceState,
|
||||
SHA384_FlattenSize,
|
||||
SHA384_Flatten,
|
||||
SHA384_Resurrect,
|
||||
|
||||
/* End of Version 3.003. */
|
||||
|
||||
AESKeyWrap_CreateContext,
|
||||
AESKeyWrap_DestroyContext,
|
||||
AESKeyWrap_Encrypt,
|
||||
AESKeyWrap_Decrypt,
|
||||
|
||||
/* End of Version 3.004. */
|
||||
|
||||
BLAPI_SHVerify,
|
||||
BLAPI_VerifySelf,
|
||||
|
||||
/* End of Version 3.005. */
|
||||
|
||||
EC_NewKey,
|
||||
EC_NewKeyFromSeed,
|
||||
EC_ValidatePublicKey,
|
||||
ECDH_Derive,
|
||||
ECDSA_SignDigest,
|
||||
ECDSA_VerifyDigest,
|
||||
ECDSA_SignDigestWithSeed,
|
||||
|
||||
/* End of Version 3.006. */
|
||||
};
|
||||
|
||||
|
||||
const FREEBLVector *
|
||||
FREEBL_GetVector(void)
|
||||
{
|
||||
return &vector;
|
||||
}
|
||||
|
||||
1366
mozilla/security/nss/lib/freebl/loader.c
Normal file
386
mozilla/security/nss/lib/freebl/loader.h
Normal file
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* loader.h - load platform dependent DSO containing freebl implementation.
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
* Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: loader.h,v 1.9 2003-02-27 01:31:14 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _LOADER_H_
|
||||
#define _LOADER_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
#define FREEBL_VERSION 0x0306
|
||||
|
||||
struct FREEBLVectorStr {
|
||||
|
||||
unsigned short length; /* of this struct in bytes */
|
||||
unsigned short version; /* of this struct. */
|
||||
|
||||
RSAPrivateKey * (* p_RSA_NewKey)(int keySizeInBits,
|
||||
SECItem * publicExponent);
|
||||
|
||||
SECStatus (* p_RSA_PublicKeyOp) (RSAPublicKey * key,
|
||||
unsigned char * output,
|
||||
const unsigned char * input);
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyOp)(RSAPrivateKey * key,
|
||||
unsigned char * output,
|
||||
const unsigned char * input);
|
||||
|
||||
SECStatus (* p_DSA_NewKey)(const PQGParams * params,
|
||||
DSAPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_DSA_SignDigest)(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_DSA_VerifyDigest)(DSAPublicKey * key,
|
||||
const SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_DSA_NewKeyFromSeed)(const PQGParams *params,
|
||||
const unsigned char * seed,
|
||||
DSAPrivateKey **privKey);
|
||||
|
||||
SECStatus (* p_DSA_SignDigestWithSeed)(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed);
|
||||
|
||||
SECStatus (* p_DH_GenParam)(int primeLen, DHParams ** params);
|
||||
|
||||
SECStatus (* p_DH_NewKey)(DHParams * params,
|
||||
DHPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_DH_Derive)(SECItem * publicValue,
|
||||
SECItem * prime,
|
||||
SECItem * privateValue,
|
||||
SECItem * derivedSecret,
|
||||
unsigned int maxOutBytes);
|
||||
|
||||
SECStatus (* p_KEA_Derive)(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret);
|
||||
|
||||
PRBool (* p_KEA_Verify)(SECItem *Y, SECItem *prime, SECItem *subPrime);
|
||||
|
||||
RC4Context * (* p_RC4_CreateContext)(const unsigned char *key, int len);
|
||||
|
||||
void (* p_RC4_DestroyContext)(RC4Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC4_Encrypt)(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC4_Decrypt)(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
RC2Context * (* p_RC2_CreateContext)(const unsigned char *key,
|
||||
unsigned int len, const unsigned char *iv,
|
||||
int mode, unsigned effectiveKeyLen);
|
||||
|
||||
void (* p_RC2_DestroyContext)(RC2Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC2_Encrypt)(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC2_Decrypt)(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
RC5Context *(* p_RC5_CreateContext)(const SECItem *key, unsigned int rounds,
|
||||
unsigned int wordSize, const unsigned char *iv, int mode);
|
||||
|
||||
void (* p_RC5_DestroyContext)(RC5Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC5_Encrypt)(RC5Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC5_Decrypt)(RC5Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
DESContext *(* p_DES_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int mode, PRBool encrypt);
|
||||
|
||||
void (* p_DES_DestroyContext)(DESContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_DES_Encrypt)(DESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_DES_Decrypt)(DESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
AESContext * (* p_AES_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int mode, int encrypt, unsigned int keylen,
|
||||
unsigned int blocklen);
|
||||
|
||||
void (* p_AES_DestroyContext)(AESContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_AES_Encrypt)(AESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_AES_Decrypt)(AESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_MD5_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
SECStatus (* p_MD5_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
|
||||
MD5Context *(* p_MD5_NewContext)(void);
|
||||
|
||||
void (* p_MD5_DestroyContext)(MD5Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_MD5_Begin)(MD5Context *cx);
|
||||
|
||||
void (* p_MD5_Update)(MD5Context *cx,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
void (* p_MD5_End)(MD5Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
unsigned int (* p_MD5_FlattenSize)(MD5Context *cx);
|
||||
|
||||
SECStatus (* p_MD5_Flatten)(MD5Context *cx,unsigned char *space);
|
||||
|
||||
MD5Context * (* p_MD5_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
void (* p_MD5_TraceState)(MD5Context *cx);
|
||||
|
||||
SECStatus (* p_MD2_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
MD2Context *(* p_MD2_NewContext)(void);
|
||||
|
||||
void (* p_MD2_DestroyContext)(MD2Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_MD2_Begin)(MD2Context *cx);
|
||||
|
||||
void (* p_MD2_Update)(MD2Context *cx,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
void (* p_MD2_End)(MD2Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
unsigned int (* p_MD2_FlattenSize)(MD2Context *cx);
|
||||
|
||||
SECStatus (* p_MD2_Flatten)(MD2Context *cx,unsigned char *space);
|
||||
|
||||
MD2Context * (* p_MD2_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SECStatus (* p_SHA1_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
SECStatus (* p_SHA1_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
|
||||
SHA1Context *(* p_SHA1_NewContext)(void);
|
||||
|
||||
void (* p_SHA1_DestroyContext)(SHA1Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_SHA1_Begin)(SHA1Context *cx);
|
||||
|
||||
void (* p_SHA1_Update)(SHA1Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
void (* p_SHA1_End)(SHA1Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
void (* p_SHA1_TraceState)(SHA1Context *cx);
|
||||
|
||||
unsigned int (* p_SHA1_FlattenSize)(SHA1Context *cx);
|
||||
|
||||
SECStatus (* p_SHA1_Flatten)(SHA1Context *cx,unsigned char *space);
|
||||
|
||||
SHA1Context * (* p_SHA1_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SECStatus (* p_RNG_RNGInit)(void);
|
||||
|
||||
SECStatus (* p_RNG_RandomUpdate)(const void *data, size_t bytes);
|
||||
|
||||
SECStatus (* p_RNG_GenerateGlobalRandomBytes)(void *dest, size_t len);
|
||||
|
||||
void (* p_RNG_RNGShutdown)(void);
|
||||
|
||||
SECStatus (* p_PQG_ParamGen)(unsigned int j, PQGParams **pParams,
|
||||
PQGVerify **pVfy);
|
||||
|
||||
SECStatus (* p_PQG_ParamGenSeedLen)( unsigned int j, unsigned int seedBytes,
|
||||
PQGParams **pParams, PQGVerify **pVfy);
|
||||
|
||||
SECStatus (* p_PQG_VerifyParams)(const PQGParams *params,
|
||||
const PQGVerify *vfy, SECStatus *result);
|
||||
|
||||
/* Version 3.001 came to here */
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyOpDoubleChecked)(RSAPrivateKey *key,
|
||||
unsigned char *output,
|
||||
const unsigned char *input);
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyCheck)(RSAPrivateKey *key);
|
||||
|
||||
void (* p_BL_Cleanup)(void);
|
||||
|
||||
/* Version 3.002 came to here */
|
||||
|
||||
SHA256Context *(* p_SHA256_NewContext)(void);
|
||||
void (* p_SHA256_DestroyContext)(SHA256Context *cx, PRBool freeit);
|
||||
void (* p_SHA256_Begin)(SHA256Context *cx);
|
||||
void (* p_SHA256_Update)(SHA256Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA256_End)(SHA256Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA256_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA256_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA256_TraceState)(SHA256Context *cx);
|
||||
unsigned int (* p_SHA256_FlattenSize)(SHA256Context *cx);
|
||||
SECStatus (* p_SHA256_Flatten)(SHA256Context *cx,unsigned char *space);
|
||||
SHA256Context * (* p_SHA256_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SHA512Context *(* p_SHA512_NewContext)(void);
|
||||
void (* p_SHA512_DestroyContext)(SHA512Context *cx, PRBool freeit);
|
||||
void (* p_SHA512_Begin)(SHA512Context *cx);
|
||||
void (* p_SHA512_Update)(SHA512Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA512_End)(SHA512Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA512_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA512_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA512_TraceState)(SHA512Context *cx);
|
||||
unsigned int (* p_SHA512_FlattenSize)(SHA512Context *cx);
|
||||
SECStatus (* p_SHA512_Flatten)(SHA512Context *cx,unsigned char *space);
|
||||
SHA512Context * (* p_SHA512_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SHA384Context *(* p_SHA384_NewContext)(void);
|
||||
void (* p_SHA384_DestroyContext)(SHA384Context *cx, PRBool freeit);
|
||||
void (* p_SHA384_Begin)(SHA384Context *cx);
|
||||
void (* p_SHA384_Update)(SHA384Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA384_End)(SHA384Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA384_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA384_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA384_TraceState)(SHA384Context *cx);
|
||||
unsigned int (* p_SHA384_FlattenSize)(SHA384Context *cx);
|
||||
SECStatus (* p_SHA384_Flatten)(SHA384Context *cx,unsigned char *space);
|
||||
SHA384Context * (* p_SHA384_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
/* Version 3.003 came to here */
|
||||
|
||||
AESKeyWrapContext * (* p_AESKeyWrap_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv, int encrypt, unsigned int keylen);
|
||||
|
||||
void (* p_AESKeyWrap_DestroyContext)(AESKeyWrapContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_AESKeyWrap_Encrypt)(AESKeyWrapContext *cx,
|
||||
unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_AESKeyWrap_Decrypt)(AESKeyWrapContext *cx,
|
||||
unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
/* Version 3.004 came to here */
|
||||
|
||||
PRBool (*p_BLAPI_SHVerify)(const char *name, PRFuncPtr addr);
|
||||
PRBool (*p_BLAPI_VerifySelf)(const char *name);
|
||||
|
||||
/* Version 3.005 came to here */
|
||||
|
||||
SECStatus (* p_EC_NewKey)(ECParams * params,
|
||||
ECPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_EC_NewKeyFromSeed)(ECParams * params,
|
||||
ECPrivateKey ** privKey,
|
||||
const unsigned char * seed,
|
||||
int seedlen);
|
||||
|
||||
SECStatus (* p_EC_ValidatePublicKey)(ECParams * params,
|
||||
SECItem * publicValue);
|
||||
|
||||
SECStatus (* p_ECDH_Derive)(SECItem * publicValue,
|
||||
ECParams * params,
|
||||
SECItem * privateValue,
|
||||
PRBool withCofactor,
|
||||
SECItem * derivedSecret);
|
||||
|
||||
SECStatus (* p_ECDSA_SignDigest)(ECPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_ECDSA_VerifyDigest)(ECPublicKey * key,
|
||||
const SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_ECDSA_SignDigestWithSeed)(ECPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed,
|
||||
const int seedlen);
|
||||
|
||||
/* Version 3.006 came to here */
|
||||
|
||||
};
|
||||
|
||||
typedef struct FREEBLVectorStr FREEBLVector;
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
typedef const FREEBLVector * FREEBLGetVectorFn(void);
|
||||
|
||||
extern FREEBLGetVectorFn FREEBL_GetVector;
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
315
mozilla/security/nss/lib/freebl/mac_rand.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#ifdef notdef
|
||||
#include "xp_core.h"
|
||||
#include "xp_file.h"
|
||||
#endif
|
||||
#include "secrng.h"
|
||||
#include "mcom_db.h"
|
||||
#ifdef XP_MAC
|
||||
#include <Events.h>
|
||||
#include <OSUtils.h>
|
||||
#include <QDOffscreen.h>
|
||||
#include <PPCToolbox.h>
|
||||
#include <Processes.h>
|
||||
#include <LowMem.h>
|
||||
#include <Scrap.h>
|
||||
|
||||
/* Static prototypes */
|
||||
static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen);
|
||||
void FE_ReadScreen();
|
||||
|
||||
static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen)
|
||||
{
|
||||
union endianness {
|
||||
int32 i;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
if (srclen <= dstlen) {
|
||||
memcpy(dst, src, srclen);
|
||||
return srclen;
|
||||
}
|
||||
u.i = 0x01020304;
|
||||
if (u.c[0] == 0x01) {
|
||||
/* big-endian case */
|
||||
memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
|
||||
} else {
|
||||
/* little-endian case */
|
||||
memcpy(dst, src, dstlen);
|
||||
}
|
||||
return dstlen;
|
||||
}
|
||||
|
||||
size_t RNG_GetNoise(void *buf, size_t maxbytes)
|
||||
{
|
||||
UnsignedWide microTickCount;
|
||||
Microseconds(µTickCount);
|
||||
return CopyLowBits(buf, maxbytes, µTickCount, sizeof(microTickCount));
|
||||
}
|
||||
|
||||
void RNG_FileForRNG(const char *filename)
|
||||
{
|
||||
unsigned char buffer[BUFSIZ];
|
||||
size_t bytes;
|
||||
#ifdef notdef /*sigh*/
|
||||
XP_File file;
|
||||
unsigned long totalFileBytes = 0;
|
||||
|
||||
if (filename == NULL) /* For now, read in global history if filename is null */
|
||||
file = XP_FileOpen(NULL, xpGlobalHistory,XP_FILE_READ_BIN);
|
||||
else
|
||||
file = XP_FileOpen(NULL, xpURL,XP_FILE_READ_BIN);
|
||||
if (file != NULL) {
|
||||
for (;;) {
|
||||
bytes = XP_FileRead(buffer, sizeof(buffer), file);
|
||||
if (bytes == 0) break;
|
||||
RNG_RandomUpdate( buffer, bytes);
|
||||
totalFileBytes += bytes;
|
||||
if (totalFileBytes > 100*1024) break; /* No more than 100 K */
|
||||
}
|
||||
XP_FileClose(file);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Pass yet another snapshot of our highest resolution clock into
|
||||
* the hash function.
|
||||
*/
|
||||
bytes = RNG_GetNoise(buffer, sizeof(buffer));
|
||||
RNG_RandomUpdate(buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
void RNG_SystemInfoForRNG()
|
||||
{
|
||||
/* Time */
|
||||
{
|
||||
unsigned long sec;
|
||||
size_t bytes;
|
||||
GetDateTime(&sec); /* Current time since 1970 */
|
||||
RNG_RandomUpdate( &sec, sizeof(sec));
|
||||
bytes = RNG_GetNoise(&sec, sizeof(sec));
|
||||
RNG_RandomUpdate(&sec, bytes);
|
||||
}
|
||||
/* User specific variables */
|
||||
{
|
||||
MachineLocation loc;
|
||||
ReadLocation(&loc);
|
||||
RNG_RandomUpdate( &loc, sizeof(loc));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* User name */
|
||||
{
|
||||
unsigned long userRef;
|
||||
Str32 userName;
|
||||
GetDefaultUser(&userRef, userName);
|
||||
RNG_RandomUpdate( &userRef, sizeof(userRef));
|
||||
RNG_RandomUpdate( userName, sizeof(userName));
|
||||
}
|
||||
#endif
|
||||
/* Mouse location */
|
||||
{
|
||||
Point mouseLoc;
|
||||
GetMouse(&mouseLoc);
|
||||
RNG_RandomUpdate( &mouseLoc, sizeof(mouseLoc));
|
||||
}
|
||||
/* Keyboard time threshold */
|
||||
{
|
||||
SInt16 keyTresh = LMGetKeyThresh();
|
||||
RNG_RandomUpdate( &keyTresh, sizeof(keyTresh));
|
||||
}
|
||||
/* Last key pressed */
|
||||
{
|
||||
SInt8 keyLast;
|
||||
keyLast = LMGetKbdLast();
|
||||
RNG_RandomUpdate( &keyLast, sizeof(keyLast));
|
||||
}
|
||||
/* Volume */
|
||||
{
|
||||
UInt8 volume = LMGetSdVolume();
|
||||
RNG_RandomUpdate( &volume, sizeof(volume));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* Current directory */
|
||||
{
|
||||
SInt32 dir = LMGetCurDirStore();
|
||||
RNG_RandomUpdate( &dir, sizeof(dir));
|
||||
}
|
||||
#endif
|
||||
/* Process information about all the processes in the machine */
|
||||
{
|
||||
ProcessSerialNumber process;
|
||||
ProcessInfoRec pi;
|
||||
|
||||
process.highLongOfPSN = process.lowLongOfPSN = kNoProcess;
|
||||
|
||||
while (GetNextProcess(&process) == noErr)
|
||||
{
|
||||
FSSpec fileSpec;
|
||||
pi.processInfoLength = sizeof(ProcessInfoRec);
|
||||
pi.processName = NULL;
|
||||
pi.processAppSpec = &fileSpec;
|
||||
GetProcessInformation(&process, &pi);
|
||||
RNG_RandomUpdate( &pi, sizeof(pi));
|
||||
RNG_RandomUpdate( &fileSpec, sizeof(fileSpec));
|
||||
}
|
||||
}
|
||||
|
||||
#if !TARGET_CARBON
|
||||
/* Heap */
|
||||
{
|
||||
THz zone = LMGetTheZone();
|
||||
RNG_RandomUpdate( &zone, sizeof(zone));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Screen */
|
||||
{
|
||||
GDHandle h = GetMainDevice(); /* GDHandle is **GDevice */
|
||||
RNG_RandomUpdate( *h, sizeof(GDevice));
|
||||
}
|
||||
|
||||
#if !TARGET_CARBON
|
||||
/* Scrap size */
|
||||
{
|
||||
SInt32 scrapSize = LMGetScrapSize();
|
||||
RNG_RandomUpdate( &scrapSize, sizeof(scrapSize));
|
||||
}
|
||||
/* Scrap count */
|
||||
{
|
||||
SInt16 scrapCount = LMGetScrapCount();
|
||||
RNG_RandomUpdate( &scrapCount, sizeof(scrapCount));
|
||||
}
|
||||
#else
|
||||
{
|
||||
ScrapRef scrap;
|
||||
if (GetCurrentScrap(&scrap) == noErr) {
|
||||
UInt32 flavorCount;
|
||||
if (GetScrapFlavorCount(scrap, &flavorCount) == noErr) {
|
||||
ScrapFlavorInfo* flavorInfo = (ScrapFlavorInfo*) malloc(flavorCount * sizeof(ScrapFlavorInfo));
|
||||
if (flavorInfo != NULL) {
|
||||
if (GetScrapFlavorInfoList(scrap, &flavorCount, flavorInfo) == noErr) {
|
||||
UInt32 i;
|
||||
RNG_RandomUpdate(&flavorCount, sizeof(flavorCount));
|
||||
for (i = 0; i < flavorCount; ++i) {
|
||||
Size flavorSize;
|
||||
if (GetScrapFlavorSize(scrap, flavorInfo[i].flavorType, &flavorSize) == noErr)
|
||||
RNG_RandomUpdate(&flavorSize, sizeof(flavorSize));
|
||||
}
|
||||
}
|
||||
free(flavorInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* File stuff, last modified, etc. */
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
GetVolParmsInfoBuffer volInfo;
|
||||
pb.ioParam.ioVRefNum = 0;
|
||||
pb.ioParam.ioNamePtr = nil;
|
||||
pb.ioParam.ioBuffer = (Ptr) &volInfo;
|
||||
pb.ioParam.ioReqCount = sizeof(volInfo);
|
||||
PBHGetVolParmsSync(&pb);
|
||||
RNG_RandomUpdate( &volInfo, sizeof(volInfo));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* Event queue */
|
||||
{
|
||||
EvQElPtr eventQ;
|
||||
for (eventQ = (EvQElPtr) LMGetEventQueue()->qHead;
|
||||
eventQ;
|
||||
eventQ = (EvQElPtr)eventQ->qLink)
|
||||
RNG_RandomUpdate( &eventQ->evtQWhat, sizeof(EventRecord));
|
||||
}
|
||||
#endif
|
||||
FE_ReadScreen();
|
||||
RNG_FileForRNG(NULL);
|
||||
}
|
||||
|
||||
void FE_ReadScreen()
|
||||
{
|
||||
UInt16 coords[4];
|
||||
PixMapHandle pmap;
|
||||
GDHandle gh;
|
||||
UInt16 screenHeight;
|
||||
UInt16 screenWidth; /* just what they say */
|
||||
UInt32 bytesToRead; /* number of bytes we're giving */
|
||||
UInt32 offset; /* offset into the graphics buffer */
|
||||
UInt16 rowBytes;
|
||||
UInt32 rowsToRead;
|
||||
float bytesPerPixel; /* dependent on buffer depth */
|
||||
Ptr p; /* temporary */
|
||||
UInt16 x, y, w, h;
|
||||
|
||||
gh = LMGetMainDevice();
|
||||
if ( !gh )
|
||||
return;
|
||||
pmap = (**gh).gdPMap;
|
||||
if ( !pmap )
|
||||
return;
|
||||
|
||||
RNG_GenerateGlobalRandomBytes( coords, sizeof( coords ) );
|
||||
|
||||
/* make x and y inside the screen rect */
|
||||
screenHeight = (**pmap).bounds.bottom - (**pmap).bounds.top;
|
||||
screenWidth = (**pmap).bounds.right - (**pmap).bounds.left;
|
||||
x = coords[0] % screenWidth;
|
||||
y = coords[1] % screenHeight;
|
||||
w = ( coords[2] & 0x7F ) | 0x40; /* Make sure that w is in the range 64..128 */
|
||||
h = ( coords[3] & 0x7F ) | 0x40; /* same for h */
|
||||
|
||||
bytesPerPixel = (**pmap).pixelSize / 8;
|
||||
rowBytes = (**pmap).rowBytes & 0x7FFF;
|
||||
|
||||
/* starting address */
|
||||
offset = ( rowBytes * y ) + (UInt32)( (float)x * bytesPerPixel );
|
||||
|
||||
/* don't read past the end of the pixmap's rowbytes */
|
||||
bytesToRead = PR_MIN( (UInt32)( w * bytesPerPixel ),
|
||||
(UInt32)( rowBytes - ( x * bytesPerPixel ) ) );
|
||||
|
||||
/* don't read past the end of the graphics device pixmap */
|
||||
rowsToRead = PR_MIN( h,
|
||||
( screenHeight - y ) );
|
||||
|
||||
p = GetPixBaseAddr( pmap ) + offset;
|
||||
|
||||
while ( rowsToRead-- )
|
||||
{
|
||||
RNG_RandomUpdate( p, bytesToRead );
|
||||
p += rowBytes;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
146
mozilla/security/nss/lib/freebl/manifest.mn
Normal file
@@ -0,0 +1,146 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
# Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = nss
|
||||
|
||||
ifndef FREEBL_RECURSIVE_BUILD
|
||||
LIBRARY_NAME = freebl
|
||||
else
|
||||
ifdef USE_PURE_32
|
||||
CORE_DEPTH = ../../../..
|
||||
LIBRARY_NAME = freebl_pure32
|
||||
else
|
||||
LIBRARY_NAME = freebl_hybrid
|
||||
endif
|
||||
endif
|
||||
|
||||
# same version as rest of freebl
|
||||
LIBRARY_VERSION = _3
|
||||
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
|
||||
|
||||
REQUIRES =
|
||||
|
||||
EXPORTS = \
|
||||
blapi.h \
|
||||
blapit.h \
|
||||
secrng.h \
|
||||
shsign.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
secmpi.h \
|
||||
ec.h \
|
||||
$(NULL)
|
||||
|
||||
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
|
||||
MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c
|
||||
|
||||
ifdef MOZILLA_BSAFE_BUILD
|
||||
CSRCS = \
|
||||
fblstdlib.c \
|
||||
sha_fast.c \
|
||||
md2.c \
|
||||
md5.c \
|
||||
blapi_bsf.c \
|
||||
$(MPI_SRCS) \
|
||||
dh.c \
|
||||
$(NULL)
|
||||
else
|
||||
CSRCS = \
|
||||
ldvector.c \
|
||||
prng_fips1861.c \
|
||||
sysrand.c \
|
||||
sha_fast.c \
|
||||
md2.c \
|
||||
md5.c \
|
||||
sha512.c \
|
||||
alg2268.c \
|
||||
arcfour.c \
|
||||
arcfive.c \
|
||||
desblapi.c \
|
||||
des.c \
|
||||
rijndael.c \
|
||||
aeskeywrap.c \
|
||||
dh.c \
|
||||
ec.c \
|
||||
GFp_ecl.c \
|
||||
GF2m_ecl.c \
|
||||
pqg.c \
|
||||
dsa.c \
|
||||
rsa.c \
|
||||
shvfy.c \
|
||||
$(MPI_SRCS) \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ALL_CSRCS := $(CSRCS)
|
||||
|
||||
ALL_HDRS = \
|
||||
blapi.h \
|
||||
blapit.h \
|
||||
des.h \
|
||||
ec.h \
|
||||
GFp_ecl.h \
|
||||
GF2m_ecl.h \
|
||||
loader.h \
|
||||
rijndael.h \
|
||||
secmpi.h \
|
||||
sha.h \
|
||||
sha_fast.h \
|
||||
shsign.h \
|
||||
vis_proto.h \
|
||||
$(NULL)
|
||||
|
||||
ifdef AES_GEN_TBL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES
|
||||
else
|
||||
ifdef AES_GEN_TBL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO
|
||||
else
|
||||
ifdef AES_GEN_VAL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES
|
||||
else
|
||||
ifdef AES_GEN_VAL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES_MACRO
|
||||
else
|
||||
DEFINES += -DRIJNDAEL_INCLUDE_TABLES
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
39
mozilla/security/nss/lib/freebl/mapfile.Solaris
Normal file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
libfreebl_3.so {
|
||||
global:
|
||||
FREEBL_GetVector;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
import sys
|
||||
import cgi
|
||||
import time
|
||||
import re
|
||||
|
||||
from pysqlite2 import dbapi2 as sqlite
|
||||
|
||||
print "Content-type: text/plain\n\n"
|
||||
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
# incoming query string has the following parameters:
|
||||
# user=name
|
||||
# (REQUIRED) user that made this annotation
|
||||
# tbox=foopy
|
||||
# (REQUIRED) name of the tinderbox to annotate
|
||||
# data=string
|
||||
# annotation to record
|
||||
# time=seconds
|
||||
# time since the epoch in GMT of this test result; if ommitted, current time at time of script run is used
|
||||
|
||||
tbox = form.getfirst("tbox")
|
||||
user = form.getfirst("user")
|
||||
data = form.getfirst("data")
|
||||
timeval = form.getfirst("time")
|
||||
if timeval is None:
|
||||
timeval = int(time.time())
|
||||
|
||||
if (user is None) or (tbox is None) or (data is None):
|
||||
print "Bad args"
|
||||
sys.exit()
|
||||
|
||||
if re.match(r"[^A-Za-z0-9]", tbox):
|
||||
print "Bad tbox name"
|
||||
sys.exit()
|
||||
|
||||
db = sqlite.connect("db/" + tbox + ".sqlite")
|
||||
|
||||
try:
|
||||
db.execute("CREATE TABLE test_results (test_name STRING, test_time INTEGER, test_value FLOAT, test_data BLOB);")
|
||||
db.execute("CREATE TABLE annotations (anno_user STRING, anno_time INTEGER, anno_string STRING);")
|
||||
db.execute("CREATE INDEX test_name_idx ON test_results.test_name")
|
||||
db.execute("CREATE INDEX test_time_idx ON test_results.test_time")
|
||||
db.execute("CREATE INDEX anno_time_idx ON annotations.anno_time")
|
||||
except:
|
||||
pass
|
||||
|
||||
db.execute("INSERT INTO annotations VALUES (?,?,?)", (user, timeval, data))
|
||||
|
||||
db.commit()
|
||||
|
||||
print "Inserted."
|
||||
|
||||
sys.exit()
|
||||
@@ -1,59 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# bonsaibouncer
|
||||
#
|
||||
# Bounce a request to bonsai.mozilla.org, getting around silly
|
||||
# cross-domain XMLHTTPRequest deficiencies.
|
||||
#
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
import os
|
||||
import sys
|
||||
import cgi
|
||||
import gzip
|
||||
import urllib
|
||||
from urllib import quote
|
||||
|
||||
import cStringIO
|
||||
|
||||
bonsai = "http://bonsai.mozilla.org/cvsquery.cgi";
|
||||
|
||||
def main():
|
||||
#doGzip = 0
|
||||
#try:
|
||||
# if string.find(os.environ["HTTP_ACCEPT_ENCODING"], "gzip") != -1:
|
||||
# doGzip = 1
|
||||
#except:
|
||||
# pass
|
||||
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
treeid = form.getfirst("treeid")
|
||||
module = form.getfirst("module")
|
||||
branch = form.getfirst("branch")
|
||||
mindate = form.getfirst("mindate")
|
||||
maxdate = form.getfirst("maxdate")
|
||||
xml_nofiles = form.getfirst("xml_nofiles")
|
||||
|
||||
if not treeid or not module or not branch or not mindate or not maxdate:
|
||||
print "Content-type: text/plain\n\n"
|
||||
print "ERROR"
|
||||
return
|
||||
|
||||
url = bonsai + "?" + "branchtype=match&sortby=Date&date=explicit&cvsroot=%2Fcvsroot&xml=1"
|
||||
url += "&treeid=%s&module=%s&branch=%s&mindate=%s&maxdate=%s" % (quote(treeid), quote(module), quote(branch), quote(mindate), quote(maxdate))
|
||||
|
||||
if (xml_nofiles):
|
||||
url += "&xml_nofiles=1"
|
||||
|
||||
urlstream = urllib.urlopen(url)
|
||||
|
||||
sys.stdout.write("Content-type: text/xml\n\n")
|
||||
|
||||
for s in urlstream:
|
||||
sys.stdout.write(s)
|
||||
|
||||
urlstream.close()
|
||||
|
||||
main()
|
||||
@@ -1,216 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
import sys
|
||||
import cgi
|
||||
import time
|
||||
import re
|
||||
|
||||
from graphsdb import db
|
||||
|
||||
#if var is a valid number returns a value other than None
|
||||
def checkNumber(var):
|
||||
if var is None:
|
||||
return 1
|
||||
reNumber = re.compile('^[0-9.]*$')
|
||||
return reNumber.match(var)
|
||||
|
||||
#if var is a valid string returns a value other than None
|
||||
def checkString(var):
|
||||
if var is None:
|
||||
return 1
|
||||
reString = re.compile('^[0-9A-Za-z._()\- ]*$')
|
||||
return reString.match(var)
|
||||
|
||||
print "Content-type: text/plain\n\n"
|
||||
link_format = "RETURN:%s:%.2f:%sspst=range&spstart=%d&spend=%d&bpst=cursor&bpstart=%d&bpend=%d&m1tid=%d&m1bl=0&m1avg=0\n"
|
||||
link_str = ""
|
||||
|
||||
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
# incoming query string has the following parameters:
|
||||
# type=discrete|continuous
|
||||
# indicates discrete vs. continuous dataset, defaults to continuous
|
||||
# value=n
|
||||
# (REQUIRED) value to be recorded as the actual test value
|
||||
# tbox=foopy
|
||||
# (REQUIRED) name of the tinderbox reporting the value (or rather, the name that is to be given this set of data)
|
||||
# testname=test
|
||||
# (REQUIRED) the name of this test
|
||||
# data=rawdata
|
||||
# raw data for this test
|
||||
# time=seconds
|
||||
# time since the epoch in GMT of this test result; if ommitted, current time at time of script run is used
|
||||
# date
|
||||
# date that the test was run - this is for discrete graphs
|
||||
# branch=1.8.1,1.8.0 or 1.9.0
|
||||
# name of the branch that the build was generated for
|
||||
# branchid=id
|
||||
# date of the build
|
||||
# http://wiki.mozilla.org/MozillaQualityAssurance:Build_Ids
|
||||
|
||||
#takes as input a file for parsing in csv with the format:
|
||||
# value,testname,tbox,time,data,branch,branchid,type,data
|
||||
|
||||
# Create the DB schema if it doesn't already exist
|
||||
# XXX can pull out dataset_info.machine and dataset_info.{test,test_type} into two separate tables,
|
||||
# if we need to.
|
||||
|
||||
# value,testname,tbox,time,data,branch,branchid,type,data
|
||||
|
||||
fields = ["value", "testname", "tbox", "timeval", "date", "branch", "branchid", "type", "data"]
|
||||
strFields = ["type", "data", "tbox", "testname", "branch", "branchid"]
|
||||
numFields = ["date", "timeval", "value"]
|
||||
d_ids = []
|
||||
all_ids = []
|
||||
all_types = []
|
||||
if form.has_key("filename"):
|
||||
val = form["filename"]
|
||||
if val.file:
|
||||
print "found a file"
|
||||
for line in val.file:
|
||||
line = line.rstrip("\n\r")
|
||||
contents = line.split(',')
|
||||
#clear any previous content in the fields variables - stops reuse of data over lines
|
||||
for field in fields:
|
||||
globals()[field] = ''
|
||||
if len(contents) < 7:
|
||||
print "Incompatable file format"
|
||||
sys.exit(500)
|
||||
for field, content in zip(fields, contents):
|
||||
globals()[field] = content
|
||||
for strField in strFields:
|
||||
if not globals().has_key(strField):
|
||||
continue
|
||||
if not checkString(globals()[strField]):
|
||||
print "Invalid string arg: ", strField, " '" + globals()[strField] + "'"
|
||||
sys.exit(500)
|
||||
for numField in numFields:
|
||||
if not globals().has_key(numField):
|
||||
continue
|
||||
if not checkNumber(globals()[numField]):
|
||||
print "Invalid string arg: ", numField, " '" + globals()[numField] + "'"
|
||||
sys.exit(500)
|
||||
|
||||
#do some checks to ensure that we are enforcing the requirement rules of the script
|
||||
if (not type):
|
||||
type = "continuous"
|
||||
|
||||
if (not timeval):
|
||||
timeval = int(time.time())
|
||||
|
||||
if (type == "discrete") and (not date):
|
||||
print "Bad args, need a valid date"
|
||||
sys.exit(500)
|
||||
|
||||
if (not value) or (not tbox) or (not testname):
|
||||
print "Bad args"
|
||||
sys.exit(500)
|
||||
|
||||
|
||||
# figure out our dataset id
|
||||
setid = -1
|
||||
|
||||
# Not a big fan of this while loop. If something goes wrong with the select it will insert until the script times out.
|
||||
while setid == -1:
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT id FROM dataset_info WHERE type <=> ? AND machine <=> ? AND test <=> ? AND test_type <=> ? AND extra_data <=> ? AND branch <=> ? AND date <=> ? limit 1",
|
||||
(type, tbox, testname, "perf", "branch="+branch, branch, date))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
|
||||
if len(res) == 0:
|
||||
db.execute("INSERT INTO dataset_info (type, machine, test, test_type, extra_data, branch, date) VALUES (?,?,?,?,?,?,?)",
|
||||
(type, tbox, testname, "perf", "branch="+branch, branch, date))
|
||||
else:
|
||||
setid = res[0][0]
|
||||
|
||||
db.execute("INSERT INTO dataset_values (dataset_id, time, value) VALUES (?,?,?)", (setid, timeval, value))
|
||||
db.execute("INSERT INTO dataset_branchinfo (dataset_id, time, branchid) VALUES (?,?,?)", (setid, timeval, branchid))
|
||||
if data and data != "":
|
||||
db.execute("INSERT INTO dataset_extra_data (dataset_id, time, data) VALUES (?,?,?)", (setid, timeval, data))
|
||||
|
||||
if (type == "discrete"):
|
||||
if not setid in d_ids:
|
||||
d_ids.append(setid)
|
||||
if not setid in all_ids:
|
||||
all_ids.append(setid)
|
||||
all_types.append(type)
|
||||
|
||||
for setid, type in zip(all_ids, all_types):
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT MIN(time), MAX(time), test FROM dataset_values, dataset_info WHERE dataset_id = ? and id = dataset_id GROUP BY test", (setid,))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
tstart = res[0][0]
|
||||
tend = res[0][1]
|
||||
testname = res[0][2]
|
||||
if type == "discrete":
|
||||
link_str += (link_format % (testname, float(-1), "dgraph.html#name=" + testname + "&", tstart, tend, tstart, tend, setid,))
|
||||
else:
|
||||
tstart = 0
|
||||
link_str += (link_format % (testname, float(-1), "graph.html#",tstart, tend, tstart, tend, setid,))
|
||||
|
||||
#this code auto-adds a set of continuous data for each series of discrete data sets - creating an overview of the data
|
||||
# generated by a given test (matched by machine, test, test_type, extra_data and branch)
|
||||
for setid in d_ids:
|
||||
cur = db.cursor()
|
||||
#throw out the largest value and take the average of the rest
|
||||
cur.execute("SELECT AVG(value) FROM dataset_values WHERE dataset_id = ? and value != (SELECT MAX(value) from dataset_values where dataset_id = ?)", (setid, setid,))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
avg = res[0][0]
|
||||
if avg is not None:
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT machine, test, test_type, extra_data, branch, date FROM dataset_info WHERE id = ?", (setid,))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
tbox = res[0][0]
|
||||
testname = res[0][1]
|
||||
test_type = res[0][2]
|
||||
extra_data = res[0][3]
|
||||
branch = str(res[0][4])
|
||||
timeval = res[0][5]
|
||||
date = ''
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT branchid FROM dataset_branchinfo WHERE dataset_id = ?", (setid,))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
branchid = res[0][0]
|
||||
dsetid = -1
|
||||
while dsetid == -1 :
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT id from dataset_info where type = ? AND machine <=> ? AND test = ? AND test_type = ? AND extra_data = ? AND branch <=> ? AND date <=> ? limit 1",
|
||||
("continuous", tbox, testname+"_avg", "perf", "branch="+branch, branch, date))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
if len(res) == 0:
|
||||
db.execute("INSERT INTO dataset_info (type, machine, test, test_type, extra_data, branch, date) VALUES (?,?,?,?,?,?,?)",
|
||||
("continuous", tbox, testname+"_avg", "perf", "branch="+branch, branch, date))
|
||||
else:
|
||||
dsetid = res[0][0]
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT * FROM dataset_values WHERE dataset_id=? AND time <=> ? limit 1", (dsetid, timeval))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
if len(res) == 0:
|
||||
db.execute("INSERT INTO dataset_values (dataset_id, time, value) VALUES (?,?,?)", (dsetid, timeval, avg))
|
||||
db.execute("INSERT INTO dataset_branchinfo (dataset_id, time, branchid) VALUES (?,?,?)", (dsetid, timeval, branchid))
|
||||
else:
|
||||
db.execute("UPDATE dataset_values SET value=? WHERE dataset_id=? AND time <=> ?", (avg, dsetid, timeval))
|
||||
db.execute("UPDATE dataset_branchinfo SET branchid=? WHERE dataset_id=? AND time <=> ?", (branchid, dsetid, timeval))
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT MIN(time), MAX(time) FROM dataset_values WHERE dataset_id = ?", (dsetid,))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
tstart = 0
|
||||
tend = res[0][1]
|
||||
link_str += (link_format % (testname, float(avg), "graph.html#", tstart, tend, tstart, tend, dsetid,))
|
||||
|
||||
db.commit()
|
||||
print "Inserted."
|
||||
print link_str
|
||||
|
||||
sys.exit()
|
||||
@@ -1,175 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
import sys
|
||||
import cgi
|
||||
import time
|
||||
import re
|
||||
|
||||
from graphsdb import db
|
||||
|
||||
#if var is a valid number returns a value other than None
|
||||
def checkNumber(var):
|
||||
if var is None:
|
||||
return 1
|
||||
reNumber = re.compile('^[0-9.]*$')
|
||||
return reNumber.match(var)
|
||||
|
||||
#if var is a valid string returns a value other than None
|
||||
def checkString(var):
|
||||
if var is None:
|
||||
return 1
|
||||
reString = re.compile('^[0-9A-Za-z._()\- ]*$')
|
||||
return reString.match(var)
|
||||
|
||||
print "Content-type: text/plain\n\n"
|
||||
link_format = "RETURN:%.2f:%sspst=range&spstart=%d&spend=%d&bpst=cursor&bpstart=%d&bpend=%d&m1tid=%d&m1bl=0&m1avg=0\n"
|
||||
link_str = ""
|
||||
|
||||
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
# incoming query string has the following parameters:
|
||||
# type=discrete|continuous
|
||||
# indicates discrete vs. continuous dataset, defaults to continuous
|
||||
# value=n
|
||||
# (REQUIRED) value to be recorded as the actual test value
|
||||
# tbox=foopy
|
||||
# (REQUIRED) name of the tinderbox reporting the value (or rather, the name that is to be given this set of data)
|
||||
# testname=test
|
||||
# (REQUIRED) the name of this test
|
||||
# data=rawdata
|
||||
# raw data for this test
|
||||
# time=seconds
|
||||
# time since the epoch in GMT of this test result; if ommitted, current time at time of script run is used
|
||||
# date
|
||||
# date that the test was run - this is for discrete graphs
|
||||
# branch=1.8.1,1.8.0 or 1.9.0
|
||||
# name of the branch that the build was generated for
|
||||
# branchid=id
|
||||
# date of the build
|
||||
# http://wiki.mozilla.org/MozillaQualityAssurance:Build_Ids
|
||||
|
||||
#make sure that we are getting clean data from the user
|
||||
for strField in ["type", "data", "tbox", "testname", "branch", "branchid"]:
|
||||
val = form.getfirst(strField)
|
||||
if not checkString(val):
|
||||
print "Invalid string arg: ", strField, " '" + val + "'"
|
||||
sys.exit(500)
|
||||
globals()[strField] = val
|
||||
|
||||
for numField in ["date", "time", "value"]:
|
||||
val = form.getfirst(numField)
|
||||
if numField == "time":
|
||||
numField = "timeval"
|
||||
if not checkNumber(val):
|
||||
print "Invalid num arg: ", numField, " '" + val + "'"
|
||||
sys.exit(500)
|
||||
globals()[numField] = val
|
||||
|
||||
#do some checks to ensure that we are enforcing the requirement rules of the script
|
||||
if (not type):
|
||||
type = "continuous"
|
||||
|
||||
if (not timeval):
|
||||
timeval = int(time.time())
|
||||
|
||||
if (type == "discrete") and (not date):
|
||||
print "Bad args, need a valid date"
|
||||
sys.exit(500)
|
||||
|
||||
if (not value) or (not tbox) or (not testname):
|
||||
print "Bad args"
|
||||
sys.exit(500)
|
||||
|
||||
|
||||
# Create the DB schema if it doesn't already exist
|
||||
# XXX can pull out dataset_info.machine and dataset_info.{test,test_type} into two separate tables,
|
||||
# if we need to.
|
||||
|
||||
# figure out our dataset id
|
||||
setid = -1
|
||||
|
||||
while setid == -1:
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT id FROM dataset_info WHERE type <=> ? AND machine <=> ? AND test <=> ? AND test_type <=> ? AND extra_data=? AND branch <=> ? AND date <=> ?",
|
||||
(type, tbox, testname, "perf", "branch="+branch, branch, date))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
|
||||
if len(res) == 0:
|
||||
db.execute("INSERT INTO dataset_info (type, machine, test, test_type, extra_data, branch, date) VALUES (?,?,?,?,?,?,?)",
|
||||
(type, tbox, testname, "perf", "branch="+branch, branch, date))
|
||||
else:
|
||||
setid = res[0][0]
|
||||
|
||||
db.execute("INSERT INTO dataset_values (dataset_id, time, value) VALUES (?,?,?)", (setid, timeval, value))
|
||||
db.execute("INSERT INTO dataset_branchinfo (dataset_id, time, branchid) VALUES (?,?,?)", (setid, timeval, branchid))
|
||||
if data and data != "":
|
||||
db.execute("INSERT INTO dataset_extra_data (dataset_id, time, data) VALUES (?,?,?)", (setid, timeval, data))
|
||||
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT MIN(time), MAX(time) FROM dataset_values WHERE dataset_id = ?", (setid,))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
tstart = res[0][0]
|
||||
tend = res[0][1]
|
||||
if type == "discrete":
|
||||
link_str += (link_format % (float(-1), "dgraph.html#name=" + testname + "&", tstart, tend, tstart, tend, setid,))
|
||||
else:
|
||||
tstart = 0
|
||||
link_str += (link_format % (float(-1), "graph.html#",tstart, tend, tstart, tend, setid,))
|
||||
|
||||
|
||||
#this code auto-adds a set of continuous data for each series of discrete data sets - creating an overview of the data
|
||||
# generated by a given test (matched by machine, test, test_type, extra_data and branch)
|
||||
# it is not terribly efficient as it updates the tracking number on the continuous set each time a point is added
|
||||
# to the discrete set. If the efficiency becomes a concern we can re-examine the code - for now it is a good
|
||||
# solution for generating the secondary, tracking data.
|
||||
if type == "discrete" :
|
||||
timeval = date
|
||||
date = ''
|
||||
cur = db.cursor()
|
||||
#throw out the largest value and take the average of the rest
|
||||
cur.execute("SELECT AVG(value) FROM dataset_values WHERE dataset_id = ? and value != (SELECT MAX(value) from dataset_values where dataset_id = ?)", (setid, setid,))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
avg = res[0][0]
|
||||
if avg is not None:
|
||||
|
||||
setid = -1
|
||||
while setid == -1 :
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT id from dataset_info where type <=> ? AND machine <=> ? AND test <=> ? AND test_type <=> ? AND extra_data <=> ? AND branch <=> ? AND date <=> ?",
|
||||
("continuous", tbox, testname+"_avg", "perf", "branch="+branch, branch, date))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
if len(res) == 0:
|
||||
db.execute("INSERT INTO dataset_info (type, machine, test, test_type, extra_data, branch, date) VALUES (?,?,?,?,?,?,?)",
|
||||
("continuous", tbox, testname+"_avg", "perf", "branch="+branch, branch, date))
|
||||
else:
|
||||
setid = res[0][0]
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT * FROM dataset_values WHERE dataset_id=? AND time <=> ?", (setid, timeval))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
if len(res) == 0:
|
||||
db.execute("INSERT INTO dataset_values (dataset_id, time, value) VALUES (?,?,?)", (setid, timeval, avg))
|
||||
db.execute("INSERT INTO dataset_branchinfo (dataset_id, time, branchid) VALUES (?,?,?)", (setid, timeval, branchid))
|
||||
else:
|
||||
db.execute("UPDATE dataset_values SET value=? WHERE dataset_id=? AND time <=> ?", (avg, setid, timeval))
|
||||
db.execute("UPDATE dataset_branchinfo SET branchid=? WHERE dataset_id=? AND time <=> ?", (branchid, setid, timeval))
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT MIN(time), MAX(time) FROM dataset_values WHERE dataset_id = ?", (setid,))
|
||||
res = cur.fetchall()
|
||||
cur.close()
|
||||
tstart = 0
|
||||
tend = res[0][1]
|
||||
link_str += (link_format % (float(avg), "graph.html#", tstart, tend, tstart, tend, setid,))
|
||||
|
||||
db.commit()
|
||||
print "Inserted."
|
||||
print link_str
|
||||
|
||||
sys.exit()
|
||||
@@ -1,20 +0,0 @@
|
||||
import MySQLdb
|
||||
from MySQLdb import *
|
||||
|
||||
|
||||
|
||||
|
||||
class GraphConnection(MySQLdb.connections.Connection):
|
||||
def execute(self,query, args):
|
||||
cur = self.cursor()
|
||||
result = cur.execute(query,args)
|
||||
cur.close()
|
||||
return result
|
||||
class GraphsCursor(MySQLdb.cursors.Cursor):
|
||||
def execute(self, query, args=None):
|
||||
query = query.replace('?','%s')
|
||||
return MySQLdb.cursors.Cursor.execute(self, query, args)
|
||||
|
||||
def connect(*args,**kwargs):
|
||||
kwargs['cursorclass'] = GraphsCursor
|
||||
return GraphConnection(*args,**kwargs)
|
||||
@@ -1,105 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Perf-o-matic-too</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="js/graph.css"></link>
|
||||
|
||||
<!-- MochiKit -->
|
||||
<script type="text/javascript" src="js/mochikit/MochiKit.js"></script>
|
||||
|
||||
<!-- YUI -->
|
||||
<script type="text/javascript" src="js/yui/yahoo.js"></script>
|
||||
<script type="text/javascript" src="js/yui/dom.js"></script>
|
||||
<script type="text/javascript" src="js/yui/event.js"></script>
|
||||
<script type="text/javascript" src="js/yui/animation.js"></script>
|
||||
<script type="text/javascript" src="js/yui/container.js"></script>
|
||||
|
||||
<!-- Core -->
|
||||
<script type="text/javascript" src="js/TinderboxData.js"></script>
|
||||
<script type="text/javascript" src="js/DataSet.js"></script>
|
||||
<script type="text/javascript" src="js/GraphCanvas.js"></script>
|
||||
|
||||
<script type="text/javascript" src="js/dGraphFormModule.js"></script>
|
||||
<script type="text/javascript" src="js/graph.js"></script>
|
||||
<script type="text/javascript" src="js/ResizeGraph.js"></script>
|
||||
|
||||
<!-- BonsaiService needs e4x -->
|
||||
<script type="text/javascript; e4x=1" src="js/BonsaiService.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="loadingDone(DISCRETE_GRAPH)">
|
||||
<!--<h1>Graph</h1>-->
|
||||
|
||||
<!-- Take your damn divs and floats and clears and shove 'em! -->
|
||||
|
||||
<div style="width: 710px; height:20px; margin-left:10px ">
|
||||
<span id="loading" class="loading"></span>
|
||||
</div>
|
||||
<form action="javascript:;">
|
||||
<table class="graphconfig-no" width="100%">
|
||||
|
||||
<tr style="vertical-align: top">
|
||||
<td class="graphconfig-list">
|
||||
<div id="graphforms"></div>
|
||||
|
||||
</td>
|
||||
<td class="graphconfig-test-list">
|
||||
<div id="graphforms-test-list"></div>
|
||||
</td>
|
||||
|
||||
<td class="dgraphconfig">
|
||||
<!--
|
||||
<div id="baseline">
|
||||
<span>Use </span><select id="baselineDropdown"><option value="0">nothing</option></select><span> as a baseline</span><br>
|
||||
</div>
|
||||
-->
|
||||
<br>
|
||||
|
||||
<div id="formend">
|
||||
<input id="graphbutton" type="submit" onclick="onGraph()" value="Graph It!">
|
||||
<!-- <label for="baseline">No baseline</label><input type="radio" name="baseline" checked onclick="onNoBaseLineClick()"> -->
|
||||
</br> </br>
|
||||
<div><a id="linktothis" href="dgraph.html">Link to this graph</a> </div>
|
||||
</br>
|
||||
<div><a id="dumptocsv" href="dumpdata.cgi">Dump to csv</a> </div>
|
||||
</div>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<!-- small graph -->
|
||||
<div style="width: 900px; height:20px">
|
||||
<center><span id="status" class="status"></span></center>
|
||||
</div>
|
||||
|
||||
<div id="container" style="width: 100%">
|
||||
|
||||
<!-- these are absolute size, so we wrap them in a div that can overflow -->
|
||||
<div id="graph-container" style="width: 900px; margin:auto">
|
||||
<div id="smallgraph-labels-x" style="position: relative; left: 51px; margin-left: 1px; margin-right: 1px; height: 30px; width: 700px"></div>
|
||||
<div id="smallgraph-labels-y" style="position: relative; left: 0px; top: 0px; float: left; height: 76px; width: 50px;"></div>
|
||||
<canvas style="clear: left; border: 1px solid #888; padding-top: 1px;" id="smallgraph" height="75" width="650"></canvas>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div id="graph-labels-y" style="position: relative; left: 0px; top: 0px; float: left; margin-top: 1px; margin-bottom: 1px; height: 300px; width: 50px;"></div>
|
||||
<canvas style="clear: left; border: 1px solid #888;" id="graph" height="300" width="650"></canvas>
|
||||
<div id="graph-labels-x" style="position: relative; left: 50px; margin-left: 1px; margin-right: 1px; height: 50px; width: 700px"></div>
|
||||
</div>
|
||||
<div id="graph-label-container" style="float:left;margin-top:30px;">
|
||||
<span id="graph-label-list" class="graph-label-list-member" align="left"></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
ResizableBigGraph = new ResizeGraph();
|
||||
ResizableBigGraph.init('graph');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
import os
|
||||
import sys
|
||||
import cgi
|
||||
import time
|
||||
import re
|
||||
import gzip
|
||||
import minjson as json
|
||||
|
||||
import cStringIO
|
||||
|
||||
from graphsdb import db
|
||||
|
||||
#
|
||||
# returns a plain text file containing the information for a given dataset in two csv tables
|
||||
# the first table containing the dataset info (branch, date, etc)
|
||||
# the second table containing the databaset values
|
||||
#
|
||||
# incoming query string:
|
||||
#
|
||||
# setid=number
|
||||
# Where number is a valid setid
|
||||
#
|
||||
# starttime=tval
|
||||
# Start time to return results from, in seconds since GMT epoch
|
||||
# endtime=tval
|
||||
# End time, in seconds since GMT epoch
|
||||
|
||||
def doError(errCode):
|
||||
errString = "unknown error"
|
||||
if errCode == -1:
|
||||
errString = "bad tinderbox"
|
||||
elif errCode == -2:
|
||||
errString = "bad test name"
|
||||
print "{ resultcode: " + str(errCode) + ", error: '" + errString + "' }"
|
||||
|
||||
def esc(val):
|
||||
delim = '"'
|
||||
val = delim + str(val).replace(delim, delim + delim) + delim
|
||||
return val
|
||||
|
||||
def dumpData(fo, setid, starttime, endtime):
|
||||
s1 = ""
|
||||
s2 = ""
|
||||
if starttime:
|
||||
s1 = " AND time >= B." + starttime
|
||||
if endtime:
|
||||
s2 = " AND time <= B." + endtime
|
||||
|
||||
cur = db.cursor()
|
||||
setid = ",".join(setid)
|
||||
fo.write("dataset,machine,branch,test,date\n")
|
||||
cur.execute("SELECT B.id, B.machine, B.branch, B.test, B.date FROM dataset_info as B WHERE id IN (%s) %s %s ORDER BY id" % (setid, s1, s2,))
|
||||
for row in cur:
|
||||
fo.write ('%s,%s,%s,%s,%s\n' % (esc(row[0]), esc(row[1]), esc(row[2]), esc(row[3]), esc(row[4])))
|
||||
fo.write("dataset,time,value,buildid,data\n")
|
||||
cur.close()
|
||||
cur = db.cursor()
|
||||
#cur.execute("SELECT dataset_id, time, value, branchid, data from ((dataset_values NATURAL JOIN dataset_branchinfo) NATURAL JOIN dataset_extra_data) WHERE dataset_id IN (%s) %s %s ORDER BY dataset_id, time" % (setid, s1, s2,))
|
||||
cur.execute("SELECT dataset_values.dataset_id, dataset_values.time, dataset_values.value, dataset_branchinfo.branchid, dataset_extra_data.data FROM dataset_values LEFT JOIN dataset_branchinfo ON dataset_values.dataset_id = dataset_branchinfo.dataset_id AND dataset_values.time = dataset_branchinfo.time LEFT JOIN dataset_extra_data ON dataset_values.dataset_id = dataset_extra_data.dataset_id AND dataset_values.time = dataset_extra_data.time WHERE dataset_values.dataset_id IN (%s) %s %s ORDER BY dataset_values.dataset_id, dataset_values.time" % (setid, s1, s2))
|
||||
for row in cur:
|
||||
fo.write ('%s,%s,%s,%s,%s\n' % (esc(row[0]), esc(row[1]), esc(row[2]), esc(row[3]), esc(row[4])))
|
||||
cur.close()
|
||||
|
||||
#if var is a number returns a value other than None
|
||||
def checkNumber(var):
|
||||
if var is None:
|
||||
return 1
|
||||
reNumber = re.compile('^[0-9.]*$')
|
||||
return reNumber.match(var)
|
||||
|
||||
#if var is a string returns a value other than None
|
||||
def checkString(var):
|
||||
if var is None:
|
||||
return 1
|
||||
reString = re.compile('^[0-9A-Za-z._()\- ]*$')
|
||||
return reString.match(var)
|
||||
|
||||
doGzip = 0
|
||||
try:
|
||||
if "gzip" in os.environ["HTTP_ACCEPT_ENCODING"]:
|
||||
doGzip = 1
|
||||
except:
|
||||
pass
|
||||
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
for numField in ["setid"]:
|
||||
val = form.getlist(numField)
|
||||
for v in val:
|
||||
if not checkNumber(v):
|
||||
print "Invalid string arg: ", numField, " '" + v + "'"
|
||||
sys.exit(500)
|
||||
globals()[numField] = val
|
||||
|
||||
for numField in ["starttime", "endtime"]:
|
||||
val = form.getfirst(numField)
|
||||
if not checkNumber(val):
|
||||
print "Invalid string arg: ", numField, " '" + val + "'"
|
||||
sys.exit(500)
|
||||
globals()[numField] = val
|
||||
|
||||
if not setid:
|
||||
print "Content-Type: text/plain\n"
|
||||
print "No data set selected\n"
|
||||
sys.exit(500)
|
||||
|
||||
zbuf = cStringIO.StringIO()
|
||||
zfile = zbuf
|
||||
if doGzip == 1:
|
||||
zfile = gzip.GzipFile(mode = 'wb', fileobj = zbuf, compresslevel = 9)
|
||||
|
||||
dumpData(zfile, setid, starttime, endtime)
|
||||
|
||||
sys.stdout.write("Content-Type: text/plain\n")
|
||||
if doGzip == 1:
|
||||
zfile.close()
|
||||
sys.stdout.write("Content-Encoding: gzip\n")
|
||||
sys.stdout.write("\n")
|
||||
|
||||
sys.stdout.write(zbuf.getvalue())
|
||||
|
||||
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Perf-o-matic-too</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="js/graph.css"></link>
|
||||
|
||||
<!-- MochiKit -->
|
||||
<script type="text/javascript" src="js/mochikit/MochiKit.js"></script>
|
||||
|
||||
<!-- YUI -->
|
||||
<script type="text/javascript" src="js/yui/yahoo.js"></script>
|
||||
<script type="text/javascript" src="js/yui/dom.js"></script>
|
||||
<script type="text/javascript" src="js/yui/event.js"></script>
|
||||
<script type="text/javascript" src="js/yui/animation.js"></script>
|
||||
<script type="text/javascript" src="js/yui/container.js"></script>
|
||||
|
||||
<!-- Core -->
|
||||
<script type="text/javascript" src="js/TinderboxData.js"></script>
|
||||
<script type="text/javascript" src="js/DataSet.js"></script>
|
||||
<script type="text/javascript" src="js/GraphCanvas.js"></script>
|
||||
|
||||
<script type="text/javascript" src="js/edGraphFormModule.js"></script>
|
||||
<script type="text/javascript" src="js/graph.js"></script>
|
||||
<script type="text/javascript" src="js/ResizeGraph.js"></script>
|
||||
|
||||
<!-- BonsaiService needs e4x -->
|
||||
<script type="text/javascript; e4x=1" src="js/BonsaiService.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="loadingDone(DATA_GRAPH)">
|
||||
<!--<h1>Graph</h1>-->
|
||||
|
||||
<!-- Take your damn divs and floats and clears and shove 'em! -->
|
||||
|
||||
<div style="width: 710px; height:20px; margin-left:10px ">
|
||||
<span id="loading" class="loading"></span>
|
||||
</div>
|
||||
<form action="javascript:;">
|
||||
<table class="graphconfig-no" width="100%">
|
||||
|
||||
<tr style="vertical-align: top">
|
||||
<td class="graphconfig-list">
|
||||
<div id="graphforms"></div>
|
||||
|
||||
</td>
|
||||
<td class="graphconfig-test-list">
|
||||
<div id="graphforms-test-list"></div>
|
||||
</td>
|
||||
|
||||
<td class="dgraphconfig">
|
||||
<!--
|
||||
<div id="baseline">
|
||||
<span>Use </span><select id="baselineDropdown"><option value="0">nothing</option></select><span> as a baseline</span><br>
|
||||
</div>
|
||||
-->
|
||||
<br>
|
||||
|
||||
<div id="formend">
|
||||
<input id="graphbutton" type="submit" onclick="onGraph()" value="Graph It!">
|
||||
<!-- <label for="baseline">No baseline</label><input type="radio" name="baseline" checked onclick="onNoBaseLineClick()"> -->
|
||||
</br> </br>
|
||||
<div><a id="linktothis" href="edgraph.html">Link to this graph</a> </div>
|
||||
</br>
|
||||
<div><a id="dumptocsv" href="dumpdata.cgi">Dump to csv</a> </div>
|
||||
</div>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<!-- small graph -->
|
||||
<div style="width: 900px; height:20px">
|
||||
<center><span id="status" class="status"></span></center>
|
||||
</div>
|
||||
|
||||
<div id="container" style="width: 100%">
|
||||
|
||||
<!-- these are absolute size, so we wrap them in a div that can overflow -->
|
||||
<div id="graph-container" style="width: 900px; margin:auto">
|
||||
<div id="smallgraph-labels-x" style="position: relative; left: 51px; margin-left: 1px; margin-right: 1px; height: 30px; width: 700px"></div>
|
||||
<div id="smallgraph-labels-y" style="position: relative; left: 0px; top: 0px; float: left; height: 76px; width: 50px;"></div>
|
||||
<canvas style="clear: left; border: 1px solid #888; padding-top: 1px;" id="smallgraph" height="75" width="650"></canvas>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div id="graph-labels-y" style="position: relative; left: 0px; top: 0px; float: left; margin-top: 1px; margin-bottom: 1px; height: 300px; width: 50px;"></div>
|
||||
<canvas style="clear: left; border: 1px solid #888;" id="graph" height="300" width="650"></canvas>
|
||||
<div id="graph-labels-x" style="position: relative; left: 50px; margin-left: 1px; margin-right: 1px; height: 50px; width: 700px"></div>
|
||||
</div>
|
||||
<div id="graph-label-container" style="float:left;margin-top:30px;">
|
||||
<span id="graph-label-list" class="graph-label-list-member" align="left"></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
ResizableBigGraph = new ResizeGraph();
|
||||
ResizableBigGraph.init('graph');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
print "Content-type: text/plain\n\n";
|
||||
|
||||
#foreach my $k (keys(%ENV)) {
|
||||
# print "$k => " . $ENV{$k} . "\n";
|
||||
#}
|
||||
|
||||
my $QS = $ENV{"QUERY_STRING"};
|
||||
my %query = ();
|
||||
|
||||
{
|
||||
my @qp = split /\&/,$QS;
|
||||
foreach my $q (@qp) {
|
||||
my @qp1 = split /=/,$q;
|
||||
$query{$qp1[0]} = $qp1[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($query{"setid"})) {
|
||||
my $testid = $query{"setid"};
|
||||
|
||||
print "{ resultcode: 0, results: [";
|
||||
|
||||
srand();
|
||||
|
||||
my $lv = 200 + rand (100);
|
||||
foreach my $k (1 .. 500) {
|
||||
#my $kv = $k;
|
||||
#my $v = $k;
|
||||
my $kv = 1148589000 + ($k*60*20);
|
||||
my $v = $lv;
|
||||
$lv = $lv + (rand(10) - 5);
|
||||
print "$kv, $v, ";
|
||||
}
|
||||
print "] }";
|
||||
} else {
|
||||
print "{ resultcode: 0, results: [
|
||||
{ id: 1, machine: 'tbox1', test: 'test1', test_type: 'perf', extra_data: null },
|
||||
{ id: 4, machine: 'tbox2', test: 'test1', test_type: 'perf', extra_data: null },
|
||||
{ id: 3, machine: 'tbox1', test: 'test3', test_type: 'perf', extra_data: null },
|
||||
{ id: 6, machine: 'tbox3', test: 'test3', test_type: 'perf', extra_data: null },
|
||||
{ id: 2, machine: 'tbox1', test: 'test2', test_type: 'perf', extra_data: null },
|
||||
{ id: 5, machine: 'tbox2', test: 'test2', test_type: 'perf', extra_data: null },
|
||||
] }";
|
||||
}
|
||||
|
||||
@@ -1,276 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
import os
|
||||
import sys
|
||||
import cgi
|
||||
import time
|
||||
import re
|
||||
import gzip
|
||||
import minjson as json
|
||||
|
||||
import cStringIO
|
||||
|
||||
from graphsdb import db
|
||||
#
|
||||
# All objects are returned in the form:
|
||||
# {
|
||||
# resultcode: n,
|
||||
# ...
|
||||
# }
|
||||
#
|
||||
# The ... is dependant on the result type.
|
||||
#
|
||||
# Result codes:
|
||||
# 0 success
|
||||
# -1 bad tinderbox
|
||||
# -2 bad test name
|
||||
#
|
||||
# incoming query string:
|
||||
# tbox=name
|
||||
# tinderbox name
|
||||
#
|
||||
# If only tbox specified, returns array of test names for that tinderbox in data
|
||||
# If invalid tbox specified, returns error -1
|
||||
#
|
||||
# test=testname
|
||||
# test name
|
||||
#
|
||||
# Returns results for that test in .results, in array of [time0, value0, time1, value1, ...]
|
||||
# Also returns .annotations for that dataset, in array of [time0, string0, time1, string1, ...]
|
||||
#
|
||||
# raw=1
|
||||
# Same as full results, but includes raw data for test in .rawdata, in form [time0, rawdata0, ...]
|
||||
#
|
||||
# starttime=tval
|
||||
# Start time to return results from, in seconds since GMT epoch
|
||||
# endtime=tval
|
||||
# End time, in seconds since GMT epoch
|
||||
#
|
||||
# getlist=1
|
||||
# To be combined with branch, machine and testname
|
||||
# Returns a list of distinct branches, machines or testnames in the database
|
||||
#
|
||||
# if neither getlist nor setid are found in the query string the returned results will be a list
|
||||
# of tests, limited by a given datelimit, branch, machine and testname
|
||||
# ie) dgetdata?datelimit=1&branch=1.8 will return all tests in the database that are not older than a day and that
|
||||
# were run on the 1.8 branch
|
||||
|
||||
def doError(errCode):
|
||||
errString = "unknown error"
|
||||
if errCode == -1:
|
||||
errString = "bad tinderbox"
|
||||
elif errCode == -2:
|
||||
errString = "bad test name"
|
||||
print "{ resultcode: " + str(errCode) + ", error: '" + errString + "' }"
|
||||
|
||||
def doGetList(fo, type, branch, machine, testname):
|
||||
results = []
|
||||
s1 = ""
|
||||
if branch:
|
||||
s1 = "SELECT DISTINCT branch FROM dataset_info"
|
||||
if machine:
|
||||
s1 = "SELECT DISTINCT machine FROM dataset_info"
|
||||
if testname:
|
||||
s1 = "SELECT DISTINCT test FROM dataset_info"
|
||||
cur = db.cursor()
|
||||
cur.execute(s1 + " WHERE type = ?", (type,))
|
||||
for row in cur:
|
||||
results.append({ "value": row[0] })
|
||||
cur.close()
|
||||
fo.write(json.write( {"resultcode": 0, "results": results} ))
|
||||
|
||||
def doListTests(fo, type, datelimit, branch, machine, testname, graphby):
|
||||
results = []
|
||||
s1 = ""
|
||||
|
||||
# FIXME: This could be vulnerable to SQL injection! Although it looks like checkstring should catch bad strings.
|
||||
if branch:
|
||||
s1 += " AND branch = '" + branch + "' "
|
||||
if machine:
|
||||
s1 += " AND machine = '" + machine + "' "
|
||||
if testname:
|
||||
s1 += " AND test = '" + testname + "' "
|
||||
|
||||
cur = db.cursor()
|
||||
if graphby and graphby == 'bydata':
|
||||
cur.execute("SELECT id, machine, test, test_type, dataset_extra_data.data, extra_data, branch FROM dataset_extra_data JOIN dataset_info ON dataset_extra_data.dataset_id = dataset_info.id WHERE type = ? AND test_type != ? and (date >= ?) " + s1 +" GROUP BY machine,test,test_type,dataset_extra_data.data, extra_data, branch", (type, "baseline", datelimit))
|
||||
else:
|
||||
cur.execute("SELECT id, machine, test, test_type, date, extra_data, branch FROM dataset_info WHERE type = ? AND test_type != ? and (date >= ?)" + s1, (type, "baseline", datelimit))
|
||||
for row in cur:
|
||||
if graphby and graphby == 'bydata':
|
||||
results.append( {"id": row[0],
|
||||
"machine": row[1],
|
||||
"test": row[2],
|
||||
"test_type": row[3],
|
||||
"data": row[4],
|
||||
"extra_data": row[5],
|
||||
"branch": row[6]})
|
||||
else:
|
||||
results.append( {"id": row[0],
|
||||
"machine": row[1],
|
||||
"test": row[2],
|
||||
"test_type": row[3],
|
||||
"date": row[4],
|
||||
"extra_data": row[5],
|
||||
"branch": row[6]})
|
||||
|
||||
cur.close()
|
||||
fo.write (json.write( {"resultcode": 0, "results": results} ))
|
||||
|
||||
|
||||
def getByDataResults(cur,setid,extradata,starttime,endtime):
|
||||
s1 = ""
|
||||
s2 = ""
|
||||
cur.execute("""
|
||||
SELECT dataset_info.date,avg(dataset_values.value)
|
||||
FROM dataset_info
|
||||
JOIN dataset_extra_data
|
||||
ON dataset_extra_data.dataset_id = dataset_info.id
|
||||
JOIN dataset_values
|
||||
ON dataset_extra_data.time = dataset_values.time
|
||||
AND dataset_info.id = dataset_values.dataset_id
|
||||
WHERE
|
||||
(dataset_info.machine,dataset_info.test,dataset_info.test_type,dataset_info.extra_data,dataset_info.branch) = (SELECT machine,test,test_type,extra_data,branch from dataset_info where id = ? limit 1)
|
||||
AND dataset_extra_data.data = ?
|
||||
GROUP BY dataset_info.date ORDER BY dataset_info.date
|
||||
""", (setid,extradata))
|
||||
|
||||
|
||||
def doSendResults(fo, setid, starttime, endtime, raw, graphby, extradata=None):
|
||||
s1 = ""
|
||||
s2 = ""
|
||||
if starttime:
|
||||
s1 = " AND time >= " + starttime
|
||||
if endtime:
|
||||
s2 = " AND time <= " + endtime
|
||||
|
||||
fo.write ("{ resultcode: 0,")
|
||||
|
||||
cur = db.cursor()
|
||||
if not graphby or graphby == "time":
|
||||
cur.execute("SELECT time, value FROM dataset_values WHERE dataset_id = ? " + s1 + s2 + " ORDER BY time", (setid,))
|
||||
else:
|
||||
getByDataResults(cur,setid, extradata,starttime,endtime)
|
||||
fo.write ("results: [")
|
||||
for row in cur:
|
||||
if row[1] == 'nan':
|
||||
continue
|
||||
fo.write ("%s,%s," % (row[0], row[1]))
|
||||
cur.close()
|
||||
fo.write ("],")
|
||||
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT time, value FROM annotations WHERE dataset_id = ? " + s1 + s2 + " ORDER BY time", (setid,))
|
||||
fo.write ("annotations: [")
|
||||
for row in cur:
|
||||
fo.write("%s,'%s'," % (row[0], row[1]))
|
||||
cur.close()
|
||||
fo.write ("],")
|
||||
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT test FROM dataset_info WHERE id = ?", (setid,))
|
||||
row = cur.fetchone()
|
||||
test_name = row[0]
|
||||
|
||||
cur.execute("SELECT id, extra_data FROM dataset_info WHERE test = ? and test_type = ?", (test_name, "baseline"))
|
||||
baselines = cur.fetchall()
|
||||
|
||||
fo.write ("baselines: {")
|
||||
for baseline in baselines:
|
||||
cur.execute("SELECT value FROM dataset_values WHERE dataset_id = ? LIMIT 1", (baseline[0],))
|
||||
row = cur.fetchone()
|
||||
fo.write("'%s': '%s'," % (baseline[1], row[0]))
|
||||
fo.write("},")
|
||||
cur.close()
|
||||
|
||||
if raw:
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT time, data FROM dataset_extra_data WHERE dataset_id = ? " + s1 + s2 + " ORDER BY time", (setid,))
|
||||
fo.write ("rawdata: [")
|
||||
for row in cur:
|
||||
blob = row[1]
|
||||
if "\\" in blob:
|
||||
blob = blob.replace("\\", "\\\\")
|
||||
if "'" in blob:
|
||||
blob = blob.replace("'", "\\'")
|
||||
fo.write("%s,'%s'," % (row[0], blob))
|
||||
cur.close()
|
||||
fo.write ("],")
|
||||
|
||||
cur = db.cursor()
|
||||
cur.execute("SELECT avg(value), max(value), min(value) from dataset_values where dataset_id = ? " + s1 + s2 + " GROUP BY dataset_id", (setid,))
|
||||
fo.write("stats: [")
|
||||
for row in cur:
|
||||
fo.write("%s, %s, %s," %(row[0], row[1], row[2]))
|
||||
cur.close()
|
||||
fo.write("],")
|
||||
|
||||
fo.write ("}")
|
||||
|
||||
#if var is a number returns a value other than None
|
||||
def checkNumber(var):
|
||||
if var is None:
|
||||
return 1
|
||||
reNumber = re.compile('^[0-9.]*$')
|
||||
return reNumber.match(var)
|
||||
|
||||
#if var is a string returns a value other than None
|
||||
def checkString(var):
|
||||
if var is None:
|
||||
return 1
|
||||
reString = re.compile('^[0-9A-Za-z._()\- ]*$')
|
||||
return reString.match(var)
|
||||
|
||||
doGzip = 0
|
||||
try:
|
||||
if "gzip" in os.environ["HTTP_ACCEPT_ENCODING"]:
|
||||
doGzip = 1
|
||||
except:
|
||||
pass
|
||||
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
#make sure that we are getting clean data from the user
|
||||
for strField in ["type", "machine", "branch", "test", "graphby","extradata"]:
|
||||
val = form.getfirst(strField)
|
||||
if strField == "test":
|
||||
strField = "testname"
|
||||
if not checkString(val):
|
||||
print "Invalid string arg: ", strField, " '" + val + "'"
|
||||
sys.exit(500)
|
||||
globals()[strField] = val
|
||||
|
||||
for numField in ["setid", "raw", "starttime", "endtime", "datelimit", "getlist"]:
|
||||
val = form.getfirst(numField)
|
||||
if not checkNumber(val):
|
||||
print "Invalid string arg: ", numField, " '" + val + "'"
|
||||
sys.exit(500)
|
||||
globals()[numField] = val
|
||||
|
||||
if not datelimit:
|
||||
datelimit = 0
|
||||
|
||||
zbuf = cStringIO.StringIO()
|
||||
zfile = zbuf
|
||||
if doGzip == 1:
|
||||
zfile = gzip.GzipFile(mode = 'wb', fileobj = zbuf, compresslevel = 5)
|
||||
|
||||
if not setid and not getlist:
|
||||
doListTests(zfile, type, datelimit, branch, machine, testname, graphby)
|
||||
elif not getlist:
|
||||
doSendResults(zfile, setid, starttime, endtime, raw, graphby,extradata)
|
||||
else:
|
||||
doGetList(zfile, type, branch, machine, testname)
|
||||
|
||||
sys.stdout.write("Content-Type: text/plain\n")
|
||||
if doGzip == 1:
|
||||
zfile.close()
|
||||
sys.stdout.write("Content-Encoding: gzip\n")
|
||||
sys.stdout.write("\n")
|
||||
|
||||
sys.stdout.write(zbuf.getvalue())
|
||||
|
||||
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Perf-o-matic</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="js/graph.css">
|
||||
|
||||
<!-- MochiKit -->
|
||||
<script type="text/javascript" src="js/mochikit/MochiKit.js"></script>
|
||||
|
||||
<!-- YUI -->
|
||||
<script type="text/javascript" src="js/yui/yahoo.js"></script>
|
||||
<script type="text/javascript" src="js/yui/dom.js"></script>
|
||||
<script type="text/javascript" src="js/yui/event.js"></script>
|
||||
<script type="text/javascript" src="js/yui/animation.js"></script>
|
||||
<script type="text/javascript" src="js/yui/container.js"></script>
|
||||
|
||||
<!-- Core -->
|
||||
<script type="text/javascript" src="js/TinderboxData.js"></script>
|
||||
<script type="text/javascript" src="js/DataSet.js"></script>
|
||||
<script type="text/javascript" src="js/GraphCanvas.js"></script>
|
||||
|
||||
<script type="text/javascript" src="js/GraphFormModule.js"></script>
|
||||
<script type="text/javascript" src="js/graph.js"></script>
|
||||
<script type="text/javascript" src="js/ResizeGraph.js"></script>
|
||||
|
||||
<!-- BonsaiService needs e4x -->
|
||||
<script type="text/javascript; e4x=1" src="js/BonsaiService.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="loadingDone(CONTINUOUS_GRAPH)">
|
||||
<!--<h1>Graph</h1>-->
|
||||
|
||||
<!-- Take your damn divs and floats and clears and shove 'em! -->
|
||||
|
||||
<div style="width: 710px; height:20px; margin-left:10px ">
|
||||
<span id="loading" class="loading"></span>
|
||||
</div>
|
||||
|
||||
<form action="javascript:;">
|
||||
<table class="graphconfig-no" width="100%">
|
||||
|
||||
<tr style="vertical-align: top">
|
||||
<td class="graphconfig">
|
||||
<table>
|
||||
<tr style="vertical-align: top;">
|
||||
<td>Show</td>
|
||||
<td>
|
||||
<input id="load-all-radio" type="radio" name="dataload" onclick="onDataLoadChanged()" checked>
|
||||
<label>all data</label><br>
|
||||
<input id="load-days-radio" type="radio" name="dataload" onclick="onDataLoadChanged()">
|
||||
<label>previous</label> <input type="text" value="30" id="load-days-entry" size="3" onchange="onDataLoadChanged()"> <label>days</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div id="baseline">
|
||||
<span>Use </span><select id="baselineDropdown"><option value="0">nothing</option></select><span> as a baseline</span><br>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div id="formend">
|
||||
<input type="submit" onclick="onGraph()" value="Graph It!">
|
||||
</br> </br>
|
||||
<!-- <label for="baseline">No baseline</label><input type="radio" name="baseline" checked onclick="onNoBaseLineClick()"> -->
|
||||
<a id="linktothis" href="graph.html">Link to this graph</a>
|
||||
</br>
|
||||
<div><a id="dumptocsv" href="dumpdata.cgi">Dump to csv</a> </div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<input style="display:none" id="bonsaibutton" type="button" onclick="onUpdateBonsai()" value="Refresh Bonsai Data">
|
||||
</td>
|
||||
|
||||
<td class="graphconfig-list">
|
||||
<div id="graphforms"></div>
|
||||
<div id="addone">
|
||||
<img src="js/img/plus.png" class="plusminus" onclick="addGraphForm()" alt="Plus">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
<!-- small graph -->
|
||||
<div style="width: 900px; height:20px">
|
||||
<center><span id="status" class="status"></span></center>
|
||||
</div>
|
||||
|
||||
<!-- these are absolute size, so we wrap them in a div that can overflow -->
|
||||
<div id="graph-container" style="margin:auto; width:900px;">
|
||||
<div id="smallgraph-labels-x" style="position: relative; left: 51px; margin-left: 1px; margin-right: 1px; height: 30px; width: 700px"></div>
|
||||
<div id="smallgraph-labels-y" style="position: relative; left: 0px; top: 0px; float: left; height: 76px; width: 50px;"></div>
|
||||
<canvas style="clear: left; border: 1px solid #888; padding-top: 1px;" id="smallgraph" height="75" width="700"></canvas>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div id="graph-labels-y" style="position: relative; left: 0px; top: 0px; float: left; margin-top: 1px; margin-bottom: 1px; height: 300px; width: 50px;"></div>
|
||||
<canvas style="clear: left; border: 1px solid #888;" id="graph" height="300" width="700"></canvas>
|
||||
<div id="graph-labels-x" style="position: relative; left: 50px; margin-left: 1px; margin-right: 1px; height: 50px; width: 700px"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
ResizableBigGraph = new ResizeGraph();
|
||||
ResizableBigGraph.init('graph');
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
from pysqlite2 import dbapi2 as sqlite
|
||||
from databases import mysql as MySQLdb
|
||||
|
||||
|
||||
db = MySQLdb.connect("localhost","o","o","o_graphs")
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is new-graph code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function BonsaiService() {
|
||||
}
|
||||
|
||||
BonsaiService.prototype = {
|
||||
// this could cache stuff, so that we only have to request the bookend data
|
||||
// if we want a wider range, but it's probably not worth it for now.
|
||||
//
|
||||
// The callback is called with an object argument which contains:
|
||||
// {
|
||||
// times: [ t1, t2, t3, .. ],
|
||||
// who: [ w1, w2, w3, .. ],
|
||||
// log: [ l1, l2, l3, .. ],
|
||||
// files: [ [ r11, f11, r12, f12, r13, f13, .. ], [ r21, f21, r22, f22, r23, f23, .. ], .. ]
|
||||
// }
|
||||
//
|
||||
// r = revision number, as a string, e.g. "1.15"
|
||||
// f = file, e.g. "mozilla/widget/foo.cpp"
|
||||
//
|
||||
// arg1 = callback, arg2 = null
|
||||
// arg1 = includeFiles, arg2 = callback
|
||||
requestCheckinsBetween: function (startDate, endDate, arg1, arg2) {
|
||||
var includeFiles = arg1;
|
||||
var callback = arg2;
|
||||
|
||||
if (arg2 == null) {
|
||||
callback = arg1;
|
||||
includeFiles = null;
|
||||
}
|
||||
|
||||
var queryargs = {
|
||||
treeid: "default",
|
||||
module: "SeaMonkeyAll",
|
||||
branch: "HEAD",
|
||||
mindate: startDate,
|
||||
maxdate: endDate
|
||||
};
|
||||
|
||||
if (!includeFiles)
|
||||
queryargs.xml_nofiles = "1";
|
||||
|
||||
log ("bonsai request: ", queryString(queryargs));
|
||||
|
||||
doSimpleXMLHttpRequest (bonsaicgi, queryargs)
|
||||
.addCallbacks(
|
||||
function (obj) {
|
||||
var result = { times: [], who: [], comment: [], files: null };
|
||||
if (includeFiles)
|
||||
result.files = [];
|
||||
|
||||
// strip out the xml declaration
|
||||
var s = obj.responseText.replace(/<\?xml version="1.0"\?>/, "");
|
||||
var bq = new XML(s);
|
||||
for (var i = 0; i < bq.ci.length(); i++) {
|
||||
var ci = bq.ci[i];
|
||||
result.times.push(ci.@date);
|
||||
result.who.push(ci.@who);
|
||||
result.comment.push(ci.log.text().toString());
|
||||
if (includeFiles) {
|
||||
var files = [];
|
||||
for (var j = 0; j < ci.files.f.length(); j++) {
|
||||
var f = ci.files.f[j];
|
||||
files.push(f.@rev);
|
||||
files.push(f.text().toString());
|
||||
}
|
||||
result.files.push(files);
|
||||
}
|
||||
}
|
||||
|
||||
callback.call (window, result);
|
||||
},
|
||||
function () { alert ("Error talking to bonsai"); });
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,273 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is new-graph code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function TimeDataSet(data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
TimeDataSet.prototype = {
|
||||
data: null,
|
||||
|
||||
indicesForTimeRange: function (startTime, endTime) {
|
||||
var startIndex = -1;
|
||||
var endIndex = -1;
|
||||
|
||||
if (this.data[0] > endTime ||
|
||||
this.data[this.data.length-2] < startTime)
|
||||
return null;
|
||||
|
||||
for (var i = 0; i < this.data.length/2; i++) {
|
||||
if (startIndex == -1 && this.data[i*2] >= startTime) {
|
||||
startIndex = i;
|
||||
} else if (startIndex != -1 && this.data[i*2] > endTime) {
|
||||
endIndex = i;
|
||||
return [startIndex, endIndex];
|
||||
}
|
||||
}
|
||||
|
||||
endIndex = (this.data.length/2) - 1;
|
||||
return [startIndex, endIndex];
|
||||
},
|
||||
};
|
||||
|
||||
function TimeValueDataSet(data, color) {
|
||||
this.data = data;
|
||||
|
||||
this.firstTime = data[0];
|
||||
if (data.length > 2)
|
||||
this.lastTime = data[data.length-2];
|
||||
else
|
||||
this.lastTime = data[0];
|
||||
|
||||
if (color) {
|
||||
this.color = color;
|
||||
} else {
|
||||
this.color = "#000000";
|
||||
}
|
||||
|
||||
log ("new tds:", this.firstTime, this.lastTime);
|
||||
|
||||
this.relativeToSets = new Array();
|
||||
}
|
||||
|
||||
TimeValueDataSet.prototype = {
|
||||
__proto__: new TimeDataSet(),
|
||||
|
||||
firstTime: 0,
|
||||
lastTime: 0,
|
||||
data: null, // array: [time0, value0, time1, value1, ...]
|
||||
relativeTo: null,
|
||||
|
||||
color: "black",
|
||||
title: '',
|
||||
|
||||
minMaxValueForTimeRange: function (startTime, endTime) {
|
||||
var minValue = Number.POSITIVE_INFINITY;
|
||||
var maxValue = Number.NEGATIVE_INFINITY;
|
||||
for (var i = 0; i < this.data.length/2; i++) {
|
||||
var t = this.data[i*2];
|
||||
if (t >= startTime && t <= endTime) {
|
||||
var v = this.data[i*2+1];
|
||||
if (v < minValue)
|
||||
minValue = v;
|
||||
if (v > maxValue)
|
||||
maxValue = v;
|
||||
}
|
||||
}
|
||||
|
||||
return [minValue, maxValue];
|
||||
},
|
||||
|
||||
// create a new ds that's the average of this ds's values,
|
||||
// with the average sampled over the given interval,
|
||||
// at every avginterval/2
|
||||
createAverage: function (avginterval) {
|
||||
if (avginterval <= 0)
|
||||
throw "avginterval <= 0";
|
||||
|
||||
if (this.averageDataSet != null &&
|
||||
this.averageInterval == avginterval)
|
||||
{
|
||||
return this.averageDataSet;
|
||||
}
|
||||
|
||||
var newdata = [];
|
||||
|
||||
var time0 = this.data[0];
|
||||
var val0 = 0;
|
||||
var count0 = 0;
|
||||
|
||||
var time1 = time0 + avginterval/2;
|
||||
var val1 = 0;
|
||||
var count1 = 0;
|
||||
|
||||
var ns = this.data.length/2;
|
||||
for (var i = 0; i < ns; i++) {
|
||||
var t = this.data[i*2];
|
||||
var v = this.data[i*2+1];
|
||||
if (t > time0+avginterval) {
|
||||
newdata.push(time0 + avginterval/2);
|
||||
newdata.push(count0 ? (val0 / count0) : 0);
|
||||
|
||||
// catch up
|
||||
while (time1 < t) {
|
||||
time0 += avginterval/2;
|
||||
time1 = time0;
|
||||
}
|
||||
|
||||
time0 = time1;
|
||||
val0 = val1;
|
||||
count0 = count1;
|
||||
|
||||
time1 = time0 + avginterval/2;
|
||||
val1 = 0;
|
||||
count1 = 0;
|
||||
}
|
||||
|
||||
val0 += v;
|
||||
count0++;
|
||||
|
||||
if (t > time1) {
|
||||
val1 += v;
|
||||
count1++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count0 > 0) {
|
||||
newdata.push(time0 + avginterval/2);
|
||||
newdata.push(val0 / count0);
|
||||
}
|
||||
|
||||
var newds = new TimeValueDataSet(newdata, lighterColor(this.color));
|
||||
newds.averageOf = this;
|
||||
|
||||
this.averageDataSet = newds;
|
||||
this.averageInterval = avginterval;
|
||||
|
||||
return newds;
|
||||
},
|
||||
|
||||
// create a new dataset with this ds's data,
|
||||
// relative to otherds
|
||||
createRelativeTo: function (otherds, absval) {
|
||||
if (otherds == this) {
|
||||
log("error, same ds");
|
||||
return null;
|
||||
}
|
||||
|
||||
for each (var s in this.relativeToSets) {
|
||||
if (s.relativeTo == otherds)
|
||||
return s;
|
||||
}
|
||||
|
||||
var firstTime = this.firstTime;
|
||||
var lastTime = this.lastTime;
|
||||
|
||||
if (otherds.firstTime > firstTime)
|
||||
firstTime = otherds.firstTime;
|
||||
if (otherds.lastTime < lastTime)
|
||||
lastTime = otherds.lastTime;
|
||||
|
||||
var newdata = [];
|
||||
|
||||
var thisidx = this.indicesForTimeRange (firstTime, lastTime);
|
||||
var otheridx = this.indicesForTimeRange (firstTime, lastTime);
|
||||
|
||||
var o = otheridx[0];
|
||||
var ov, ov1, ov2, ot1, ot2;
|
||||
for (var i = thisidx[0]; i < thisidx[1]; i++) {
|
||||
var t = this.data[i*2];
|
||||
var tv = this.data[i*2+1];
|
||||
while (otherds.data[o*2] < t)
|
||||
o++;
|
||||
|
||||
ot1 = otherds.data[o*2];
|
||||
ov1 = otherds.data[o*2+1];
|
||||
if (o < otheridx[1]) {
|
||||
ot2 = otherds.data[o*2+2];
|
||||
ov2 = otherds.data[o*2+3];
|
||||
} else {
|
||||
ot2 = ot1;
|
||||
ov2 = ov1;
|
||||
}
|
||||
|
||||
|
||||
var d = (t-ot1)/(ot2-ot1);
|
||||
ov = (1-d) * ov1 + d * ov2;
|
||||
|
||||
newdata.push(t);
|
||||
//log ("i", i, "tv", tv, "ov", ov, "t", t, "ot1", ot1, "ot2", ot2, "ov1", ov1, "ov2", ov2);
|
||||
//log ("i", i, "tv", tv, "ov", ov, "tv/ov", tv/ov, "ov/tv", ov/tv);
|
||||
if (absval) {
|
||||
newdata.push(tv-ov);
|
||||
} else {
|
||||
if (tv > ov)
|
||||
newdata.push((tv/ov) - 1);
|
||||
else
|
||||
newdata.push(-((ov/tv) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
var newds = new TimeValueDataSet(newdata, this.color);
|
||||
newds.relativeTo = otherds;
|
||||
|
||||
this.relativeToSets.push(newds);
|
||||
|
||||
return newds;
|
||||
},
|
||||
};
|
||||
|
||||
function TimeStringDataSet(data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
TimeStringDataSet.prototype = {
|
||||
__proto__: new TimeDataSet(),
|
||||
data: null,
|
||||
|
||||
onDataSetChanged: null,
|
||||
|
||||
init: function () {
|
||||
},
|
||||
|
||||
addString: function (time, string) {
|
||||
},
|
||||
|
||||
removeStringAt: function (index) {
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is new-graph code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var GraphFormModules = [];
|
||||
var GraphFormModuleCount = 0;
|
||||
|
||||
function GraphFormModule(userConfig) {
|
||||
GraphFormModuleCount++;
|
||||
this.__proto__.__proto__.constructor.call(this, "graphForm" + GraphFormModuleCount, userConfig);
|
||||
}
|
||||
|
||||
GraphFormModule.prototype = {
|
||||
__proto__: new YAHOO.widget.Module(),
|
||||
|
||||
imageRoot: "",
|
||||
|
||||
testId: null,
|
||||
baseline: false,
|
||||
average: false,
|
||||
color: "#000000",
|
||||
onLoadingDone : new YAHOO.util.CustomEvent("onloadingdone"),
|
||||
onLoading : new YAHOO.util.CustomEvent("onloading"),
|
||||
|
||||
init: function (el, userConfig) {
|
||||
var self = this;
|
||||
|
||||
this.__proto__.__proto__.init.call(this, el/*, userConfig*/);
|
||||
|
||||
this.cfg = new YAHOO.util.Config(this);
|
||||
this.cfg.addProperty("testid", { suppressEvent: true });
|
||||
this.cfg.addProperty("average", { suppressEvent: true });
|
||||
this.cfg.addProperty("baseline", { suppressEvent: true });
|
||||
|
||||
if (userConfig)
|
||||
this.cfg.applyConfig(userConfig, true);
|
||||
|
||||
var form, td, el;
|
||||
|
||||
form = new DIV({ class: "graphform-line" });
|
||||
|
||||
td = new SPAN();
|
||||
/*
|
||||
el = new IMG({ src: "js/img/plus.png", class: "plusminus",
|
||||
onclick: function(event) { addGraphForm(); } });
|
||||
td.appendChild(el);
|
||||
*/
|
||||
el = new IMG({ src: "js/img/minus.png", class: "plusminus",
|
||||
onclick: function(event) { self.remove(); } });
|
||||
td.appendChild(el);
|
||||
form.appendChild(td);
|
||||
|
||||
td = new SPAN();
|
||||
el = new DIV({ id: "whee", style: "display: inline; border: 1px solid black; height: 15; " +
|
||||
"padding-right: 15; vertical-align: middle; margin: 3px;" });
|
||||
this.colorDiv = el;
|
||||
td.appendChild(el);
|
||||
form.appendChild(td);
|
||||
|
||||
td = new SPAN();
|
||||
el = new SELECT({ name: "testname",
|
||||
class: "testname",
|
||||
onchange: function(event) { self.onChangeTest(); } });
|
||||
this.testSelect = el;
|
||||
td.appendChild(el);
|
||||
form.appendChild(td);
|
||||
|
||||
td = new SPAN({ style: "padding-left: 10px;"});
|
||||
appendChildNodes(td, "Average:");
|
||||
el = new INPUT({ name: "average",
|
||||
type: "checkbox",
|
||||
onchange: function(event) { self.average = event.target.checked; } });
|
||||
this.averageCheckbox = el;
|
||||
td.appendChild(el);
|
||||
form.appendChild(td);
|
||||
|
||||
this.setBody (form);
|
||||
|
||||
var forceTestId = null;
|
||||
this.average = false;
|
||||
if (userConfig) {
|
||||
forceTestId = this.cfg.getProperty("testid");
|
||||
avg = this.cfg.getProperty("average");
|
||||
baseline = this.cfg.getProperty("baseline");
|
||||
if (avg == 1) {
|
||||
this.averageCheckbox.checked = true;
|
||||
this.average = true;
|
||||
}
|
||||
if (baseline == 1)
|
||||
this.onBaseLineRadioClick();
|
||||
}
|
||||
|
||||
Tinderbox.requestTestList(function (tests) {
|
||||
var opts = [];
|
||||
// let's sort by machine name
|
||||
var sortedTests = Array.sort(tests, function (a, b) {
|
||||
if (a.machine < b.machine) return -1;
|
||||
if (a.machine > b.machine) return 1;
|
||||
if (a.test < b.test) return -1;
|
||||
if (a.test > b.test) return 1;
|
||||
if (a.test_type < b.test_type) return -1;
|
||||
if (a.test_type > b.test_type) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
for each (var test in sortedTests) {
|
||||
var tstr = test.machine + " - " + test.test + " - " + test.branch;
|
||||
opts.push(new OPTION({ value: test.id }, tstr));
|
||||
}
|
||||
replaceChildNodes(self.testSelect, opts);
|
||||
|
||||
if (forceTestId != null) {
|
||||
self.testSelect.value = forceTestId;
|
||||
} else {
|
||||
self.testSelect.value = sortedTests[0].id;
|
||||
}
|
||||
setTimeout(function () { self.onChangeTest(forceTestId); }, 0);
|
||||
self.onLoadingDone.fire();
|
||||
});
|
||||
|
||||
GraphFormModules.push(this);
|
||||
},
|
||||
|
||||
getQueryString: function (prefix) {
|
||||
return prefix + "tid=" + this.testId + "&" + prefix + "bl=" + (this.baseline ? "1" : "0")
|
||||
+ "&" + prefix + "avg=" + (this.average? "1" : "0");
|
||||
},
|
||||
|
||||
getDumpString: function () {
|
||||
return "setid=" + this.testId;
|
||||
},
|
||||
|
||||
onChangeTest: function (forceTestId) {
|
||||
this.testId = this.testSelect.value;
|
||||
},
|
||||
|
||||
onBaseLineRadioClick: function () {
|
||||
GraphFormModules.forEach(function (g) { g.baseline = false; });
|
||||
this.baseline = true;
|
||||
},
|
||||
|
||||
setColor: function (newcolor) {
|
||||
this.color = newcolor;
|
||||
this.colorDiv.style.backgroundColor = colorToRgbString(newcolor);
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
if (GraphFormModules.length == 1)
|
||||
return;
|
||||
|
||||
var nf = [];
|
||||
for each (var f in GraphFormModules) {
|
||||
if (f != this)
|
||||
nf.push(f);
|
||||
}
|
||||
GraphFormModules = nf;
|
||||
this.destroy();
|
||||
},
|
||||
};
|
||||
@@ -1,161 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is new-graph code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeremiah Orem <oremj@oremj.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function ResizeGraph() {
|
||||
}
|
||||
|
||||
ResizeGraph.prototype = {
|
||||
|
||||
margin_right: 25,
|
||||
margin_bottom: 25,
|
||||
resizing: false,
|
||||
active: false,
|
||||
element: null,
|
||||
handle: null,
|
||||
startX: null,
|
||||
startY: null,
|
||||
startHeight: null,
|
||||
startWidth: null,
|
||||
startTop: null,
|
||||
startLeft: null,
|
||||
currentDirection: '',
|
||||
|
||||
|
||||
init: function(elem) {
|
||||
this.handle = elem;
|
||||
this.element = getElement(elem);
|
||||
connect(this.handle,'onmousedown',this, 'mouseDownFunc');
|
||||
connect(document,'onmouseup',this, 'mouseUpFunc');
|
||||
connect(this.handle,'onmousemove',this, 'mouseMoveFunc');
|
||||
connect(document,'onmousemove',this, 'updateElement');
|
||||
},
|
||||
|
||||
directions: function(e) {
|
||||
var pointer = e.mouse();
|
||||
var graphPosition = elementPosition(this.handle);
|
||||
var dimensions = elementDimensions(this.handle);
|
||||
var dir = '';
|
||||
if ( pointer.page.x > (graphPosition.x + dimensions.w) - this.margin_right ) {
|
||||
dir= "e";
|
||||
}
|
||||
else if ( pointer.page.y > (graphPosition.y + dimensions.h) - this.margin_bottom ) {
|
||||
dir = "s";
|
||||
}
|
||||
return dir;
|
||||
},
|
||||
|
||||
draw: function(e) {
|
||||
var pointer = [e.mouse().page.x, e.mouse().page.y];
|
||||
var style = this.element.style;
|
||||
if (this.currentDirection.indexOf('s') != -1) {
|
||||
var newHeight = this.startHeight + pointer[1] - this.startY;
|
||||
if (newHeight > this.margin_bottom) {
|
||||
style.height = newHeight + "px";
|
||||
this.element.height = newHeight;
|
||||
}
|
||||
}
|
||||
if (this.currentDirection.indexOf('e') != -1) {
|
||||
var newWidth = this.startWidth + pointer[0] - this.startX;
|
||||
if (newWidth > this.margin_right) {
|
||||
if (newWidth > 900) {
|
||||
getElement('graph-container').style.width = (newWidth + 200) + "px";
|
||||
}
|
||||
style.width = newWidth + "px";
|
||||
this.element.width = newWidth;
|
||||
}
|
||||
}
|
||||
},
|
||||
mouseDownFunc: function(e)
|
||||
{
|
||||
var dir = this.directions(e);
|
||||
pointer = e.mouse();
|
||||
if (dir.length > 0 ) {
|
||||
this.active = true;
|
||||
var dimensions = elementDimensions(this.handle);
|
||||
var graphPosition = elementPosition(this.handle);
|
||||
this.startTop = graphPosition.y;
|
||||
this.startLeft = graphPosition.x;
|
||||
this.startHeight = dimensions.h;
|
||||
this.startWidth = dimensions.w;
|
||||
this.startX = pointer.page.x + document.body.scrollLeft + document.documentElement.scrollLeft;
|
||||
this.startY = pointer.page.y + document.body.scrollLeft + document.documentElement.scrollLeft;
|
||||
this.currentDirection = dir;
|
||||
e.stop();
|
||||
}
|
||||
},
|
||||
mouseMoveFunc: function(e)
|
||||
{
|
||||
pointer = e.mouse();
|
||||
graphPosition = elementPosition(this.handle);
|
||||
dimensions = elementDimensions(this.handle);
|
||||
dir = this.directions(e);
|
||||
if(dir.length > 0) {
|
||||
getElement(this.handle).style.cursor = dir + "-resize";
|
||||
}
|
||||
else {
|
||||
getElement(this.handle).style.cursor = '';
|
||||
}
|
||||
},
|
||||
updateElement: function(e)
|
||||
{
|
||||
if( this.active ) {
|
||||
if ( ! this.resizing ) {
|
||||
var style = getElement(this.handle).style;
|
||||
this.resizing = true;
|
||||
style.position = "relative";
|
||||
}
|
||||
this.draw(e);
|
||||
e.stop()
|
||||
return false;
|
||||
}
|
||||
},
|
||||
finishResize: function(e,success) {
|
||||
this.active = false;
|
||||
this.resizing = false;
|
||||
},
|
||||
mouseUpFunc: function(e)
|
||||
{
|
||||
if(this.active && this.resizing) {
|
||||
this.finishResize(e,true);
|
||||
BigPerfGraph.resize();
|
||||
e.stop();
|
||||
}
|
||||
this.active = false;
|
||||
this.resizing = false;
|
||||
},
|
||||
|
||||
};
|
||||
@@ -1,417 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is new-graph code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Alice Nodelman <anodelman@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//const getdatacgi = "getdata-fake.cgi?";
|
||||
//const getdatacgi = "http://localhost:9050/getdata.cgi?";
|
||||
const getdatacgi = "getdata.cgi?"
|
||||
|
||||
|
||||
function checkErrorReturn(obj) {
|
||||
if (!obj || obj.resultcode != 0) {
|
||||
alert ("Error: " + (obj ? (obj.error + "(" + obj.resultcode + ")") : "(nil)"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function TinderboxData() {
|
||||
this.onTestListAvailable = new YAHOO.util.CustomEvent("testlistavailable");
|
||||
this.onDataSetAvailable = new YAHOO.util.CustomEvent("datasetavailable");
|
||||
this.testList = null;
|
||||
|
||||
this.testData = {};
|
||||
|
||||
}
|
||||
|
||||
TinderboxData.prototype = {
|
||||
testList: null,
|
||||
testData: null,
|
||||
|
||||
onTestListAvailable: null,
|
||||
onDataSetAvailable: null,
|
||||
|
||||
defaultLoadRange: null,
|
||||
raw: 0,
|
||||
|
||||
init: function () {
|
||||
var self = this;
|
||||
//netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
|
||||
|
||||
loadJSONDoc(getdatacgi + "type=continuous")
|
||||
.addCallbacks(
|
||||
function (obj) {
|
||||
if (!checkErrorReturn(obj)) return;
|
||||
self.testList = obj.results;
|
||||
//log("default test list" + self.testList);
|
||||
self.onTestListAvailable.fire(self.testList);
|
||||
},
|
||||
function () {alert ("Error talking to " + getdatacgi + ""); });
|
||||
},
|
||||
|
||||
requestTestList: function (callback) {
|
||||
//log("requestTestList default");
|
||||
var self = this;
|
||||
|
||||
if (this.testList != null) {
|
||||
callback.call (window, this.testList);
|
||||
} else {
|
||||
var cb =
|
||||
function (type, args, obj) {
|
||||
self.onTestListAvailable.unsubscribe(cb, obj);
|
||||
obj.call (window, args[0]);
|
||||
};
|
||||
|
||||
this.onTestListAvailable.subscribe (cb, callback);
|
||||
}
|
||||
},
|
||||
|
||||
// arg1 = startTime, arg2 = endTime, arg3 = callback
|
||||
// arg1 = callback, arg2/arg3 == null
|
||||
requestDataSetFor: function (testId, arg1, arg2, arg3) {
|
||||
var self = this;
|
||||
|
||||
var startTime = arg1;
|
||||
var endTime = arg2;
|
||||
var callback = arg3;
|
||||
|
||||
if (arg1 && arg2 == null && arg3 == null) {
|
||||
callback = arg1;
|
||||
if (this.defaultLoadRange) {
|
||||
startTime = this.defaultLoadRange[0];
|
||||
endTime = this.defaultLoadRange[1];
|
||||
//log ("load range using default", startTime, endTime);
|
||||
} else {
|
||||
startTime = null;
|
||||
endTime = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (testId in this.testData) {
|
||||
var ds = this.testData[testId];
|
||||
//log ("Can maybe use cached?");
|
||||
if ((ds.requestedFirstTime == null && ds.requestedLastTime == null) ||
|
||||
(ds.requestedFirstTime <= startTime &&
|
||||
ds.requestedLastTime >= endTime))
|
||||
{
|
||||
//log ("Using cached ds");
|
||||
callback.call (window, testId, ds);
|
||||
return;
|
||||
}
|
||||
|
||||
// this can be optimized, if we request just the bookend bits,
|
||||
// but that's overkill
|
||||
if (ds.firstTime < startTime)
|
||||
startTime = ds.firstTime;
|
||||
if (ds.lastTime > endTime)
|
||||
endTime = ds.lastTime;
|
||||
}
|
||||
|
||||
var cb =
|
||||
function (type, args, obj) {
|
||||
if (args[0] != testId ||
|
||||
args[2] > startTime ||
|
||||
args[3] < endTime)
|
||||
{
|
||||
// not useful for us; there's another
|
||||
// outstanding request for our time range, so wait for that
|
||||
return;
|
||||
}
|
||||
|
||||
self.onDataSetAvailable.unsubscribe(cb, obj);
|
||||
obj.call (window, args[0], args[1]);
|
||||
};
|
||||
this.onDataSetAvailable.subscribe (cb, callback);
|
||||
|
||||
//netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
|
||||
|
||||
var reqstr = getdatacgi + "setid=" + testId;
|
||||
if (startTime)
|
||||
reqstr += "&starttime=" + startTime;
|
||||
if (endTime)
|
||||
reqstr += "&endtime=" + endTime;
|
||||
//raw data is the extra_data column
|
||||
if (this.raw)
|
||||
reqstr += "&raw=1";
|
||||
//log (reqstr);
|
||||
loadJSONDoc(reqstr)
|
||||
.addCallbacks(
|
||||
function (obj) {
|
||||
if (!checkErrorReturn(obj)) return;
|
||||
|
||||
var ds = new TimeValueDataSet(obj.results);
|
||||
|
||||
//this is the the case of a discrete graph - where the entire test run is always requested
|
||||
//so the start and end points are the first and last entries in the returned data set
|
||||
if (!startTime && !endTime) {
|
||||
startTime = ds.data[0];
|
||||
endTime = ds.data[ds.data.length -2];
|
||||
}
|
||||
ds.requestedFirstTime = startTime;
|
||||
ds.requestedLastTime = endTime;
|
||||
self.testData[testId] = ds;
|
||||
if (obj.annotations)
|
||||
ds.annotations = new TimeStringDataSet(obj.annotations);
|
||||
if (obj.baselines)
|
||||
ds.baselines = obj.baselines;
|
||||
if (obj.rawdata)
|
||||
ds.rawdata = obj.rawdata;
|
||||
if (obj.stats)
|
||||
ds.stats = obj.stats;
|
||||
self.onDataSetAvailable.fire(testId, ds, startTime, endTime);
|
||||
},
|
||||
function (obj) {alert ("Error talking to " + getdatacgi + " (" + obj + ")"); log (obj.stack); });
|
||||
},
|
||||
|
||||
clearValueDataSets: function () {
|
||||
//log ("clearvalueDatasets");
|
||||
this.tinderboxTestData = {};
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
function DiscreteTinderboxData() {
|
||||
};
|
||||
|
||||
DiscreteTinderboxData.prototype = {
|
||||
__proto__: new TinderboxData(),
|
||||
|
||||
init: function () {
|
||||
},
|
||||
|
||||
requestTestList: function (limitDate, branch, machine, testname, callback) {
|
||||
var self = this;
|
||||
//netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
|
||||
var limiters = "";
|
||||
|
||||
var tDate = 0;
|
||||
if (limitDate != null) {
|
||||
tDate = new Date().getTime();
|
||||
tDate -= limitDate * 86400 * 1000;
|
||||
//log ("returning test lists greater than this date" + (new Date(tDate)).toGMTString());
|
||||
//TODO hack hack hack
|
||||
tDate = Math.floor(tDate/1000)
|
||||
|
||||
}
|
||||
if (branch != null) limiters += "&branch=" + branch;
|
||||
if (machine != null) limiters += "&machine=" + machine;
|
||||
if (testname != null) limiters += "&test=" + testname;
|
||||
//log("drequestTestList: " + getdatacgi + "type=discrete&datelimit=" + tDate + limiters);
|
||||
loadJSONDoc(getdatacgi + "type=discrete&datelimit=" + tDate + limiters)
|
||||
.addCallbacks(
|
||||
function (obj) {
|
||||
if (!checkErrorReturn(obj)) return;
|
||||
self.testList = obj.results;
|
||||
//log ("testlist: " + self.testList);
|
||||
callback.call(window, self.testList);
|
||||
},
|
||||
function () {alert ("requestTestList: Error talking to " + getdatacgi + ""); });
|
||||
},
|
||||
|
||||
requestSearchList: function (branch, machine, testname, callback) {
|
||||
var self = this;
|
||||
limiters = "";
|
||||
if (branch != null) limiters += "&branch=" + branch;
|
||||
if (machine != null) limiters += "&machine=" + machine;
|
||||
if (testname != null) limiters += "&test=" + testname;
|
||||
//log(getdatacgi + "getlist=1&type=discrete" + limiters);
|
||||
loadJSONDoc(getdatacgi + "getlist=1&type=discrete" + limiters)
|
||||
.addCallbacks(
|
||||
function (obj) {
|
||||
if (!checkErrorReturn(obj)) return;
|
||||
callback.call(window, obj.results);
|
||||
},
|
||||
function () {alert ("requestSearchList: Error talking to " + getdatacgi); });
|
||||
},
|
||||
};
|
||||
function ExtraDataTinderboxData() {
|
||||
};
|
||||
|
||||
ExtraDataTinderboxData.prototype = {
|
||||
__proto__: new TinderboxData(),
|
||||
|
||||
init: function () {
|
||||
},
|
||||
|
||||
requestTestList: function (limitDate, branch, machine, testname, callback) {
|
||||
var self = this;
|
||||
//netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
|
||||
var limiters = "";
|
||||
|
||||
var tDate = 0;
|
||||
if (limitDate != null) {
|
||||
tDate = new Date().getTime();
|
||||
tDate -= limitDate * 86400 * 1000;
|
||||
//log ("returning test lists greater than this date" + (new Date(tDate)).toGMTString());
|
||||
//TODO hack hack hack
|
||||
tDate = Math.floor(tDate/1000)
|
||||
|
||||
}
|
||||
if (branch != null) limiters += "&branch=" + branch;
|
||||
if (machine != null) limiters += "&machine=" + machine;
|
||||
if (testname != null) limiters += "&test=" + testname;
|
||||
//log("drequestTestList: " + getdatacgi + "type=discrete&datelimit=" + tDate + limiters);
|
||||
loadJSONDoc(getdatacgi + "type=discrete&graphby=bydata&datelimit=" + tDate + limiters)
|
||||
.addCallbacks(
|
||||
function (obj) {
|
||||
if (!checkErrorReturn(obj)) return;
|
||||
self.testList = obj.results;
|
||||
//log ("testlist: " + self.testList);
|
||||
callback.call(window, self.testList);
|
||||
},
|
||||
function () {alert ("requestTestList: Error talking to " + getdatacgi + ""); });
|
||||
},
|
||||
|
||||
requestSearchList: function (branch, machine, testname, callback) {
|
||||
var self = this;
|
||||
limiters = "";
|
||||
if (branch != null) limiters += "&branch=" + branch;
|
||||
if (machine != null) limiters += "&machine=" + machine;
|
||||
if (testname != null) limiters += "&test=" + testname;
|
||||
//log(getdatacgi + "getlist=1&type=discrete" + limiters);
|
||||
loadJSONDoc(getdatacgi + "getlist=1&type=discrete" + limiters)
|
||||
.addCallbacks(
|
||||
function (obj) {
|
||||
if (!checkErrorReturn(obj)) return;
|
||||
callback.call(window, obj.results);
|
||||
},
|
||||
function () {alert ("requestSearchList: Error talking to " + getdatacgi); });
|
||||
},
|
||||
// arg1 = startTime, arg2 = endTime, arg3 = callback
|
||||
// arg1 = callback, arg2/arg3 == null
|
||||
requestDataSetFor: function (testId, arg1, arg2, arg3) {
|
||||
var self = this;
|
||||
|
||||
var startTime = arg1;
|
||||
var endTime = arg2;
|
||||
var callback = arg3;
|
||||
|
||||
var tempArray = new Array();
|
||||
tempArray = testId.split("_",2);
|
||||
testId = tempArray[0];
|
||||
var extradata = tempArray[1];
|
||||
|
||||
if (arg1 && arg2 == null && arg3 == null) {
|
||||
callback = arg1;
|
||||
if (this.defaultLoadRange) {
|
||||
startTime = this.defaultLoadRange[0];
|
||||
endTime = this.defaultLoadRange[1];
|
||||
//log ("load range using default", startTime, endTime);
|
||||
} else {
|
||||
startTime = null;
|
||||
endTime = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (testId in this.testData) {
|
||||
var ds = this.testData[testId];
|
||||
//log ("Can maybe use cached?");
|
||||
if ((ds.requestedFirstTime == null && ds.requestedLastTime == null) ||
|
||||
(ds.requestedFirstTime <= startTime &&
|
||||
ds.requestedLastTime >= endTime))
|
||||
{
|
||||
//log ("Using cached ds");
|
||||
callback.call (window, testId, ds);
|
||||
return;
|
||||
}
|
||||
|
||||
// this can be optimized, if we request just the bookend bits,
|
||||
// but that's overkill
|
||||
if (ds.firstTime < startTime)
|
||||
startTime = ds.firstTime;
|
||||
if (ds.lastTime > endTime)
|
||||
endTime = ds.lastTime;
|
||||
}
|
||||
|
||||
var cb =
|
||||
function (type, args, obj) {
|
||||
if (args[0] != testId ||
|
||||
args[2] > startTime ||
|
||||
args[3] < endTime)
|
||||
{
|
||||
// not useful for us; there's another
|
||||
// outstanding request for our time range, so wait for that
|
||||
return;
|
||||
}
|
||||
|
||||
self.onDataSetAvailable.unsubscribe(cb, obj);
|
||||
obj.call (window, args[0], args[1]);
|
||||
};
|
||||
this.onDataSetAvailable.subscribe (cb, callback);
|
||||
|
||||
//netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
|
||||
|
||||
var reqstr = getdatacgi + "setid=" + testId;
|
||||
if (startTime)
|
||||
reqstr += "&starttime=" + startTime;
|
||||
if (endTime)
|
||||
reqstr += "&endtime=" + endTime;
|
||||
//raw data is the extra_data column
|
||||
if (this.raw)
|
||||
reqstr += "&raw=1";
|
||||
reqstr += "&graphby=bydata";
|
||||
reqstr += "&extradata=" + extradata;
|
||||
//log (reqstr);
|
||||
loadJSONDoc(reqstr)
|
||||
.addCallbacks(
|
||||
function (obj) {
|
||||
if (!checkErrorReturn(obj)) return;
|
||||
|
||||
var ds = new TimeValueDataSet(obj.results);
|
||||
|
||||
//this is the the case of a discrete graph - where the entire test run is always requested
|
||||
//so the start and end points are the first and last entries in the returned data set
|
||||
if (!startTime && !endTime) {
|
||||
startTime = ds.data[0];
|
||||
endTime = ds.data[ds.data.length -2];
|
||||
}
|
||||
ds.requestedFirstTime = startTime;
|
||||
ds.requestedLastTime = endTime;
|
||||
self.testData[testId] = ds;
|
||||
if (obj.annotations)
|
||||
ds.annotations = new TimeStringDataSet(obj.annotations);
|
||||
if (obj.baselines)
|
||||
ds.baselines = obj.baselines;
|
||||
if (obj.rawdata)
|
||||
ds.rawdata = obj.rawdata;
|
||||
if (obj.stats)
|
||||
ds.stats = obj.stats;
|
||||
self.onDataSetAvailable.fire(testId, ds, startTime, endTime);
|
||||
},
|
||||
function (obj) {alert ("Error talking to " + getdatacgi + " (" + obj + ")"); log (obj.stack); });
|
||||
},
|
||||
};
|
||||
@@ -1,381 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is new-graph code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Alice Nodelman <anodelman@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var GraphFormModules = [];
|
||||
var GraphFormModuleCount = 0;
|
||||
|
||||
function DiscreteGraphFormModule(userConfig, userName) {
|
||||
GraphFormModuleCount++;
|
||||
//log("userName: " + userName);
|
||||
//this.__proto__.__proto__.constructor.call(this, "graphForm" + GraphFormModuleCount, userConfig, userName);
|
||||
this.init("graphForm" + GraphFormModuleCount, userConfig, userName);
|
||||
}
|
||||
|
||||
DiscreteGraphFormModule.prototype = {
|
||||
__proto__: new YAHOO.widget.Module(),
|
||||
|
||||
imageRoot: "",
|
||||
|
||||
testId: null,
|
||||
testIds: null,
|
||||
testText: "",
|
||||
baseline: false,
|
||||
average: false,
|
||||
name: "",
|
||||
limitDays: null,
|
||||
isLimit: null,
|
||||
onLoadingDone : new YAHOO.util.CustomEvent("onloadingdone"),
|
||||
onLoading : new YAHOO.util.CustomEvent("onloading"),
|
||||
addedInitialInfo : new YAHOO.util.CustomEvent("addedinitialinfo"),
|
||||
|
||||
init: function (el, userConfig, userName) {
|
||||
var self = this;
|
||||
//log("el " + el + " userConfig " + userConfig + " userName " + userName);
|
||||
this.__proto__.__proto__.init.call(this, el/*, userConfig*/);
|
||||
|
||||
this.cfg = new YAHOO.util.Config(this);
|
||||
this.cfg.addProperty("testid", { suppressEvent: true });
|
||||
this.cfg.addProperty("average", { suppressEvent: true });
|
||||
this.cfg.addProperty("baseline", { suppressEvent: true });
|
||||
|
||||
if (userConfig)
|
||||
this.cfg.applyConfig(userConfig, true);
|
||||
|
||||
var form, td, el;
|
||||
var tbl;
|
||||
var tbl_row;
|
||||
var tbl_col;
|
||||
tbl = new TABLE({});
|
||||
tbl_row = new TR({});
|
||||
tbl_col = new TD({colspan: 2});
|
||||
appendChildNodes(tbl_col,"Limit selection list by:");
|
||||
appendChildNodes(tbl_row, tbl_col);
|
||||
tbl_col = new TD({});
|
||||
appendChildNodes(tbl_col,"Choose test(s) to graph:");
|
||||
appendChildNodes(tbl_row, tbl_col);
|
||||
tbl.appendChild(tbl_row);
|
||||
|
||||
|
||||
tbl_row = new TR({});
|
||||
|
||||
form = new DIV({ class: "graphform-line" });
|
||||
|
||||
tbl_col = new TD({});
|
||||
el = new INPUT({ name: "dataload" + GraphFormModules.length,
|
||||
id: "all-days-radio",
|
||||
type: "radio",
|
||||
checked: 1,
|
||||
onchange: function(event) { self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
|
||||
tbl_col.appendChild(el);
|
||||
appendChildNodes(tbl_col, "all tests");
|
||||
|
||||
tbl_col.appendChild(new DIV({}));
|
||||
el = new INPUT({ name: "dataload" + GraphFormModules.length,
|
||||
type: "radio",
|
||||
onchange: function(event) { self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);} });
|
||||
this.isLimit = el;
|
||||
tbl_col.appendChild(el);
|
||||
appendChildNodes(tbl_col, "previous ");
|
||||
el = new INPUT({ name: "load-days-entry",
|
||||
id: "load-days-entry",
|
||||
type: "text",
|
||||
size: "3",
|
||||
value: "5",
|
||||
onchange: function(event) { if (self.isLimit.checked) {
|
||||
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);} } });
|
||||
this.limitDays = el;
|
||||
tbl_col.appendChild(el);
|
||||
appendChildNodes(tbl_col, " days");
|
||||
|
||||
tbl_row.appendChild(tbl_col);
|
||||
|
||||
tbl_col = new TD({});
|
||||
appendChildNodes(tbl_col, "Branch: ");
|
||||
appendChildNodes(tbl_col, new BR({}));
|
||||
el = new SELECT({ name: "branchname",
|
||||
class: "other",
|
||||
size: 5,
|
||||
onchange: function(event) { if (self.isLimit.checked) {
|
||||
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
|
||||
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
|
||||
this.branchSelect = el;
|
||||
Tinderbox.requestSearchList(1, null, null, function (list) {
|
||||
var opts = [];
|
||||
opts.push(new OPTION({value: null, selected: true}, "all"));
|
||||
for each (var listvalue in list) {
|
||||
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
|
||||
}
|
||||
replaceChildNodes(self.branchSelect, opts);
|
||||
});
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
tbl_col = new TD({rowspan: 2, colspan: 2});
|
||||
span = new SPAN({id: "listname"});
|
||||
appendChildNodes(tbl_col, span);
|
||||
appendChildNodes(tbl_col, new BR({}));
|
||||
el = new SELECT({ name: "testname",
|
||||
class: "testname",
|
||||
multiple: true,
|
||||
center: true,
|
||||
size: 20,
|
||||
onchange: function(event) { self.onChangeTest(); } });
|
||||
this.testSelect = el;
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
tbl.appendChild(tbl_row);
|
||||
tbl_row = new TR({});
|
||||
|
||||
tbl_col = new TD({});
|
||||
appendChildNodes(tbl_col, "Machine: ");
|
||||
appendChildNodes(tbl_col, new BR({}));
|
||||
el = new SELECT({ name: "machinename",
|
||||
class: "other",
|
||||
size: 5,
|
||||
onchange: function(event) { if (self.isLimit.checked) {
|
||||
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
|
||||
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
|
||||
this.machineSelect = el;
|
||||
Tinderbox.requestSearchList(null, 1, null, function (list) {
|
||||
var opts = [];
|
||||
opts.push(new OPTION({value: null, selected: true}, "all"));
|
||||
for each (var listvalue in list) {
|
||||
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
|
||||
}
|
||||
replaceChildNodes(self.machineSelect, opts);
|
||||
});
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
|
||||
tbl_col = new TD({});
|
||||
appendChildNodes(tbl_col, "Test name: ");
|
||||
appendChildNodes(tbl_col, new BR({}));
|
||||
el = new SELECT({ name: "testtypename",
|
||||
class: "other",
|
||||
size: 5,
|
||||
onchange: function(event) { if (self.isLimit.checked) {
|
||||
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
|
||||
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
|
||||
this.testtypeSelect = el;
|
||||
|
||||
var forceTestIds = null;
|
||||
this.average = false;
|
||||
if (userConfig) {
|
||||
forceTestIds = userConfig;
|
||||
}
|
||||
//log ("userName: " + userName);
|
||||
|
||||
Tinderbox.requestSearchList(null, null, 1, function (list) {
|
||||
var opts = [];
|
||||
//opts.push(new OPTION({value: null, selected: true}, "all"));
|
||||
for each (var listvalue in list) {
|
||||
if ((userName) && (userName == listvalue.value)) {
|
||||
opts.push(new OPTION({ value: listvalue.value, selected : true}, listvalue.value));
|
||||
}
|
||||
else {
|
||||
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
|
||||
}
|
||||
}
|
||||
replaceChildNodes(self.testtypeSelect, opts);
|
||||
if (forceTestIds == null) {
|
||||
self.testtypeSelect.options[0].selected = true;
|
||||
self.update(null, null, null, self.testtypeSelect.value, forceTestIds);
|
||||
}
|
||||
else {
|
||||
self.update(null, null, null, userName, forceTestIds);
|
||||
}
|
||||
});
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
/*
|
||||
tbl_col = new TD({rowspan: 2, colspan: 2});
|
||||
el = new SELECT({ name: "testname",
|
||||
class: "testname",
|
||||
multiple: true,
|
||||
size: 20,
|
||||
onchange: function(event) { self.onChangeTest(); } });
|
||||
this.testSelect = el;
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
*/
|
||||
tbl.appendChild(tbl_row);
|
||||
form.appendChild(tbl);
|
||||
|
||||
|
||||
|
||||
this.setBody (form);
|
||||
/*
|
||||
var forceTestIds = null;
|
||||
this.average = false;
|
||||
if (userConfig) {
|
||||
forceTestIds = userConfig;
|
||||
}
|
||||
*/
|
||||
//self.update(null, null, null, null, forceTestIds);
|
||||
GraphFormModules.push(this);
|
||||
},
|
||||
|
||||
getQueryString: function (prefix) {
|
||||
var qstring = '';
|
||||
ctr = 1;
|
||||
for each (var opt in this.testSelect.options) {
|
||||
if (opt.selected) {
|
||||
prefixed = prefix + ctr;
|
||||
qstring += "&" + prefixed + "tid=" + opt.value + "&" + prefixed + "bl=" + (this.baseline ? "1" : "0")
|
||||
+ "&" + prefixed + "avg=" + (this.average? "1" : "0");
|
||||
ctr++
|
||||
}
|
||||
}
|
||||
return qstring;
|
||||
},
|
||||
|
||||
getDumpString: function () {
|
||||
var prefix = '';
|
||||
var dstring = '';
|
||||
for each (var opt in this.testSelect.options) {
|
||||
if (opt.selected) {
|
||||
dstring += prefix + "setid=" + opt.value;
|
||||
prefix = "&";
|
||||
}
|
||||
}
|
||||
return dstring;
|
||||
},
|
||||
|
||||
onChangeTest: function (forceTestIds) {
|
||||
this.testId = this.testSelect.value;
|
||||
//log("setting testId: " + this.testId);
|
||||
this.testIds = [];
|
||||
for each (var opt in this.testSelect.options) {
|
||||
if (opt.selected) {
|
||||
//log("opt: " + opt.value);
|
||||
this.testIds.push([opt.value, opt.text]);
|
||||
}
|
||||
}
|
||||
//log("testIDs: " + this.testIds);
|
||||
//log(this.testSelect.options[this.testSelect.selectedIndex].text);
|
||||
this.testText = this.testSelect.options[this.testSelect.selectedIndex];
|
||||
this.addedInitialInfo.fire();
|
||||
this.name = this.testtypeSelect.value;
|
||||
},
|
||||
|
||||
onBaseLineRadioClick: function () {
|
||||
GraphFormModules.forEach(function (g) { g.baseline = false; });
|
||||
this.baseline = true;
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
var nf = [];
|
||||
for each (var f in GraphFormModules) {
|
||||
if (f != this)
|
||||
nf.push(f);
|
||||
}
|
||||
GraphFormModules = nf;
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
update: function (limitD, branch, machine, testname, forceTestIds) {
|
||||
var self = this;
|
||||
this.onLoading.fire("updating test list");
|
||||
//log ("attempting to update graphformmodule, forceTestIds " + forceTestIds);
|
||||
Tinderbox.requestTestList(limitD, branch, machine, testname, function (tests) {
|
||||
var opts = [];
|
||||
var branch_opts = [];
|
||||
if (tests == '') {
|
||||
log("empty test list");
|
||||
self.onLoadingDone.fire();
|
||||
replaceChildNodes(self.testSelect, null);
|
||||
btn = getElement("graphbutton");
|
||||
btn.disabled = true;
|
||||
return;
|
||||
}
|
||||
// let's sort by machine name
|
||||
var sortedTests = Array.sort(tests, function (a, b) {
|
||||
if (a.machine < b.machine) return -1;
|
||||
if (a.machine > b.machine) return 1;
|
||||
if (a.test < b.test) return -1;
|
||||
if (a.test > b.test) return 1;
|
||||
if (a.test_type < b.test_type) return -1;
|
||||
if (a.test_type > b.test_type) return 1;
|
||||
if (a.date < b.date) return -1;
|
||||
if (a.date > b.date) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
for each (var test in sortedTests) {
|
||||
var d = new Date(test.date*1000);
|
||||
var s1 = (d.getHours() < 10 ? "0" : "") + d.getHours() + (d.getMinutes() < 10 ? ":0" : ":") + d.getMinutes() +
|
||||
//(d.getSeconds() < 10 ? ":0" : ":") + d.getSeconds() +
|
||||
" " + (d.getDate() < 10 ? "0" : "") + d.getDate();
|
||||
s1 += "/" + MONTH_ABBREV[d.getMonth()] + "/" + (d.getFullYear() -2000 < 10 ? "0" : "") + (d.getFullYear() - 2000);
|
||||
//(d.getYear() + 1900);
|
||||
var padstr = "--------------------";
|
||||
var tstr = "" + //test.test + padstr.substr(0, 20-test.test.length) +
|
||||
test.branch.toString() + padstr.substr(0, 6-test.branch.toString().length) +
|
||||
"-" + test.machine + padstr.substr(0, 10-test.machine.length) +
|
||||
"-" + s1;
|
||||
startSelected = false;
|
||||
if (forceTestIds != null) {
|
||||
if ((forceTestIds == test.id) || (forceTestIds.indexOf(Number(test.id)) > -1)) {
|
||||
startSelected = true;
|
||||
}
|
||||
}
|
||||
if (startSelected) {
|
||||
//log("starting with an initial selection");
|
||||
opts.push(new OPTION({ value: test.id, selected: true}, tstr));
|
||||
}
|
||||
else {
|
||||
opts.push(new OPTION({ value: test.id}, tstr));
|
||||
}
|
||||
}
|
||||
replaceChildNodes(self.testSelect, opts);
|
||||
|
||||
if (forceTestIds == null) {
|
||||
self.testSelect.options[0].selected = true;
|
||||
//self.testSelect.value = sortedTests[0].id;
|
||||
}
|
||||
replaceChildNodes("listname", null);
|
||||
appendChildNodes("listname","Select from " + testname + ":");
|
||||
btn = getElement("graphbutton");
|
||||
btn.disabled = false;
|
||||
setTimeout(function () { self.onChangeTest(forceTestIds); }, 0);
|
||||
self.onLoadingDone.fire();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is new-graph code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Alice Nodelman <anodelman@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var GraphFormModules = [];
|
||||
var GraphFormModuleCount = 0;
|
||||
|
||||
function ExtraDataGraphFormModule(userConfig, userName) {
|
||||
GraphFormModuleCount++;
|
||||
//log("userName: " + userName);
|
||||
//this.__proto__.__proto__.constructor.call(this, "graphForm" + GraphFormModuleCount, userConfig, userName);
|
||||
this.init("graphForm" + GraphFormModuleCount, userConfig, userName);
|
||||
}
|
||||
|
||||
ExtraDataGraphFormModule.prototype = {
|
||||
__proto__: new YAHOO.widget.Module(),
|
||||
|
||||
imageRoot: "",
|
||||
|
||||
testId: null,
|
||||
testIds: null,
|
||||
testText: "",
|
||||
baseline: false,
|
||||
average: false,
|
||||
name: "",
|
||||
limitDays: null,
|
||||
isLimit: null,
|
||||
onLoadingDone : new YAHOO.util.CustomEvent("onloadingdone"),
|
||||
onLoading : new YAHOO.util.CustomEvent("onloading"),
|
||||
addedInitialInfo : new YAHOO.util.CustomEvent("addedinitialinfo"),
|
||||
|
||||
init: function (el, userConfig, userName) {
|
||||
var self = this;
|
||||
//log("el " + el + " userConfig " + userConfig + " userName " + userName);
|
||||
this.__proto__.__proto__.init.call(this, el/*, userConfig*/);
|
||||
|
||||
this.cfg = new YAHOO.util.Config(this);
|
||||
this.cfg.addProperty("testid", { suppressEvent: true });
|
||||
this.cfg.addProperty("average", { suppressEvent: true });
|
||||
this.cfg.addProperty("baseline", { suppressEvent: true });
|
||||
|
||||
if (userConfig)
|
||||
this.cfg.applyConfig(userConfig, true);
|
||||
|
||||
var form, td, el;
|
||||
var tbl;
|
||||
var tbl_row;
|
||||
var tbl_col;
|
||||
tbl = new TABLE({});
|
||||
tbl_row = new TR({});
|
||||
tbl_col = new TD({colspan: 2});
|
||||
appendChildNodes(tbl_col,"Limit selection list by:");
|
||||
appendChildNodes(tbl_row, tbl_col);
|
||||
tbl_col = new TD({});
|
||||
appendChildNodes(tbl_col,"Choose test(s) to graph:");
|
||||
appendChildNodes(tbl_row, tbl_col);
|
||||
tbl.appendChild(tbl_row);
|
||||
|
||||
|
||||
tbl_row = new TR({});
|
||||
|
||||
form = new DIV({ class: "graphform-line" });
|
||||
|
||||
tbl_col = new TD({});
|
||||
el = new INPUT({ name: "dataload" + GraphFormModules.length,
|
||||
id: "all-days-radio",
|
||||
type: "radio",
|
||||
checked: 1,
|
||||
onchange: function(event) { self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
|
||||
tbl_col.appendChild(el);
|
||||
appendChildNodes(tbl_col, "all tests");
|
||||
|
||||
tbl_col.appendChild(new DIV({}));
|
||||
el = new INPUT({ name: "dataload" + GraphFormModules.length,
|
||||
type: "radio",
|
||||
onchange: function(event) { self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);} });
|
||||
this.isLimit = el;
|
||||
tbl_col.appendChild(el);
|
||||
appendChildNodes(tbl_col, "previous ");
|
||||
el = new INPUT({ name: "load-days-entry",
|
||||
id: "load-days-entry",
|
||||
type: "text",
|
||||
size: "3",
|
||||
value: "5",
|
||||
onchange: function(event) { if (self.isLimit.checked) {
|
||||
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);} } });
|
||||
this.limitDays = el;
|
||||
tbl_col.appendChild(el);
|
||||
appendChildNodes(tbl_col, " days");
|
||||
|
||||
tbl_row.appendChild(tbl_col);
|
||||
|
||||
tbl_col = new TD({});
|
||||
appendChildNodes(tbl_col, "Branch: ");
|
||||
appendChildNodes(tbl_col, new BR({}));
|
||||
el = new SELECT({ name: "branchname",
|
||||
class: "other",
|
||||
size: 5,
|
||||
onchange: function(event) { if (self.isLimit.checked) {
|
||||
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
|
||||
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
|
||||
this.branchSelect = el;
|
||||
Tinderbox.requestSearchList(1, null, null, function (list) {
|
||||
var opts = [];
|
||||
opts.push(new OPTION({value: null, selected: true}, "all"));
|
||||
for each (var listvalue in list) {
|
||||
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
|
||||
}
|
||||
replaceChildNodes(self.branchSelect, opts);
|
||||
});
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
tbl_col = new TD({rowspan: 2, colspan: 2});
|
||||
span = new SPAN({id: "listname"});
|
||||
appendChildNodes(tbl_col, span);
|
||||
appendChildNodes(tbl_col, new BR({}));
|
||||
el = new SELECT({ name: "testname",
|
||||
class: "testname",
|
||||
multiple: true,
|
||||
center: true,
|
||||
size: 20,
|
||||
onchange: function(event) { self.onChangeTest(); } });
|
||||
this.testSelect = el;
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
tbl.appendChild(tbl_row);
|
||||
tbl_row = new TR({});
|
||||
|
||||
tbl_col = new TD({});
|
||||
appendChildNodes(tbl_col, "Machine: ");
|
||||
appendChildNodes(tbl_col, new BR({}));
|
||||
el = new SELECT({ name: "machinename",
|
||||
class: "other",
|
||||
size: 5,
|
||||
onchange: function(event) { if (self.isLimit.checked) {
|
||||
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
|
||||
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
|
||||
this.machineSelect = el;
|
||||
Tinderbox.requestSearchList(null, 1, null, function (list) {
|
||||
var opts = [];
|
||||
opts.push(new OPTION({value: null, selected: true}, "all"));
|
||||
for each (var listvalue in list) {
|
||||
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
|
||||
}
|
||||
replaceChildNodes(self.machineSelect, opts);
|
||||
});
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
|
||||
tbl_col = new TD({});
|
||||
appendChildNodes(tbl_col, "Test name: ");
|
||||
appendChildNodes(tbl_col, new BR({}));
|
||||
el = new SELECT({ name: "testtypename",
|
||||
class: "other",
|
||||
size: 5,
|
||||
onchange: function(event) { if (self.isLimit.checked) {
|
||||
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
|
||||
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
|
||||
this.testtypeSelect = el;
|
||||
|
||||
var forceTestIds = null;
|
||||
this.average = false;
|
||||
if (userConfig) {
|
||||
forceTestIds = userConfig;
|
||||
}
|
||||
//log ("userName: " + userName);
|
||||
|
||||
Tinderbox.requestSearchList(null, null, 1, function (list) {
|
||||
var opts = [];
|
||||
//opts.push(new OPTION({value: null, selected: true}, "all"));
|
||||
for each (var listvalue in list) {
|
||||
if ((userName) && (userName == listvalue.value)) {
|
||||
opts.push(new OPTION({ value: listvalue.value, selected : true}, listvalue.value));
|
||||
}
|
||||
else {
|
||||
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
|
||||
}
|
||||
}
|
||||
replaceChildNodes(self.testtypeSelect, opts);
|
||||
if (forceTestIds == null) {
|
||||
self.testtypeSelect.options[0].selected = true;
|
||||
self.update(null, null, null, self.testtypeSelect.value, forceTestIds);
|
||||
}
|
||||
else {
|
||||
self.update(null, null, null, userName, forceTestIds);
|
||||
}
|
||||
});
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
/*
|
||||
tbl_col = new TD({rowspan: 2, colspan: 2});
|
||||
el = new SELECT({ name: "testname",
|
||||
class: "testname",
|
||||
multiple: true,
|
||||
size: 20,
|
||||
onchange: function(event) { self.onChangeTest(); } });
|
||||
this.testSelect = el;
|
||||
tbl_col.appendChild(el);
|
||||
tbl_row.appendChild(tbl_col);
|
||||
*/
|
||||
tbl.appendChild(tbl_row);
|
||||
form.appendChild(tbl);
|
||||
|
||||
|
||||
|
||||
this.setBody (form);
|
||||
/*
|
||||
var forceTestIds = null;
|
||||
this.average = false;
|
||||
if (userConfig) {
|
||||
forceTestIds = userConfig;
|
||||
}
|
||||
*/
|
||||
//self.update(null, null, null, null, forceTestIds);
|
||||
GraphFormModules.push(this);
|
||||
},
|
||||
|
||||
getQueryString: function (prefix) {
|
||||
var qstring = '';
|
||||
ctr = 1;
|
||||
for each (var opt in this.testSelect.options) {
|
||||
if (opt.selected) {
|
||||
prefixed = prefix + ctr;
|
||||
qstring += "&" + prefixed + "tid=" + opt.value + "&" + prefixed + "bl=" + (this.baseline ? "1" : "0")
|
||||
+ "&" + prefixed + "avg=" + (this.average? "1" : "0");
|
||||
ctr++
|
||||
}
|
||||
}
|
||||
return qstring;
|
||||
},
|
||||
|
||||
getDumpString: function () {
|
||||
var prefix = '';
|
||||
var dstring = '';
|
||||
for each (var opt in this.testSelect.options) {
|
||||
if (opt.selected) {
|
||||
dstring += prefix + "setid=" + opt.value;
|
||||
prefix = "&";
|
||||
}
|
||||
}
|
||||
return dstring;
|
||||
},
|
||||
|
||||
onChangeTest: function (forceTestIds) {
|
||||
this.testId = this.testSelect.value;
|
||||
//log("setting testId: " + this.testId);
|
||||
this.testIds = [];
|
||||
for each (var opt in this.testSelect.options) {
|
||||
if (opt.selected) {
|
||||
//log("opt: " + opt.value);
|
||||
this.testIds.push([opt.value, opt.text]);
|
||||
}
|
||||
}
|
||||
//log("testIDs: " + this.testIds);
|
||||
//log(this.testSelect.options[this.testSelect.selectedIndex].text);
|
||||
this.testText = this.testSelect.options[this.testSelect.selectedIndex];
|
||||
this.addedInitialInfo.fire();
|
||||
this.name = this.testtypeSelect.value;
|
||||
},
|
||||
|
||||
onBaseLineRadioClick: function () {
|
||||
GraphFormModules.forEach(function (g) { g.baseline = false; });
|
||||
this.baseline = true;
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
var nf = [];
|
||||
for each (var f in GraphFormModules) {
|
||||
if (f != this)
|
||||
nf.push(f);
|
||||
}
|
||||
GraphFormModules = nf;
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
update: function (limitD, branch, machine, testname, forceTestIds) {
|
||||
var self = this;
|
||||
this.onLoading.fire("updating test list");
|
||||
//log ("attempting to update graphformmodule, forceTestIds " + forceTestIds);
|
||||
Tinderbox.requestTestList(limitD, branch, machine, testname, function (tests) {
|
||||
var opts = [];
|
||||
var branch_opts = [];
|
||||
if (tests == '') {
|
||||
log("empty test list");
|
||||
self.onLoadingDone.fire();
|
||||
replaceChildNodes(self.testSelect, null);
|
||||
btn = getElement("graphbutton");
|
||||
btn.disabled = true;
|
||||
return;
|
||||
}
|
||||
// let's sort by machine name
|
||||
var sortedTests = Array.sort(tests, function (a, b) {
|
||||
if (a.machine < b.machine) return -1;
|
||||
if (a.machine > b.machine) return 1;
|
||||
if (a.test < b.test) return -1;
|
||||
if (a.test > b.test) return 1;
|
||||
if (a.test_type < b.test_type) return -1;
|
||||
if (a.test_type > b.test_type) return 1;
|
||||
if (a.data < b.data) return -1;
|
||||
if (a.data > b.data) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
for each (var test in sortedTests) {
|
||||
var s1 = test.data;
|
||||
var padstr = "--------------------";
|
||||
var tstr = "" + //test.test + padstr.substr(0, 20-test.test.length) +
|
||||
test.branch.toString() + padstr.substr(0, 6-test.branch.toString().length) +
|
||||
"-" + test.machine + padstr.substr(0, 10-test.machine.length) +
|
||||
"-" + s1;
|
||||
startSelected = false;
|
||||
if (forceTestIds != null) {
|
||||
if ((forceTestIds == test.id) || (forceTestIds.indexOf(Number(test.id)) > -1)) {
|
||||
startSelected = true;
|
||||
}
|
||||
}
|
||||
if (startSelected) {
|
||||
//log("starting with an initial selection");
|
||||
opts.push(new OPTION({ value: test.id + "_" + test.data, selected: true}, tstr));
|
||||
}
|
||||
else {
|
||||
opts.push(new OPTION({ value: test.id + "_" + test.data}, tstr));
|
||||
}
|
||||
}
|
||||
replaceChildNodes(self.testSelect, opts);
|
||||
|
||||
if (forceTestIds == null) {
|
||||
self.testSelect.options[0].selected = true;
|
||||
//self.testSelect.value = sortedTests[0].id;
|
||||
}
|
||||
replaceChildNodes("listname", null);
|
||||
appendChildNodes("listname","Select from " + testname + ":");
|
||||
btn = getElement("graphbutton");
|
||||
btn.disabled = false;
|
||||
setTimeout(function () { self.onChangeTest(forceTestIds); }, 0);
|
||||
self.onLoadingDone.fire();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
|
||||
.graphconfig {
|
||||
background-color: #cccccc;
|
||||
-moz-border-radius: 10px 0 0 10px;
|
||||
padding: 10px;
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
.dgraphconfig {
|
||||
background-color: #cccccc;
|
||||
-moz-border-radius: 10px 0 0 10px;
|
||||
padding: 10px;
|
||||
width: 7em;
|
||||
}
|
||||
|
||||
.graphconfig-list {
|
||||
background-color: #cccccc;
|
||||
-moz-border-radius: 0 10px 10px 0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* Yuck */
|
||||
|
||||
.graphform-line, .baseline {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.graphform-first-span {
|
||||
/* font-weight: bold; */
|
||||
}
|
||||
|
||||
/*
|
||||
#graphforms div .bd .graphform-line .graphform-first-span:after {
|
||||
content: "For ";
|
||||
}
|
||||
|
||||
.module + .module .bd .graphform-line .graphform-first-span:after {
|
||||
content: "and " ! important;
|
||||
}
|
||||
*/
|
||||
|
||||
select.tinderbox, select.testname {
|
||||
font-family: monospace;
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
select.other {
|
||||
font-family: monospace;
|
||||
width: 225px;
|
||||
}
|
||||
|
||||
.plusminus {
|
||||
padding: 3px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.plusminus:hover {
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.plusminushidden {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.y-axis-label {
|
||||
font-family: Tahoma, Verdana, Vera Sans, "Bitstream Vera Sans", Arial, Helvetica, sans-serif;
|
||||
font-size: 75%;
|
||||
vertical-align: middle;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.x-axis-label {
|
||||
font-family: Tahoma, Verdana, Vera Sans, "Bitstream Vera Sans", Arial, Helvetica, sans-serif;
|
||||
font-size: 75%;
|
||||
padding: 0px;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.status {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
/* debug */
|
||||
/*div { border: 1px solid blue; }*/
|
||||
@@ -1,661 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is new-graph code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Alice Nodelman <anodelman@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// all times are in seconds
|
||||
|
||||
const ONE_HOUR_SECONDS = 60*60;
|
||||
const ONE_DAY_SECONDS = 24*ONE_HOUR_SECONDS;
|
||||
const ONE_WEEK_SECONDS = 7*ONE_DAY_SECONDS;
|
||||
const ONE_YEAR_SECONDS = 365*ONE_DAY_SECONDS; // leap years whatever.
|
||||
|
||||
const MONTH_ABBREV = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
|
||||
|
||||
const CONTINUOUS_GRAPH = 0;
|
||||
const DISCRETE_GRAPH = 1;
|
||||
const DATA_GRAPH = 2;
|
||||
|
||||
const bonsaicgi = "bonsaibouncer.cgi";
|
||||
|
||||
// more days than this and we'll force user confirmation for the bonsai query
|
||||
const bonsaiNoForceDays = 90;
|
||||
|
||||
// the default average interval
|
||||
var gAverageInterval = 3*ONE_HOUR_SECONDS;
|
||||
var gCurrentLoadRange = null;
|
||||
var gForceBonsai = false;
|
||||
|
||||
var Tinderbox;
|
||||
var BigPerfGraph;
|
||||
var SmallPerfGraph;
|
||||
var Bonsai;
|
||||
var graphType;
|
||||
|
||||
function loadingDone(graphTypePref) {
|
||||
//createLoggingPane(true);
|
||||
graphType = graphTypePref;
|
||||
|
||||
if (graphType == CONTINUOUS_GRAPH) {
|
||||
Tinderbox = new TinderboxData();
|
||||
SmallPerfGraph = new CalendarTimeGraph("smallgraph");
|
||||
BigPerfGraph = new CalendarTimeGraph("graph");
|
||||
onDataLoadChanged();
|
||||
} else if (graphType == DATA_GRAPH) {
|
||||
Tinderbox = new ExtraDataTinderboxData();
|
||||
SmallPerfGraph = new CalendarTimeGraph("smallgraph");
|
||||
BigPerfGraph = new CalendarTimeGraph("graph");
|
||||
}
|
||||
else {
|
||||
Tinderbox = new DiscreteTinderboxData();
|
||||
Tinderbox.raw = 1;
|
||||
SmallPerfGraph = new DiscreteGraph("smallgraph");
|
||||
BigPerfGraph = new DiscreteGraph("graph");
|
||||
onDiscreteDataLoadChanged();
|
||||
}
|
||||
|
||||
Tinderbox.init();
|
||||
|
||||
if (BonsaiService)
|
||||
Bonsai = new BonsaiService();
|
||||
|
||||
SmallPerfGraph.yLabelHeight = 20;
|
||||
SmallPerfGraph.setSelectionType("range");
|
||||
BigPerfGraph.setSelectionType("cursor");
|
||||
BigPerfGraph.setCursorType("free");
|
||||
|
||||
|
||||
SmallPerfGraph.onSelectionChanged.
|
||||
subscribe (function (type, args, obj) {
|
||||
log ("selchanged");
|
||||
|
||||
if (args[0] == "range") {
|
||||
if (args[1] && args[2]) {
|
||||
var t1 = args[1];
|
||||
var t2 = args[2];
|
||||
|
||||
var foundIndexes = [];
|
||||
|
||||
// make sure that there are at least two points
|
||||
// on at least one graph for this
|
||||
var foundPoints = false;
|
||||
var dss = BigPerfGraph.dataSets;
|
||||
for (var i = 0; i < dss.length; i++) {
|
||||
var idcs = dss[i].indicesForTimeRange(t1, t2);
|
||||
if (idcs[1] - idcs[0] > 1) {
|
||||
foundPoints = true;
|
||||
break;
|
||||
}
|
||||
foundIndexes.push(idcs);
|
||||
}
|
||||
|
||||
if (!foundPoints) {
|
||||
// we didn't find at least two points in at least
|
||||
// one graph; so munge the time numbers until we do.
|
||||
log("Orig t1 " + t1 + " t2 " + t2);
|
||||
|
||||
for (var i = 0; i < dss.length; i++) {
|
||||
if (foundIndexes[i][0] > 0) {
|
||||
t1 = Math.min(dss[i].data[(foundIndexes[i][0] - 1) * 2], t1);
|
||||
} else if (foundIndexes[i][1]+1 < (ds.data.length/2)) {
|
||||
t2 = Math.max(dss[i].data[(foundIndexes[i][1] + 1) * 2], t2);
|
||||
}
|
||||
}
|
||||
|
||||
log("Fixed t1 " + t1 + " t2 " + t2);
|
||||
}
|
||||
|
||||
BigPerfGraph.setTimeRange (t1, t2);
|
||||
} else {
|
||||
BigPerfGraph.setTimeRange (SmallPerfGraph.startTime, SmallPerfGraph.endTime);
|
||||
}
|
||||
BigPerfGraph.autoScale();
|
||||
BigPerfGraph.redraw();
|
||||
}
|
||||
|
||||
updateLinkToThis();
|
||||
updateDumpToCsv();
|
||||
});
|
||||
|
||||
if (graphType == CONTINUOUS_GRAPH) {
|
||||
BigPerfGraph.onCursorMoved.
|
||||
subscribe (function (type, args, obj) {
|
||||
var time = args[0];
|
||||
var val = args[1];
|
||||
if (time != null && val != null) {
|
||||
// cheat
|
||||
showStatus("Date: " + formatTime(time) + " Value: " + val.toFixed(2));
|
||||
} else {
|
||||
showStatus(null);
|
||||
}
|
||||
});
|
||||
BigPerfGraph.onNewGraph.
|
||||
subscribe (function(type, args, obj) {
|
||||
if (args[0].length >= GraphFormModules.length) {
|
||||
clearLoadingAnimation();
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (graphType == DATA_GRAPH) {
|
||||
BigPerfGraph.onCursorMoved.
|
||||
subscribe (function (type, args, obj) {
|
||||
var time = args[0];
|
||||
var val = args[1];
|
||||
if (time != null && val != null) {
|
||||
// cheat
|
||||
showStatus("Date: " + formatTime(time) + " Value: " + val.toFixed(2));
|
||||
} else {
|
||||
showStatus(null);
|
||||
}
|
||||
});
|
||||
BigPerfGraph.onNewGraph.
|
||||
subscribe (function(type, args, obj) {
|
||||
showGraphList(args[0]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
BigPerfGraph.onCursorMoved.
|
||||
subscribe (function (type, args, obj) {
|
||||
var time = args[0];
|
||||
var val = args[1];
|
||||
var extra_data = args[2]
|
||||
if (time != null && val != null) {
|
||||
// cheat
|
||||
showStatus("Interval: " + Math.floor(time) + " Value: " + val.toFixed(2) + " " + extra_data);
|
||||
} else {
|
||||
showStatus(null);
|
||||
}
|
||||
});
|
||||
BigPerfGraph.onNewGraph.
|
||||
subscribe (function(type, args, obj) {
|
||||
showGraphList(args[0]);
|
||||
});
|
||||
}
|
||||
if (document.location.hash) {
|
||||
handleHash(document.location.hash);
|
||||
} else {
|
||||
if (graphType == CONTINUOUS_GRAPH) {
|
||||
addGraphForm();
|
||||
}
|
||||
else if ( graphType == DATA_GRAPH ) {
|
||||
addExtraDataGraphForm();
|
||||
}
|
||||
else {
|
||||
addDiscreteGraphForm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function addExtraDataGraphForm(config, name) {
|
||||
showLoadingAnimation("populating lists");
|
||||
var ed = new ExtraDataGraphFormModule(config, name);
|
||||
ed.onLoading.subscribe (function(type,args,obj) { showLoadingAnimation(args[0]);});
|
||||
ed.onLoadingDone.subscribe (function(type,args,obj) { clearLoadingAnimation();});
|
||||
if (config) {
|
||||
ed.addedInitialInfo.subscribe(function(type,args,obj) { graphInitial();});
|
||||
}
|
||||
ed.render (getElement("graphforms"));
|
||||
return ed;
|
||||
}
|
||||
|
||||
function addDiscreteGraphForm(config, name) {
|
||||
showLoadingAnimation("populating lists");
|
||||
//log("name: " + name);
|
||||
var m = new DiscreteGraphFormModule(config, name);
|
||||
m.onLoading.subscribe (function(type,args,obj) { showLoadingAnimation(args[0]);});
|
||||
m.onLoadingDone.subscribe (function(type,args,obj) { clearLoadingAnimation();});
|
||||
if (config) {
|
||||
m.addedInitialInfo.subscribe(function(type,args,obj) { graphInitial();});
|
||||
}
|
||||
m.render (getElement("graphforms"));
|
||||
//m.setColor(randomColor());
|
||||
return m;
|
||||
}
|
||||
|
||||
function addGraphForm(config) {
|
||||
showLoadingAnimation("populating list");
|
||||
var m = new GraphFormModule(config);
|
||||
m.render (getElement("graphforms"));
|
||||
m.setColor(randomColor());
|
||||
m.onLoading.subscribe (function(type,args,obj) { showLoadingAnimation(args[0]);});
|
||||
m.onLoadingDone.subscribe (function(type,args,obj) { clearLoadingAnimation();});
|
||||
return m;
|
||||
}
|
||||
|
||||
function onNoBaseLineClick() {
|
||||
GraphFormModules.forEach (function (g) { g.baseline = false; });
|
||||
}
|
||||
|
||||
// whether the bonsai data query should redraw the graph or not
|
||||
var gReadyForRedraw = true;
|
||||
|
||||
function onUpdateBonsai() {
|
||||
BigPerfGraph.deleteAllMarkers();
|
||||
|
||||
getElement("bonsaibutton").disabled = true;
|
||||
|
||||
if (gCurrentLoadRange) {
|
||||
if ((gCurrentLoadRange[1] - gCurrentLoadRange[0]) < (bonsaiNoForceDays * ONE_DAY_SECONDS) || gForceBonsai) {
|
||||
Bonsai.requestCheckinsBetween (gCurrentLoadRange[0], gCurrentLoadRange[1],
|
||||
function (bdata) {
|
||||
for (var i = 0; i < bdata.times.length; i++) {
|
||||
BigPerfGraph.addMarker (bdata.times[i], bdata.who[i] + ": " + bdata.comment[i]);
|
||||
}
|
||||
if (gReadyForRedraw)
|
||||
BigPerfGraph.redraw();
|
||||
|
||||
getElement("bonsaibutton").disabled = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function onGraph() {
|
||||
showLoadingAnimation("building graph");
|
||||
showStatus(null);
|
||||
for each (var g in [BigPerfGraph, SmallPerfGraph]) {
|
||||
g.clearDataSets();
|
||||
g.setTimeRange(null, null);
|
||||
}
|
||||
|
||||
gReadyForRedraw = false;
|
||||
|
||||
// do the actual graph data request
|
||||
var baselineModule = null;
|
||||
GraphFormModules.forEach (function (g) { if (g.baseline) baselineModule = g; });
|
||||
if (baselineModule) {
|
||||
Tinderbox.requestDataSetFor (baselineModule.testId,
|
||||
function (testid, ds) {
|
||||
try {
|
||||
//log ("Got results for baseline: '" + testid + "' ds: " + ds);
|
||||
ds.color = baselineModule.color;
|
||||
onGraphLoadRemainder(ds);
|
||||
} catch(e) { log(e); }
|
||||
});
|
||||
} else {
|
||||
onGraphLoadRemainder();
|
||||
}
|
||||
}
|
||||
|
||||
function onGraphLoadRemainder(baselineDataSet) {
|
||||
for each (var graphModule in GraphFormModules) {
|
||||
//log ("onGraphLoadRemainder: ", graphModule.id, graphModule.testId, "color:", graphModule.color, "average:", graphModule.average);
|
||||
|
||||
// this would have been loaded earlier
|
||||
if (graphModule.baseline)
|
||||
continue;
|
||||
|
||||
var autoExpand = true;
|
||||
if (SmallPerfGraph.selectionType == "range" &&
|
||||
SmallPerfGraph.selectionStartTime &&
|
||||
SmallPerfGraph.selectionEndTime)
|
||||
{
|
||||
if (gCurrentLoadRange && (SmallPerfGraph.selectionStartTime < gCurrentLoadRange[0] ||
|
||||
SmallPerfGraph.selectionEndTime > gCurrentLoadRange[1]))
|
||||
{
|
||||
SmallPerfGraph.selectionStartTime = Math.max (SmallPerfGraph.selectionStartTime, gCurrentLoadRange[0]);
|
||||
SmallPerfGraph.selectionEndTime = Math.min (SmallPerfGraph.selectionEndTime, gCurrentLoadRange[1]);
|
||||
}
|
||||
|
||||
BigPerfGraph.setTimeRange (SmallPerfGraph.selectionStartTime, SmallPerfGraph.selectionEndTime);
|
||||
autoExpand = false;
|
||||
}
|
||||
|
||||
// we need a new closure here so that we can get the right value
|
||||
// of graphModule in our closure
|
||||
var makeCallback = function (module, color, title) {
|
||||
return function (testid, ds) {
|
||||
try {
|
||||
log("ds.firstTime " + ds.firstTime + " ds.lastTime " + ds.lastTime);
|
||||
if (undefined == ds.firstTime || !ds.lastTime) {
|
||||
// got a data set with no data in this time range, or damaged data
|
||||
// better to not graph
|
||||
for each (g in [BigPerfGraph, SmallPerfGraph]) {
|
||||
g.clearGraph();
|
||||
|
||||
}
|
||||
showStatus("No data in the given time range");
|
||||
clearLoadingAnimation();
|
||||
|
||||
}
|
||||
else {
|
||||
ds.color = color;
|
||||
if (title) {
|
||||
ds.title = title;
|
||||
}
|
||||
|
||||
if (baselineDataSet)
|
||||
ds = ds.createRelativeTo(baselineDataSet);
|
||||
|
||||
//log ("got ds: (", module.id, ")", ds.firstTime, ds.lastTime, ds.data.length);
|
||||
var avgds = null;
|
||||
if (baselineDataSet == null &&
|
||||
module.average)
|
||||
{
|
||||
avgds = ds.createAverage(gAverageInterval);
|
||||
}
|
||||
|
||||
if (avgds)
|
||||
log ("got avgds: (", module.id, ")", avgds.firstTime, avgds.lastTime, avgds.data.length);
|
||||
|
||||
for each (g in [BigPerfGraph, SmallPerfGraph]) {
|
||||
g.addDataSet(ds);
|
||||
if (avgds)
|
||||
g.addDataSet(avgds);
|
||||
if (g == SmallPerfGraph || autoExpand) {
|
||||
g.expandTimeRange(Math.max(ds.firstTime, gCurrentLoadRange ? gCurrentLoadRange[0] : ds.firstTime),
|
||||
Math.min(ds.lastTime, gCurrentLoadRange ? gCurrentLoadRange[1] : ds.lastTime));
|
||||
}
|
||||
|
||||
g.autoScale();
|
||||
|
||||
g.redraw();
|
||||
gReadyForRedraw = true;
|
||||
}
|
||||
|
||||
//if (graphType == CONTINUOUS_GRAPH) {
|
||||
updateLinkToThis();
|
||||
updateDumpToCsv();
|
||||
//}
|
||||
}
|
||||
|
||||
} catch(e) { log(e); }
|
||||
};
|
||||
};
|
||||
|
||||
if (graphModule.testIds) {
|
||||
for each (var testId in graphModule.testIds) {
|
||||
// log ("working with testId: " + testId);
|
||||
Tinderbox.requestDataSetFor (testId[0], makeCallback(graphModule, randomColor(), testId[1]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// log ("working with standard, single testId");
|
||||
Tinderbox.requestDataSetFor (graphModule.testId, makeCallback(graphModule, graphModule.color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onDataLoadChanged() {
|
||||
log ("loadchanged");
|
||||
if (getElement("load-days-radio").checked) {
|
||||
var dval = new Number(getElement("load-days-entry").value);
|
||||
log ("dval", dval);
|
||||
if (dval <= 0) {
|
||||
//getElement("load-days-entry").style.background-color = "red";
|
||||
return;
|
||||
} else {
|
||||
//getElement("load-days-entry").style.background-color = "inherit";
|
||||
}
|
||||
|
||||
var d2 = Math.ceil(Date.now() / 1000);
|
||||
d2 = (d2 - (d2 % ONE_DAY_SECONDS)) + ONE_DAY_SECONDS;
|
||||
var d1 = Math.floor(d2 - (dval * ONE_DAY_SECONDS));
|
||||
log ("drange", d1, d2);
|
||||
|
||||
Tinderbox.defaultLoadRange = [d1, d2];
|
||||
gCurrentLoadRange = [d1, d2];
|
||||
} else {
|
||||
Tinderbox.defaultLoadRange = null;
|
||||
gCurrentLoadRange = null;
|
||||
}
|
||||
|
||||
Tinderbox.clearValueDataSets();
|
||||
|
||||
// hack, reset colors
|
||||
randomColorBias = 0;
|
||||
}
|
||||
|
||||
function onExtraDataLoadChanged() {
|
||||
log ("loadchanged");
|
||||
Tinderbox.defaultLoadRange = null;
|
||||
gCurrentLoadRange = null;
|
||||
|
||||
// hack, reset colors
|
||||
randomColorBias = 0;
|
||||
}
|
||||
|
||||
|
||||
function onDiscreteDataLoadChanged() {
|
||||
log ("loadchanged");
|
||||
Tinderbox.defaultLoadRange = null;
|
||||
gCurrentLoadRange = null;
|
||||
|
||||
// hack, reset colors
|
||||
randomColorBias = 0;
|
||||
}
|
||||
|
||||
function findGraphModule(testId) {
|
||||
for each (var gm in GraphFormModules) {
|
||||
if (gm.testId == testId)
|
||||
return gm;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function updateDumpToCsv() {
|
||||
var ds = "?"
|
||||
prefix = ""
|
||||
for each (var gm in GraphFormModules) {
|
||||
ds += prefix + gm.getDumpString();
|
||||
prefix = "&"
|
||||
}
|
||||
log ("ds");
|
||||
getElement("dumptocsv").href = "http://" + document.location.host + "/dumpdata.cgi" + ds;
|
||||
}
|
||||
|
||||
function updateLinkToThis() {
|
||||
var qs = "";
|
||||
|
||||
qs += SmallPerfGraph.getQueryString("sp");
|
||||
qs += "&";
|
||||
qs += BigPerfGraph.getQueryString("bp");
|
||||
|
||||
if (graphType == CONTINUOUS_GRAPH) {
|
||||
var ctr = 1;
|
||||
for each (var gm in GraphFormModules) {
|
||||
qs += "&" + gm.getQueryString("m" + ctr);
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
qs += "&";
|
||||
qs += "name=" + GraphFormModules[0].name;
|
||||
for each (var gm in GraphFormModules) {
|
||||
qs += gm.getQueryString("m");
|
||||
}
|
||||
}
|
||||
|
||||
getElement("linktothis").href = document.location.pathname + "#" + qs;
|
||||
}
|
||||
|
||||
function handleHash(hash) {
|
||||
var qsdata = {};
|
||||
for each (var s in hash.substring(1).split("&")) {
|
||||
var q = s.split("=");
|
||||
qsdata[q[0]] = q[1];
|
||||
}
|
||||
|
||||
if (graphType == CONTINUOUS_GRAPH) {
|
||||
var ctr = 1;
|
||||
while (("m" + ctr + "tid") in qsdata) {
|
||||
var prefix = "m" + ctr;
|
||||
addGraphForm({testid: qsdata[prefix + "tid"],
|
||||
average: qsdata[prefix + "avg"]});
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var ctr=1;
|
||||
testids = [];
|
||||
while (("m" + ctr + "tid") in qsdata) {
|
||||
var prefix = "m" + ctr;
|
||||
testids.push(Number(qsdata[prefix + "tid"]));
|
||||
ctr++;
|
||||
}
|
||||
// log("qsdata[name] " + qsdata["name"]);
|
||||
addDiscreteGraphForm(testids, qsdata["name"]);
|
||||
}
|
||||
|
||||
SmallPerfGraph.handleQueryStringData("sp", qsdata);
|
||||
BigPerfGraph.handleQueryStringData("bp", qsdata);
|
||||
|
||||
var tstart = new Number(qsdata["spstart"]);
|
||||
var tend = new Number(qsdata["spend"]);
|
||||
|
||||
//Tinderbox.defaultLoadRange = [tstart, tend];
|
||||
|
||||
if (graphType == CONTINUOUS_GRAPH) {
|
||||
Tinderbox.requestTestList(function (tests) {
|
||||
setTimeout (onGraph, 0); // let the other handlers do their thing
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function graphInitial() {
|
||||
GraphFormModules[0].addedInitialInfo.unsubscribeAll();
|
||||
Tinderbox.requestTestList(null, null, null, null, function (tests) {
|
||||
setTimeout(onGraph, 0);
|
||||
});
|
||||
}
|
||||
|
||||
function showStatus(s) {
|
||||
replaceChildNodes("status", s);
|
||||
}
|
||||
|
||||
function showLoadingAnimation(message) {
|
||||
//log("starting loading animation: " + message);
|
||||
td = new SPAN();
|
||||
el = new IMG({ src: "js/img/Throbber-small.gif"});
|
||||
appendChildNodes(td, el);
|
||||
appendChildNodes(td, " loading: " + message + " ");
|
||||
replaceChildNodes("loading", td);
|
||||
}
|
||||
|
||||
function clearLoadingAnimation() {
|
||||
//log("ending loading animation");
|
||||
replaceChildNodes("loading", null);
|
||||
}
|
||||
|
||||
function showGraphList(s) {
|
||||
replaceChildNodes("graph-label-list",null);
|
||||
// log("s: " +s);
|
||||
var tbl = new TABLE({});
|
||||
var tbl_tr = new TR();
|
||||
appendChildNodes(tbl_tr, new TD(""));
|
||||
appendChildNodes(tbl_tr, new TD("avg"));
|
||||
appendChildNodes(tbl_tr, new TD("max"));
|
||||
appendChildNodes(tbl_tr, new TD("min"));
|
||||
appendChildNodes(tbl_tr, new TD("test name"));
|
||||
appendChildNodes(tbl, tbl_tr);
|
||||
for each (var ds in s) {
|
||||
var tbl_tr = new TR();
|
||||
var rstring = ds.stats + " ";
|
||||
var colorDiv = new DIV({ id: "whee", style: "display: inline; border: 1px solid black; height: 15; " +
|
||||
"padding-right: 15; vertical-align: middle; margin: 3px;" });
|
||||
colorDiv.style.backgroundColor = colorToRgbString(ds.color);
|
||||
// log("ds.stats" + ds.stats);
|
||||
appendChildNodes(tbl_tr, colorDiv);
|
||||
for each (var val in ds.stats) {
|
||||
appendChildNodes(tbl_tr, new TD(val.toFixed(2)));
|
||||
}
|
||||
appendChildNodes(tbl, tbl_tr);
|
||||
appendChildNodes(tbl_tr, new TD(ds.title));
|
||||
}
|
||||
appendChildNodes("graph-label-list", tbl);
|
||||
if (s.length == GraphFormModules[0].testIds.length) {
|
||||
clearLoadingAnimation();
|
||||
}
|
||||
//replaceChildNodes("graph-label-list",rstring);
|
||||
}
|
||||
|
||||
/* Get some pre-set colors in for the first 5 graphs, thens start randomly generating stuff */
|
||||
var presetColorIndex = 0;
|
||||
var presetColors = [
|
||||
[0.0, 0.0, 0.7, 1.0],
|
||||
[0.0, 0.5, 0.0, 1.0],
|
||||
[0.7, 0.0, 0.0, 1.0],
|
||||
[0.7, 0.0, 0.7, 1.0],
|
||||
[0.0, 0.7, 0.7, 1.0]
|
||||
];
|
||||
|
||||
var randomColorBias = 0;
|
||||
function randomColor() {
|
||||
if (presetColorIndex < presetColors.length) {
|
||||
return presetColors[presetColorIndex++];
|
||||
}
|
||||
|
||||
var col = [
|
||||
(Math.random()*0.5) + ((randomColorBias==0) ? 0.5 : 0.2),
|
||||
(Math.random()*0.5) + ((randomColorBias==1) ? 0.5 : 0.2),
|
||||
(Math.random()*0.5) + ((randomColorBias==2) ? 0.5 : 0.2),
|
||||
1.0
|
||||
];
|
||||
randomColorBias++;
|
||||
if (randomColorBias == 3)
|
||||
randomColorBias = 0;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
function lighterColor(col) {
|
||||
return [
|
||||
Math.min(0.85, col[0] * 1.2),
|
||||
Math.min(0.85, col[1] * 1.2),
|
||||
Math.min(0.85, col[2] * 1.2),
|
||||
col[3]
|
||||
];
|
||||
}
|
||||
|
||||
function colorToRgbString(col) {
|
||||
// log ("in colorToRgbString");
|
||||
if (col[3] < 1) {
|
||||
return "rgba("
|
||||
+ Math.floor(col[0]*255) + ","
|
||||
+ Math.floor(col[1]*255) + ","
|
||||
+ Math.floor(col[2]*255) + ","
|
||||
+ col[3]
|
||||
+ ")";
|
||||
}
|
||||
return "rgb("
|
||||
+ Math.floor(col[0]*255) + ","
|
||||
+ Math.floor(col[1]*255) + ","
|
||||
+ Math.floor(col[2]*255) + ")";
|
||||
}
|
||||
|
Before Width: | Height: | Size: 825 B |
|
Before Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 144 B |
|
Before Width: | Height: | Size: 156 B |
@@ -1,637 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.Async 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide("MochiKit.Async");
|
||||
dojo.require("MochiKit.Base");
|
||||
}
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use("MochiKit.Base", []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.Base) == 'undefined') {
|
||||
throw "";
|
||||
}
|
||||
} catch (e) {
|
||||
throw "MochiKit.Async depends on MochiKit.Base!";
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.Async) == 'undefined') {
|
||||
MochiKit.Async = {};
|
||||
}
|
||||
|
||||
MochiKit.Async.NAME = "MochiKit.Async";
|
||||
MochiKit.Async.VERSION = "1.3.1";
|
||||
MochiKit.Async.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
MochiKit.Async.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
MochiKit.Async.Deferred = function (/* optional */ canceller) {
|
||||
this.chain = [];
|
||||
this.id = this._nextId();
|
||||
this.fired = -1;
|
||||
this.paused = 0;
|
||||
this.results = [null, null];
|
||||
this.canceller = canceller;
|
||||
this.silentlyCancelled = false;
|
||||
this.chained = false;
|
||||
};
|
||||
|
||||
MochiKit.Async.Deferred.prototype = {
|
||||
repr: function () {
|
||||
var state;
|
||||
if (this.fired == -1) {
|
||||
state = 'unfired';
|
||||
} else if (this.fired === 0) {
|
||||
state = 'success';
|
||||
} else {
|
||||
state = 'error';
|
||||
}
|
||||
return 'Deferred(' + this.id + ', ' + state + ')';
|
||||
},
|
||||
|
||||
toString: MochiKit.Base.forwardCall("repr"),
|
||||
|
||||
_nextId: MochiKit.Base.counter(),
|
||||
|
||||
cancel: function () {
|
||||
var self = MochiKit.Async;
|
||||
if (this.fired == -1) {
|
||||
if (this.canceller) {
|
||||
this.canceller(this);
|
||||
} else {
|
||||
this.silentlyCancelled = true;
|
||||
}
|
||||
if (this.fired == -1) {
|
||||
this.errback(new self.CancelledError(this));
|
||||
}
|
||||
} else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
|
||||
this.results[0].cancel();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_pause: function () {
|
||||
/***
|
||||
|
||||
Used internally to signal that it's waiting on another Deferred
|
||||
|
||||
***/
|
||||
this.paused++;
|
||||
},
|
||||
|
||||
_unpause: function () {
|
||||
/***
|
||||
|
||||
Used internally to signal that it's no longer waiting on another
|
||||
Deferred.
|
||||
|
||||
***/
|
||||
this.paused--;
|
||||
if ((this.paused === 0) && (this.fired >= 0)) {
|
||||
this._fire();
|
||||
}
|
||||
},
|
||||
|
||||
_continue: function (res) {
|
||||
/***
|
||||
|
||||
Used internally when a dependent deferred fires.
|
||||
|
||||
***/
|
||||
this._resback(res);
|
||||
this._unpause();
|
||||
},
|
||||
|
||||
_resback: function (res) {
|
||||
/***
|
||||
|
||||
The primitive that means either callback or errback
|
||||
|
||||
***/
|
||||
this.fired = ((res instanceof Error) ? 1 : 0);
|
||||
this.results[this.fired] = res;
|
||||
this._fire();
|
||||
},
|
||||
|
||||
_check: function () {
|
||||
if (this.fired != -1) {
|
||||
if (!this.silentlyCancelled) {
|
||||
throw new MochiKit.Async.AlreadyCalledError(this);
|
||||
}
|
||||
this.silentlyCancelled = false;
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
callback: function (res) {
|
||||
this._check();
|
||||
if (res instanceof MochiKit.Async.Deferred) {
|
||||
throw new Error("Deferred instances can only be chained if they are the result of a callback");
|
||||
}
|
||||
this._resback(res);
|
||||
},
|
||||
|
||||
errback: function (res) {
|
||||
this._check();
|
||||
var self = MochiKit.Async;
|
||||
if (res instanceof self.Deferred) {
|
||||
throw new Error("Deferred instances can only be chained if they are the result of a callback");
|
||||
}
|
||||
if (!(res instanceof Error)) {
|
||||
res = new self.GenericError(res);
|
||||
}
|
||||
this._resback(res);
|
||||
},
|
||||
|
||||
addBoth: function (fn) {
|
||||
if (arguments.length > 1) {
|
||||
fn = MochiKit.Base.partial.apply(null, arguments);
|
||||
}
|
||||
return this.addCallbacks(fn, fn);
|
||||
},
|
||||
|
||||
addCallback: function (fn) {
|
||||
if (arguments.length > 1) {
|
||||
fn = MochiKit.Base.partial.apply(null, arguments);
|
||||
}
|
||||
return this.addCallbacks(fn, null);
|
||||
},
|
||||
|
||||
addErrback: function (fn) {
|
||||
if (arguments.length > 1) {
|
||||
fn = MochiKit.Base.partial.apply(null, arguments);
|
||||
}
|
||||
return this.addCallbacks(null, fn);
|
||||
},
|
||||
|
||||
addCallbacks: function (cb, eb) {
|
||||
if (this.chained) {
|
||||
throw new Error("Chained Deferreds can not be re-used");
|
||||
}
|
||||
this.chain.push([cb, eb]);
|
||||
if (this.fired >= 0) {
|
||||
this._fire();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
_fire: function () {
|
||||
/***
|
||||
|
||||
Used internally to exhaust the callback sequence when a result
|
||||
is available.
|
||||
|
||||
***/
|
||||
var chain = this.chain;
|
||||
var fired = this.fired;
|
||||
var res = this.results[fired];
|
||||
var self = this;
|
||||
var cb = null;
|
||||
while (chain.length > 0 && this.paused === 0) {
|
||||
// Array
|
||||
var pair = chain.shift();
|
||||
var f = pair[fired];
|
||||
if (f === null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
res = f(res);
|
||||
fired = ((res instanceof Error) ? 1 : 0);
|
||||
if (res instanceof MochiKit.Async.Deferred) {
|
||||
cb = function (res) {
|
||||
self._continue(res);
|
||||
};
|
||||
this._pause();
|
||||
}
|
||||
} catch (err) {
|
||||
fired = 1;
|
||||
if (!(err instanceof Error)) {
|
||||
err = new MochiKit.Async.GenericError(err);
|
||||
}
|
||||
res = err;
|
||||
}
|
||||
}
|
||||
this.fired = fired;
|
||||
this.results[fired] = res;
|
||||
if (cb && this.paused) {
|
||||
// this is for "tail recursion" in case the dependent deferred
|
||||
// is already fired
|
||||
res.addBoth(cb);
|
||||
res.chained = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Base.update(MochiKit.Async, {
|
||||
evalJSONRequest: function (/* req */) {
|
||||
return eval('(' + arguments[0].responseText + ')');
|
||||
},
|
||||
|
||||
succeed: function (/* optional */result) {
|
||||
var d = new MochiKit.Async.Deferred();
|
||||
d.callback.apply(d, arguments);
|
||||
return d;
|
||||
},
|
||||
|
||||
fail: function (/* optional */result) {
|
||||
var d = new MochiKit.Async.Deferred();
|
||||
d.errback.apply(d, arguments);
|
||||
return d;
|
||||
},
|
||||
|
||||
getXMLHttpRequest: function () {
|
||||
var self = arguments.callee;
|
||||
if (!self.XMLHttpRequest) {
|
||||
var tryThese = [
|
||||
function () { return new XMLHttpRequest(); },
|
||||
function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
|
||||
function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
|
||||
function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
|
||||
function () {
|
||||
throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
|
||||
}
|
||||
];
|
||||
for (var i = 0; i < tryThese.length; i++) {
|
||||
var func = tryThese[i];
|
||||
try {
|
||||
self.XMLHttpRequest = func;
|
||||
return func();
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
return self.XMLHttpRequest();
|
||||
},
|
||||
|
||||
_nothing: function () {},
|
||||
|
||||
_xhr_onreadystatechange: function (d) {
|
||||
// MochiKit.Logging.logDebug('this.readyState', this.readyState);
|
||||
if (this.readyState == 4) {
|
||||
// IE SUCKS
|
||||
try {
|
||||
this.onreadystatechange = null;
|
||||
} catch (e) {
|
||||
try {
|
||||
this.onreadystatechange = MochiKit.Async._nothing;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
var status = null;
|
||||
try {
|
||||
status = this.status;
|
||||
if (!status && MochiKit.Base.isNotEmpty(this.responseText)) {
|
||||
// 0 or undefined seems to mean cached or local
|
||||
status = 304;
|
||||
}
|
||||
} catch (e) {
|
||||
// pass
|
||||
// MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
|
||||
}
|
||||
// 200 is OK, 304 is NOT_MODIFIED
|
||||
if (status == 200 || status == 304) { // OK
|
||||
d.callback(this);
|
||||
} else {
|
||||
var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
|
||||
if (err.number) {
|
||||
// XXX: This seems to happen on page change
|
||||
d.errback(err);
|
||||
} else {
|
||||
// XXX: this seems to happen when the server is unreachable
|
||||
d.errback(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_xhr_canceller: function (req) {
|
||||
// IE SUCKS
|
||||
try {
|
||||
req.onreadystatechange = null;
|
||||
} catch (e) {
|
||||
try {
|
||||
req.onreadystatechange = MochiKit.Async._nothing;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
req.abort();
|
||||
},
|
||||
|
||||
|
||||
sendXMLHttpRequest: function (req, /* optional */ sendContent) {
|
||||
if (typeof(sendContent) == "undefined" || sendContent === null) {
|
||||
sendContent = "";
|
||||
}
|
||||
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Async;
|
||||
var d = new self.Deferred(m.partial(self._xhr_canceller, req));
|
||||
|
||||
try {
|
||||
req.onreadystatechange = m.bind(self._xhr_onreadystatechange,
|
||||
req, d);
|
||||
req.send(sendContent);
|
||||
} catch (e) {
|
||||
try {
|
||||
req.onreadystatechange = null;
|
||||
} catch (ignore) {
|
||||
// pass
|
||||
}
|
||||
d.errback(e);
|
||||
}
|
||||
|
||||
return d;
|
||||
|
||||
},
|
||||
|
||||
doSimpleXMLHttpRequest: function (url/*, ...*/) {
|
||||
var self = MochiKit.Async;
|
||||
var req = self.getXMLHttpRequest();
|
||||
if (arguments.length > 1) {
|
||||
var m = MochiKit.Base;
|
||||
var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
|
||||
if (qs) {
|
||||
url += "?" + qs;
|
||||
}
|
||||
}
|
||||
req.open("GET", url, true);
|
||||
return self.sendXMLHttpRequest(req);
|
||||
},
|
||||
|
||||
loadJSONDoc: function (url) {
|
||||
var self = MochiKit.Async;
|
||||
var d = self.doSimpleXMLHttpRequest.apply(self, arguments);
|
||||
d = d.addCallback(self.evalJSONRequest);
|
||||
return d;
|
||||
},
|
||||
|
||||
wait: function (seconds, /* optional */value) {
|
||||
var d = new MochiKit.Async.Deferred();
|
||||
var m = MochiKit.Base;
|
||||
if (typeof(value) != 'undefined') {
|
||||
d.addCallback(function () { return value; });
|
||||
}
|
||||
var timeout = setTimeout(
|
||||
m.bind("callback", d),
|
||||
Math.floor(seconds * 1000));
|
||||
d.canceller = function () {
|
||||
try {
|
||||
clearTimeout(timeout);
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
};
|
||||
return d;
|
||||
},
|
||||
|
||||
callLater: function (seconds, func) {
|
||||
var m = MochiKit.Base;
|
||||
var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
|
||||
return MochiKit.Async.wait(seconds).addCallback(
|
||||
function (res) { return pfunc(); }
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
MochiKit.Async.DeferredLock = function () {
|
||||
this.waiting = [];
|
||||
this.locked = false;
|
||||
this.id = this._nextId();
|
||||
};
|
||||
|
||||
MochiKit.Async.DeferredLock.prototype = {
|
||||
__class__: MochiKit.Async.DeferredLock,
|
||||
acquire: function () {
|
||||
d = new MochiKit.Async.Deferred();
|
||||
if (this.locked) {
|
||||
this.waiting.push(d);
|
||||
} else {
|
||||
this.locked = true;
|
||||
d.callback(this);
|
||||
}
|
||||
return d;
|
||||
},
|
||||
release: function () {
|
||||
if (!this.locked) {
|
||||
throw TypeError("Tried to release an unlocked DeferredLock");
|
||||
}
|
||||
this.locked = false;
|
||||
if (this.waiting.length > 0) {
|
||||
this.locked = true;
|
||||
this.waiting.shift().callback(this);
|
||||
}
|
||||
},
|
||||
_nextId: MochiKit.Base.counter(),
|
||||
repr: function () {
|
||||
var state;
|
||||
if (this.locked) {
|
||||
state = 'locked, ' + this.waiting.length + ' waiting';
|
||||
} else {
|
||||
state = 'unlocked';
|
||||
}
|
||||
return 'DeferredLock(' + this.id + ', ' + state + ')';
|
||||
},
|
||||
toString: MochiKit.Base.forwardCall("repr")
|
||||
|
||||
};
|
||||
|
||||
MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
|
||||
this.list = list;
|
||||
this.resultList = new Array(this.list.length);
|
||||
|
||||
// Deferred init
|
||||
this.chain = [];
|
||||
this.id = this._nextId();
|
||||
this.fired = -1;
|
||||
this.paused = 0;
|
||||
this.results = [null, null];
|
||||
this.canceller = canceller;
|
||||
this.silentlyCancelled = false;
|
||||
|
||||
if (this.list.length === 0 && !fireOnOneCallback) {
|
||||
this.callback(this.resultList);
|
||||
}
|
||||
|
||||
this.finishedCount = 0;
|
||||
this.fireOnOneCallback = fireOnOneCallback;
|
||||
this.fireOnOneErrback = fireOnOneErrback;
|
||||
this.consumeErrors = consumeErrors;
|
||||
|
||||
var index = 0;
|
||||
MochiKit.Base.map(MochiKit.Base.bind(function (d) {
|
||||
d.addCallback(MochiKit.Base.bind(this._cbDeferred, this), index, true);
|
||||
d.addErrback(MochiKit.Base.bind(this._cbDeferred, this), index, false);
|
||||
index += 1;
|
||||
}, this), this.list);
|
||||
};
|
||||
|
||||
MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,
|
||||
MochiKit.Async.Deferred.prototype);
|
||||
|
||||
MochiKit.Base.update(MochiKit.Async.DeferredList.prototype, {
|
||||
_cbDeferred: function (index, succeeded, result) {
|
||||
this.resultList[index] = [succeeded, result];
|
||||
this.finishedCount += 1;
|
||||
if (this.fired !== 0) {
|
||||
if (succeeded && this.fireOnOneCallback) {
|
||||
this.callback([index, result]);
|
||||
} else if (!succeeded && this.fireOnOneErrback) {
|
||||
this.errback(result);
|
||||
} else if (this.finishedCount == this.list.length) {
|
||||
this.callback(this.resultList);
|
||||
}
|
||||
}
|
||||
if (!succeeded && this.consumeErrors) {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
MochiKit.Async.gatherResults = function (deferredList) {
|
||||
var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
|
||||
d.addCallback(function (results) {
|
||||
var ret = [];
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
ret.push(results[i][1]);
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
return d;
|
||||
};
|
||||
|
||||
MochiKit.Async.maybeDeferred = function (func) {
|
||||
var self = MochiKit.Async;
|
||||
var result;
|
||||
try {
|
||||
var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
|
||||
if (r instanceof self.Deferred) {
|
||||
result = r;
|
||||
} else if (r instanceof Error) {
|
||||
result = self.fail(r);
|
||||
} else {
|
||||
result = self.succeed(r);
|
||||
}
|
||||
} catch (e) {
|
||||
result = self.fail(e);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
MochiKit.Async.EXPORT = [
|
||||
"AlreadyCalledError",
|
||||
"CancelledError",
|
||||
"BrowserComplianceError",
|
||||
"GenericError",
|
||||
"XMLHttpRequestError",
|
||||
"Deferred",
|
||||
"succeed",
|
||||
"fail",
|
||||
"getXMLHttpRequest",
|
||||
"doSimpleXMLHttpRequest",
|
||||
"loadJSONDoc",
|
||||
"wait",
|
||||
"callLater",
|
||||
"sendXMLHttpRequest",
|
||||
"DeferredLock",
|
||||
"DeferredList",
|
||||
"gatherResults",
|
||||
"maybeDeferred"
|
||||
];
|
||||
|
||||
MochiKit.Async.EXPORT_OK = [
|
||||
"evalJSONRequest"
|
||||
];
|
||||
|
||||
MochiKit.Async.__new__ = function () {
|
||||
var m = MochiKit.Base;
|
||||
var ne = m.partial(m._newNamedError, this);
|
||||
ne("AlreadyCalledError",
|
||||
function (deferred) {
|
||||
/***
|
||||
|
||||
Raised by the Deferred if callback or errback happens
|
||||
after it was already fired.
|
||||
|
||||
***/
|
||||
this.deferred = deferred;
|
||||
}
|
||||
);
|
||||
|
||||
ne("CancelledError",
|
||||
function (deferred) {
|
||||
/***
|
||||
|
||||
Raised by the Deferred cancellation mechanism.
|
||||
|
||||
***/
|
||||
this.deferred = deferred;
|
||||
}
|
||||
);
|
||||
|
||||
ne("BrowserComplianceError",
|
||||
function (msg) {
|
||||
/***
|
||||
|
||||
Raised when the JavaScript runtime is not capable of performing
|
||||
the given function. Technically, this should really never be
|
||||
raised because a non-conforming JavaScript runtime probably
|
||||
isn't going to support exceptions in the first place.
|
||||
|
||||
***/
|
||||
this.message = msg;
|
||||
}
|
||||
);
|
||||
|
||||
ne("GenericError",
|
||||
function (msg) {
|
||||
this.message = msg;
|
||||
}
|
||||
);
|
||||
|
||||
ne("XMLHttpRequestError",
|
||||
function (req, msg) {
|
||||
/***
|
||||
|
||||
Raised when an XMLHttpRequest does not complete for any reason.
|
||||
|
||||
***/
|
||||
this.req = req;
|
||||
this.message = msg;
|
||||
try {
|
||||
// Strange but true that this can raise in some cases.
|
||||
this.number = req.status;
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
this.EXPORT_TAGS = {
|
||||
":common": this.EXPORT,
|
||||
":all": m.concat(this.EXPORT, this.EXPORT_OK)
|
||||
};
|
||||
|
||||
m.nameFunctions(this);
|
||||
|
||||
};
|
||||
|
||||
MochiKit.Async.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Async);
|
||||
@@ -1,825 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.Color 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito and others. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.Color');
|
||||
dojo.require('MochiKit.Base');
|
||||
}
|
||||
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use("MochiKit.Base", []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.Base) == 'undefined') {
|
||||
throw "";
|
||||
}
|
||||
} catch (e) {
|
||||
throw "MochiKit.Color depends on MochiKit.Base";
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.Color) == "undefined") {
|
||||
MochiKit.Color = {};
|
||||
}
|
||||
|
||||
MochiKit.Color.NAME = "MochiKit.Color";
|
||||
MochiKit.Color.VERSION = "1.3.1";
|
||||
|
||||
MochiKit.Color.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
MochiKit.Color.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
|
||||
MochiKit.Color.Color = function (red, green, blue, alpha) {
|
||||
if (typeof(alpha) == 'undefined' || alpha === null) {
|
||||
alpha = 1.0;
|
||||
}
|
||||
this.rgb = {
|
||||
r: red,
|
||||
g: green,
|
||||
b: blue,
|
||||
a: alpha
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Prototype methods
|
||||
MochiKit.Color.Color.prototype = {
|
||||
|
||||
__class__: MochiKit.Color.Color,
|
||||
|
||||
colorWithAlpha: function (alpha) {
|
||||
var rgb = this.rgb;
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
|
||||
},
|
||||
|
||||
colorWithHue: function (hue) {
|
||||
// get an HSL model, and set the new hue...
|
||||
var hsl = this.asHSL();
|
||||
hsl.h = hue;
|
||||
var m = MochiKit.Color;
|
||||
// convert back to RGB...
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
colorWithSaturation: function (saturation) {
|
||||
// get an HSL model, and set the new hue...
|
||||
var hsl = this.asHSL();
|
||||
hsl.s = saturation;
|
||||
var m = MochiKit.Color;
|
||||
// convert back to RGB...
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
colorWithLightness: function (lightness) {
|
||||
// get an HSL model, and set the new hue...
|
||||
var hsl = this.asHSL();
|
||||
hsl.l = lightness;
|
||||
var m = MochiKit.Color;
|
||||
// convert back to RGB...
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
darkerColorWithLevel: function (level) {
|
||||
var hsl = this.asHSL();
|
||||
hsl.l = Math.max(hsl.l - level, 0);
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
lighterColorWithLevel: function (level) {
|
||||
var hsl = this.asHSL();
|
||||
hsl.l = Math.min(hsl.l + level, 1);
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
blendedColor: function (other, /* optional */ fraction) {
|
||||
if (typeof(fraction) == 'undefined' || fraction === null) {
|
||||
fraction = 0.5;
|
||||
}
|
||||
var sf = 1.0 - fraction;
|
||||
var s = this.rgb;
|
||||
var d = other.rgb;
|
||||
var df = fraction;
|
||||
return MochiKit.Color.Color.fromRGB(
|
||||
(s.r * sf) + (d.r * df),
|
||||
(s.g * sf) + (d.g * df),
|
||||
(s.b * sf) + (d.b * df),
|
||||
(s.a * sf) + (d.a * df)
|
||||
);
|
||||
},
|
||||
|
||||
compareRGB: function (other) {
|
||||
var a = this.asRGB();
|
||||
var b = other.asRGB();
|
||||
return MochiKit.Base.compare(
|
||||
[a.r, a.g, a.b, a.a],
|
||||
[b.r, b.g, b.b, b.a]
|
||||
);
|
||||
},
|
||||
|
||||
isLight: function () {
|
||||
return this.asHSL().b > 0.5;
|
||||
},
|
||||
|
||||
isDark: function () {
|
||||
return (!this.isLight());
|
||||
},
|
||||
|
||||
toHSLString: function () {
|
||||
var c = this.asHSL();
|
||||
var ccc = MochiKit.Color.clampColorComponent;
|
||||
var rval = this._hslString;
|
||||
if (!rval) {
|
||||
var mid = (
|
||||
ccc(c.h, 360).toFixed(0)
|
||||
+ "," + ccc(c.s, 100).toPrecision(4) + "%"
|
||||
+ "," + ccc(c.l, 100).toPrecision(4) + "%"
|
||||
);
|
||||
var a = c.a;
|
||||
if (a >= 1) {
|
||||
a = 1;
|
||||
rval = "hsl(" + mid + ")";
|
||||
} else {
|
||||
if (a <= 0) {
|
||||
a = 0;
|
||||
}
|
||||
rval = "hsla(" + mid + "," + a + ")";
|
||||
}
|
||||
this._hslString = rval;
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
toRGBString: function () {
|
||||
var c = this.rgb;
|
||||
var ccc = MochiKit.Color.clampColorComponent;
|
||||
var rval = this._rgbString;
|
||||
if (!rval) {
|
||||
var mid = (
|
||||
ccc(c.r, 255).toFixed(0)
|
||||
+ "," + ccc(c.g, 255).toFixed(0)
|
||||
+ "," + ccc(c.b, 255).toFixed(0)
|
||||
);
|
||||
if (c.a != 1) {
|
||||
rval = "rgba(" + mid + "," + c.a + ")";
|
||||
} else {
|
||||
rval = "rgb(" + mid + ")";
|
||||
}
|
||||
this._rgbString = rval;
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
asRGB: function () {
|
||||
return MochiKit.Base.clone(this.rgb);
|
||||
},
|
||||
|
||||
toHexString: function () {
|
||||
var m = MochiKit.Color;
|
||||
var c = this.rgb;
|
||||
var ccc = MochiKit.Color.clampColorComponent;
|
||||
var rval = this._hexString;
|
||||
if (!rval) {
|
||||
rval = ("#" +
|
||||
m.toColorPart(ccc(c.r, 255)) +
|
||||
m.toColorPart(ccc(c.g, 255)) +
|
||||
m.toColorPart(ccc(c.b, 255))
|
||||
);
|
||||
this._hexString = rval;
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
asHSV: function () {
|
||||
var hsv = this.hsv;
|
||||
var c = this.rgb;
|
||||
if (typeof(hsv) == 'undefined' || hsv === null) {
|
||||
hsv = MochiKit.Color.rgbToHSV(this.rgb);
|
||||
this.hsv = hsv;
|
||||
}
|
||||
return MochiKit.Base.clone(hsv);
|
||||
},
|
||||
|
||||
asHSL: function () {
|
||||
var hsl = this.hsl;
|
||||
var c = this.rgb;
|
||||
if (typeof(hsl) == 'undefined' || hsl === null) {
|
||||
hsl = MochiKit.Color.rgbToHSL(this.rgb);
|
||||
this.hsl = hsl;
|
||||
}
|
||||
return MochiKit.Base.clone(hsl);
|
||||
},
|
||||
|
||||
toString: function () {
|
||||
return this.toRGBString();
|
||||
},
|
||||
|
||||
repr: function () {
|
||||
var c = this.rgb;
|
||||
var col = [c.r, c.g, c.b, c.a];
|
||||
return this.__class__.NAME + "(" + col.join(", ") + ")";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Constructor methods
|
||||
MochiKit.Base.update(MochiKit.Color.Color, {
|
||||
fromRGB: function (red, green, blue, alpha) {
|
||||
// designated initializer
|
||||
var Color = MochiKit.Color.Color;
|
||||
if (arguments.length == 1) {
|
||||
var rgb = red;
|
||||
red = rgb.r;
|
||||
green = rgb.g;
|
||||
blue = rgb.b;
|
||||
if (typeof(rgb.a) == 'undefined') {
|
||||
alpha = undefined;
|
||||
} else {
|
||||
alpha = rgb.a;
|
||||
}
|
||||
}
|
||||
return new Color(red, green, blue, alpha);
|
||||
},
|
||||
|
||||
fromHSL: function (hue, saturation, lightness, alpha) {
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
|
||||
},
|
||||
|
||||
fromHSV: function (hue, saturation, value, alpha) {
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
|
||||
},
|
||||
|
||||
fromName: function (name) {
|
||||
var Color = MochiKit.Color.Color;
|
||||
// Opera 9 seems to "quote" named colors(?!)
|
||||
if (name.charAt(0) == '"') {
|
||||
name = name.substr(1, name.length - 2);
|
||||
}
|
||||
var htmlColor = Color._namedColors[name.toLowerCase()];
|
||||
if (typeof(htmlColor) == 'string') {
|
||||
return Color.fromHexString(htmlColor);
|
||||
} else if (name == "transparent") {
|
||||
return Color.transparentColor();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
fromString: function (colorString) {
|
||||
var self = MochiKit.Color.Color;
|
||||
var three = colorString.substr(0, 3);
|
||||
if (three == "rgb") {
|
||||
return self.fromRGBString(colorString);
|
||||
} else if (three == "hsl") {
|
||||
return self.fromHSLString(colorString);
|
||||
} else if (colorString.charAt(0) == "#") {
|
||||
return self.fromHexString(colorString);
|
||||
}
|
||||
return self.fromName(colorString);
|
||||
},
|
||||
|
||||
|
||||
fromHexString: function (hexCode) {
|
||||
if (hexCode.charAt(0) == '#') {
|
||||
hexCode = hexCode.substring(1);
|
||||
}
|
||||
var components = [];
|
||||
var i, hex;
|
||||
if (hexCode.length == 3) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
hex = hexCode.substr(i, 1);
|
||||
components.push(parseInt(hex + hex, 16) / 255.0);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 6; i += 2) {
|
||||
hex = hexCode.substr(i, 2);
|
||||
components.push(parseInt(hex, 16) / 255.0);
|
||||
}
|
||||
}
|
||||
var Color = MochiKit.Color.Color;
|
||||
return Color.fromRGB.apply(Color, components);
|
||||
},
|
||||
|
||||
|
||||
_fromColorString: function (pre, method, scales, colorCode) {
|
||||
// parses either HSL or RGB
|
||||
if (colorCode.indexOf(pre) === 0) {
|
||||
colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
|
||||
}
|
||||
var colorChunks = colorCode.split(/\s*,\s*/);
|
||||
var colorFloats = [];
|
||||
for (var i = 0; i < colorChunks.length; i++) {
|
||||
var c = colorChunks[i];
|
||||
var val;
|
||||
var three = c.substring(c.length - 3);
|
||||
if (c.charAt(c.length - 1) == '%') {
|
||||
val = 0.01 * parseFloat(c.substring(0, c.length - 1));
|
||||
} else if (three == "deg") {
|
||||
val = parseFloat(c) / 360.0;
|
||||
} else if (three == "rad") {
|
||||
val = parseFloat(c) / (Math.PI * 2);
|
||||
} else {
|
||||
val = scales[i] * parseFloat(c);
|
||||
}
|
||||
colorFloats.push(val);
|
||||
}
|
||||
return this[method].apply(this, colorFloats);
|
||||
},
|
||||
|
||||
fromComputedStyle: function (elem, style, mozillaEquivalentCSS) {
|
||||
var d = MochiKit.DOM;
|
||||
var cls = MochiKit.Color.Color;
|
||||
for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
|
||||
var actualColor = d.computedStyle.apply(d, arguments);
|
||||
if (!actualColor) {
|
||||
continue;
|
||||
}
|
||||
var color = cls.fromString(actualColor);
|
||||
if (!color) {
|
||||
break;
|
||||
}
|
||||
if (color.asRGB().a > 0) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
fromBackground: function (elem) {
|
||||
var cls = MochiKit.Color.Color;
|
||||
return cls.fromComputedStyle(
|
||||
elem, "backgroundColor", "background-color") || cls.whiteColor();
|
||||
},
|
||||
|
||||
fromText: function (elem) {
|
||||
var cls = MochiKit.Color.Color;
|
||||
return cls.fromComputedStyle(
|
||||
elem, "color", "color") || cls.blackColor();
|
||||
},
|
||||
|
||||
namedColors: function () {
|
||||
return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
|
||||
}
|
||||
});
|
||||
|
||||
// Module level functions
|
||||
MochiKit.Base.update(MochiKit.Color, {
|
||||
clampColorComponent: function (v, scale) {
|
||||
v *= scale;
|
||||
if (v < 0) {
|
||||
return 0;
|
||||
} else if (v > scale) {
|
||||
return scale;
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
},
|
||||
|
||||
_hslValue: function (n1, n2, hue) {
|
||||
if (hue > 6.0) {
|
||||
hue -= 6.0;
|
||||
} else if (hue < 0.0) {
|
||||
hue += 6.0;
|
||||
}
|
||||
var val;
|
||||
if (hue < 1.0) {
|
||||
val = n1 + (n2 - n1) * hue;
|
||||
} else if (hue < 3.0) {
|
||||
val = n2;
|
||||
} else if (hue < 4.0) {
|
||||
val = n1 + (n2 - n1) * (4.0 - hue);
|
||||
} else {
|
||||
val = n1;
|
||||
}
|
||||
return val;
|
||||
},
|
||||
|
||||
hsvToRGB: function (hue, saturation, value, alpha) {
|
||||
if (arguments.length == 1) {
|
||||
var hsv = hue;
|
||||
hue = hsv.h;
|
||||
saturation = hsv.s;
|
||||
value = hsv.v;
|
||||
alpha = hsv.a;
|
||||
}
|
||||
var red;
|
||||
var green;
|
||||
var blue;
|
||||
if (saturation === 0) {
|
||||
red = 0;
|
||||
green = 0;
|
||||
blue = 0;
|
||||
} else {
|
||||
var i = Math.floor(hue * 6);
|
||||
var f = (hue * 6) - i;
|
||||
var p = value * (1 - saturation);
|
||||
var q = value * (1 - (saturation * f));
|
||||
var t = value * (1 - (saturation * (1 - f)));
|
||||
switch (i) {
|
||||
case 1: red = q; green = value; blue = p; break;
|
||||
case 2: red = p; green = value; blue = t; break;
|
||||
case 3: red = p; green = q; blue = value; break;
|
||||
case 4: red = t; green = p; blue = value; break;
|
||||
case 5: red = value; green = p; blue = q; break;
|
||||
case 6: // fall through
|
||||
case 0: red = value; green = t; blue = p; break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
r: red,
|
||||
g: green,
|
||||
b: blue,
|
||||
a: alpha
|
||||
};
|
||||
},
|
||||
|
||||
hslToRGB: function (hue, saturation, lightness, alpha) {
|
||||
if (arguments.length == 1) {
|
||||
var hsl = hue;
|
||||
hue = hsl.h;
|
||||
saturation = hsl.s;
|
||||
lightness = hsl.l;
|
||||
alpha = hsl.a;
|
||||
}
|
||||
var red;
|
||||
var green;
|
||||
var blue;
|
||||
if (saturation === 0) {
|
||||
red = lightness;
|
||||
green = lightness;
|
||||
blue = lightness;
|
||||
} else {
|
||||
var m2;
|
||||
if (lightness <= 0.5) {
|
||||
m2 = lightness * (1.0 + saturation);
|
||||
} else {
|
||||
m2 = lightness + saturation - (lightness * saturation);
|
||||
}
|
||||
var m1 = (2.0 * lightness) - m2;
|
||||
var f = MochiKit.Color._hslValue;
|
||||
var h6 = hue * 6.0;
|
||||
red = f(m1, m2, h6 + 2);
|
||||
green = f(m1, m2, h6);
|
||||
blue = f(m1, m2, h6 - 2);
|
||||
}
|
||||
return {
|
||||
r: red,
|
||||
g: green,
|
||||
b: blue,
|
||||
a: alpha
|
||||
};
|
||||
},
|
||||
|
||||
rgbToHSV: function (red, green, blue, alpha) {
|
||||
if (arguments.length == 1) {
|
||||
var rgb = red;
|
||||
red = rgb.r;
|
||||
green = rgb.g;
|
||||
blue = rgb.b;
|
||||
alpha = rgb.a;
|
||||
}
|
||||
var max = Math.max(Math.max(red, green), blue);
|
||||
var min = Math.min(Math.min(red, green), blue);
|
||||
var hue;
|
||||
var saturation;
|
||||
var value = max;
|
||||
if (min == max) {
|
||||
hue = 0;
|
||||
saturation = 0;
|
||||
} else {
|
||||
var delta = (max - min);
|
||||
saturation = delta / max;
|
||||
|
||||
if (red == max) {
|
||||
hue = (green - blue) / delta;
|
||||
} else if (green == max) {
|
||||
hue = 2 + ((blue - red) / delta);
|
||||
} else {
|
||||
hue = 4 + ((red - green) / delta);
|
||||
}
|
||||
hue /= 6;
|
||||
if (hue < 0) {
|
||||
hue += 1;
|
||||
}
|
||||
if (hue > 1) {
|
||||
hue -= 1;
|
||||
}
|
||||
}
|
||||
return {
|
||||
h: hue,
|
||||
s: saturation,
|
||||
v: value,
|
||||
a: alpha
|
||||
};
|
||||
},
|
||||
|
||||
rgbToHSL: function (red, green, blue, alpha) {
|
||||
if (arguments.length == 1) {
|
||||
var rgb = red;
|
||||
red = rgb.r;
|
||||
green = rgb.g;
|
||||
blue = rgb.b;
|
||||
alpha = rgb.a;
|
||||
}
|
||||
var max = Math.max(red, Math.max(green, blue));
|
||||
var min = Math.min(red, Math.min(green, blue));
|
||||
var hue;
|
||||
var saturation;
|
||||
var lightness = (max + min) / 2.0;
|
||||
var delta = max - min;
|
||||
if (delta === 0) {
|
||||
hue = 0;
|
||||
saturation = 0;
|
||||
} else {
|
||||
if (lightness <= 0.5) {
|
||||
saturation = delta / (max + min);
|
||||
} else {
|
||||
saturation = delta / (2 - max - min);
|
||||
}
|
||||
if (red == max) {
|
||||
hue = (green - blue) / delta;
|
||||
} else if (green == max) {
|
||||
hue = 2 + ((blue - red) / delta);
|
||||
} else {
|
||||
hue = 4 + ((red - green) / delta);
|
||||
}
|
||||
hue /= 6;
|
||||
if (hue < 0) {
|
||||
hue += 1;
|
||||
}
|
||||
if (hue > 1) {
|
||||
hue -= 1;
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
h: hue,
|
||||
s: saturation,
|
||||
l: lightness,
|
||||
a: alpha
|
||||
};
|
||||
},
|
||||
|
||||
toColorPart: function (num) {
|
||||
num = Math.round(num);
|
||||
var digits = num.toString(16);
|
||||
if (num < 16) {
|
||||
return '0' + digits;
|
||||
}
|
||||
return digits;
|
||||
},
|
||||
|
||||
__new__: function () {
|
||||
var m = MochiKit.Base;
|
||||
this.Color.fromRGBString = m.bind(
|
||||
this.Color._fromColorString, this.Color, "rgb", "fromRGB",
|
||||
[1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
|
||||
);
|
||||
this.Color.fromHSLString = m.bind(
|
||||
this.Color._fromColorString, this.Color, "hsl", "fromHSL",
|
||||
[1.0/360.0, 0.01, 0.01, 1]
|
||||
);
|
||||
|
||||
var third = 1.0 / 3.0;
|
||||
var colors = {
|
||||
// NSColor colors plus transparent
|
||||
black: [0, 0, 0],
|
||||
blue: [0, 0, 1],
|
||||
brown: [0.6, 0.4, 0.2],
|
||||
cyan: [0, 1, 1],
|
||||
darkGray: [third, third, third],
|
||||
gray: [0.5, 0.5, 0.5],
|
||||
green: [0, 1, 0],
|
||||
lightGray: [2 * third, 2 * third, 2 * third],
|
||||
magenta: [1, 0, 1],
|
||||
orange: [1, 0.5, 0],
|
||||
purple: [0.5, 0, 0.5],
|
||||
red: [1, 0, 0],
|
||||
transparent: [0, 0, 0, 0],
|
||||
white: [1, 1, 1],
|
||||
yellow: [1, 1, 0]
|
||||
};
|
||||
|
||||
var makeColor = function (name, r, g, b, a) {
|
||||
var rval = this.fromRGB(r, g, b, a);
|
||||
this[name] = function () { return rval; };
|
||||
return rval;
|
||||
};
|
||||
|
||||
for (var k in colors) {
|
||||
var name = k + "Color";
|
||||
var bindArgs = m.concat(
|
||||
[makeColor, this.Color, name],
|
||||
colors[k]
|
||||
);
|
||||
this.Color[name] = m.bind.apply(null, bindArgs);
|
||||
}
|
||||
|
||||
var isColor = function () {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (!(arguments[i] instanceof Color)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
var compareColor = function (a, b) {
|
||||
return a.compareRGB(b);
|
||||
};
|
||||
|
||||
m.nameFunctions(this);
|
||||
|
||||
m.registerComparator(this.Color.NAME, isColor, compareColor);
|
||||
|
||||
this.EXPORT_TAGS = {
|
||||
":common": this.EXPORT,
|
||||
":all": m.concat(this.EXPORT, this.EXPORT_OK)
|
||||
};
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
MochiKit.Color.EXPORT = [
|
||||
"Color"
|
||||
];
|
||||
|
||||
MochiKit.Color.EXPORT_OK = [
|
||||
"clampColorComponent",
|
||||
"rgbToHSL",
|
||||
"hslToRGB",
|
||||
"rgbToHSV",
|
||||
"hsvToRGB",
|
||||
"toColorPart"
|
||||
];
|
||||
|
||||
MochiKit.Color.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Color);
|
||||
|
||||
// Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
|
||||
|
||||
MochiKit.Color.Color._namedColors = {
|
||||
aliceblue: "#f0f8ff",
|
||||
antiquewhite: "#faebd7",
|
||||
aqua: "#00ffff",
|
||||
aquamarine: "#7fffd4",
|
||||
azure: "#f0ffff",
|
||||
beige: "#f5f5dc",
|
||||
bisque: "#ffe4c4",
|
||||
black: "#000000",
|
||||
blanchedalmond: "#ffebcd",
|
||||
blue: "#0000ff",
|
||||
blueviolet: "#8a2be2",
|
||||
brown: "#a52a2a",
|
||||
burlywood: "#deb887",
|
||||
cadetblue: "#5f9ea0",
|
||||
chartreuse: "#7fff00",
|
||||
chocolate: "#d2691e",
|
||||
coral: "#ff7f50",
|
||||
cornflowerblue: "#6495ed",
|
||||
cornsilk: "#fff8dc",
|
||||
crimson: "#dc143c",
|
||||
cyan: "#00ffff",
|
||||
darkblue: "#00008b",
|
||||
darkcyan: "#008b8b",
|
||||
darkgoldenrod: "#b8860b",
|
||||
darkgray: "#a9a9a9",
|
||||
darkgreen: "#006400",
|
||||
darkgrey: "#a9a9a9",
|
||||
darkkhaki: "#bdb76b",
|
||||
darkmagenta: "#8b008b",
|
||||
darkolivegreen: "#556b2f",
|
||||
darkorange: "#ff8c00",
|
||||
darkorchid: "#9932cc",
|
||||
darkred: "#8b0000",
|
||||
darksalmon: "#e9967a",
|
||||
darkseagreen: "#8fbc8f",
|
||||
darkslateblue: "#483d8b",
|
||||
darkslategray: "#2f4f4f",
|
||||
darkslategrey: "#2f4f4f",
|
||||
darkturquoise: "#00ced1",
|
||||
darkviolet: "#9400d3",
|
||||
deeppink: "#ff1493",
|
||||
deepskyblue: "#00bfff",
|
||||
dimgray: "#696969",
|
||||
dimgrey: "#696969",
|
||||
dodgerblue: "#1e90ff",
|
||||
firebrick: "#b22222",
|
||||
floralwhite: "#fffaf0",
|
||||
forestgreen: "#228b22",
|
||||
fuchsia: "#ff00ff",
|
||||
gainsboro: "#dcdcdc",
|
||||
ghostwhite: "#f8f8ff",
|
||||
gold: "#ffd700",
|
||||
goldenrod: "#daa520",
|
||||
gray: "#808080",
|
||||
green: "#008000",
|
||||
greenyellow: "#adff2f",
|
||||
grey: "#808080",
|
||||
honeydew: "#f0fff0",
|
||||
hotpink: "#ff69b4",
|
||||
indianred: "#cd5c5c",
|
||||
indigo: "#4b0082",
|
||||
ivory: "#fffff0",
|
||||
khaki: "#f0e68c",
|
||||
lavender: "#e6e6fa",
|
||||
lavenderblush: "#fff0f5",
|
||||
lawngreen: "#7cfc00",
|
||||
lemonchiffon: "#fffacd",
|
||||
lightblue: "#add8e6",
|
||||
lightcoral: "#f08080",
|
||||
lightcyan: "#e0ffff",
|
||||
lightgoldenrodyellow: "#fafad2",
|
||||
lightgray: "#d3d3d3",
|
||||
lightgreen: "#90ee90",
|
||||
lightgrey: "#d3d3d3",
|
||||
lightpink: "#ffb6c1",
|
||||
lightsalmon: "#ffa07a",
|
||||
lightseagreen: "#20b2aa",
|
||||
lightskyblue: "#87cefa",
|
||||
lightslategray: "#778899",
|
||||
lightslategrey: "#778899",
|
||||
lightsteelblue: "#b0c4de",
|
||||
lightyellow: "#ffffe0",
|
||||
lime: "#00ff00",
|
||||
limegreen: "#32cd32",
|
||||
linen: "#faf0e6",
|
||||
magenta: "#ff00ff",
|
||||
maroon: "#800000",
|
||||
mediumaquamarine: "#66cdaa",
|
||||
mediumblue: "#0000cd",
|
||||
mediumorchid: "#ba55d3",
|
||||
mediumpurple: "#9370db",
|
||||
mediumseagreen: "#3cb371",
|
||||
mediumslateblue: "#7b68ee",
|
||||
mediumspringgreen: "#00fa9a",
|
||||
mediumturquoise: "#48d1cc",
|
||||
mediumvioletred: "#c71585",
|
||||
midnightblue: "#191970",
|
||||
mintcream: "#f5fffa",
|
||||
mistyrose: "#ffe4e1",
|
||||
moccasin: "#ffe4b5",
|
||||
navajowhite: "#ffdead",
|
||||
navy: "#000080",
|
||||
oldlace: "#fdf5e6",
|
||||
olive: "#808000",
|
||||
olivedrab: "#6b8e23",
|
||||
orange: "#ffa500",
|
||||
orangered: "#ff4500",
|
||||
orchid: "#da70d6",
|
||||
palegoldenrod: "#eee8aa",
|
||||
palegreen: "#98fb98",
|
||||
paleturquoise: "#afeeee",
|
||||
palevioletred: "#db7093",
|
||||
papayawhip: "#ffefd5",
|
||||
peachpuff: "#ffdab9",
|
||||
peru: "#cd853f",
|
||||
pink: "#ffc0cb",
|
||||
plum: "#dda0dd",
|
||||
powderblue: "#b0e0e6",
|
||||
purple: "#800080",
|
||||
red: "#ff0000",
|
||||
rosybrown: "#bc8f8f",
|
||||
royalblue: "#4169e1",
|
||||
saddlebrown: "#8b4513",
|
||||
salmon: "#fa8072",
|
||||
sandybrown: "#f4a460",
|
||||
seagreen: "#2e8b57",
|
||||
seashell: "#fff5ee",
|
||||
sienna: "#a0522d",
|
||||
silver: "#c0c0c0",
|
||||
skyblue: "#87ceeb",
|
||||
slateblue: "#6a5acd",
|
||||
slategray: "#708090",
|
||||
slategrey: "#708090",
|
||||
snow: "#fffafa",
|
||||
springgreen: "#00ff7f",
|
||||
steelblue: "#4682b4",
|
||||
tan: "#d2b48c",
|
||||
teal: "#008080",
|
||||
thistle: "#d8bfd8",
|
||||
tomato: "#ff6347",
|
||||
turquoise: "#40e0d0",
|
||||
violet: "#ee82ee",
|
||||
wheat: "#f5deb3",
|
||||
white: "#ffffff",
|
||||
whitesmoke: "#f5f5f5",
|
||||
yellow: "#ffff00",
|
||||
yellowgreen: "#9acd32"
|
||||
};
|
||||
@@ -1,208 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.DateTime 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.DateTime');
|
||||
}
|
||||
|
||||
if (typeof(MochiKit) == 'undefined') {
|
||||
MochiKit = {};
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.DateTime) == 'undefined') {
|
||||
MochiKit.DateTime = {};
|
||||
}
|
||||
|
||||
MochiKit.DateTime.NAME = "MochiKit.DateTime";
|
||||
MochiKit.DateTime.VERSION = "1.3.1";
|
||||
MochiKit.DateTime.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
MochiKit.DateTime.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
MochiKit.DateTime.isoDate = function (str) {
|
||||
str = str + "";
|
||||
if (typeof(str) != "string" || str.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var iso = str.split('-');
|
||||
if (iso.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return new Date(iso[0], iso[1] - 1, iso[2]);
|
||||
};
|
||||
|
||||
MochiKit.DateTime._isoRegexp = /(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/;
|
||||
|
||||
MochiKit.DateTime.isoTimestamp = function (str) {
|
||||
str = str + "";
|
||||
if (typeof(str) != "string" || str.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var res = str.match(MochiKit.DateTime._isoRegexp);
|
||||
if (typeof(res) == "undefined" || res === null) {
|
||||
return null;
|
||||
}
|
||||
var year, month, day, hour, min, sec, msec;
|
||||
year = parseInt(res[1], 10);
|
||||
if (typeof(res[2]) == "undefined" || res[2] === '') {
|
||||
return new Date(year);
|
||||
}
|
||||
month = parseInt(res[2], 10) - 1;
|
||||
day = parseInt(res[3], 10);
|
||||
if (typeof(res[4]) == "undefined" || res[4] === '') {
|
||||
return new Date(year, month, day);
|
||||
}
|
||||
hour = parseInt(res[4], 10);
|
||||
min = parseInt(res[5], 10);
|
||||
sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0;
|
||||
if (typeof(res[7]) != "undefined" && res[7] !== '') {
|
||||
msec = Math.round(1000.0 * parseFloat("0." + res[7]));
|
||||
} else {
|
||||
msec = 0;
|
||||
}
|
||||
if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) {
|
||||
return new Date(year, month, day, hour, min, sec, msec);
|
||||
}
|
||||
var ofs;
|
||||
if (typeof(res[9]) != "undefined" && res[9] !== '') {
|
||||
ofs = parseInt(res[10], 10) * 3600000;
|
||||
if (typeof(res[11]) != "undefined" && res[11] !== '') {
|
||||
ofs += parseInt(res[11], 10) * 60000;
|
||||
}
|
||||
if (res[9] == "-") {
|
||||
ofs = -ofs;
|
||||
}
|
||||
} else {
|
||||
ofs = 0;
|
||||
}
|
||||
return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs);
|
||||
};
|
||||
|
||||
MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) {
|
||||
if (typeof(date) == "undefined" || date === null) {
|
||||
return null;
|
||||
}
|
||||
var hh = date.getHours();
|
||||
var mm = date.getMinutes();
|
||||
var ss = date.getSeconds();
|
||||
var lst = [
|
||||
((realISO && (hh < 10)) ? "0" + hh : hh),
|
||||
((mm < 10) ? "0" + mm : mm),
|
||||
((ss < 10) ? "0" + ss : ss)
|
||||
];
|
||||
return lst.join(":");
|
||||
};
|
||||
|
||||
MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) {
|
||||
if (typeof(date) == "undefined" || date === null) {
|
||||
return null;
|
||||
}
|
||||
var sep = realISO ? "T" : " ";
|
||||
var foot = realISO ? "Z" : "";
|
||||
if (realISO) {
|
||||
date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
|
||||
}
|
||||
return MochiKit.DateTime.toISODate(date) + sep + MochiKit.DateTime.toISOTime(date, realISO) + foot;
|
||||
};
|
||||
|
||||
MochiKit.DateTime.toISODate = function (date) {
|
||||
if (typeof(date) == "undefined" || date === null) {
|
||||
return null;
|
||||
}
|
||||
var _padTwo = MochiKit.DateTime._padTwo;
|
||||
return [
|
||||
date.getFullYear(),
|
||||
_padTwo(date.getMonth() + 1),
|
||||
_padTwo(date.getDate())
|
||||
].join("-");
|
||||
};
|
||||
|
||||
MochiKit.DateTime.americanDate = function (d) {
|
||||
d = d + "";
|
||||
if (typeof(d) != "string" || d.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var a = d.split('/');
|
||||
return new Date(a[2], a[0] - 1, a[1]);
|
||||
};
|
||||
|
||||
MochiKit.DateTime._padTwo = function (n) {
|
||||
return (n > 9) ? n : "0" + n;
|
||||
};
|
||||
|
||||
MochiKit.DateTime.toPaddedAmericanDate = function (d) {
|
||||
if (typeof(d) == "undefined" || d === null) {
|
||||
return null;
|
||||
}
|
||||
var _padTwo = MochiKit.DateTime._padTwo;
|
||||
return [
|
||||
_padTwo(d.getMonth() + 1),
|
||||
_padTwo(d.getDate()),
|
||||
d.getFullYear()
|
||||
].join('/');
|
||||
};
|
||||
|
||||
MochiKit.DateTime.toAmericanDate = function (d) {
|
||||
if (typeof(d) == "undefined" || d === null) {
|
||||
return null;
|
||||
}
|
||||
return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/');
|
||||
};
|
||||
|
||||
MochiKit.DateTime.EXPORT = [
|
||||
"isoDate",
|
||||
"isoTimestamp",
|
||||
"toISOTime",
|
||||
"toISOTimestamp",
|
||||
"toISODate",
|
||||
"americanDate",
|
||||
"toPaddedAmericanDate",
|
||||
"toAmericanDate"
|
||||
];
|
||||
|
||||
MochiKit.DateTime.EXPORT_OK = [];
|
||||
MochiKit.DateTime.EXPORT_TAGS = {
|
||||
":common": MochiKit.DateTime.EXPORT,
|
||||
":all": MochiKit.DateTime.EXPORT
|
||||
};
|
||||
|
||||
MochiKit.DateTime.__new__ = function () {
|
||||
// MochiKit.Base.nameFunctions(this);
|
||||
var base = this.NAME + ".";
|
||||
for (var k in this) {
|
||||
var o = this[k];
|
||||
if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
|
||||
try {
|
||||
o.NAME = base + k;
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.DateTime.__new__();
|
||||
|
||||
if (typeof(MochiKit.Base) != "undefined") {
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.DateTime);
|
||||
} else {
|
||||
(function (globals, module) {
|
||||
if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
|
||||
|| (typeof(MochiKit.__compat__) == 'boolean' && MochiKit.__compat__)) {
|
||||
var all = module.EXPORT_TAGS[":all"];
|
||||
for (var i = 0; i < all.length; i++) {
|
||||
globals[all[i]] = module[all[i]];
|
||||
}
|
||||
}
|
||||
})(this, MochiKit.DateTime);
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.Format 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.Format');
|
||||
}
|
||||
|
||||
if (typeof(MochiKit) == 'undefined') {
|
||||
MochiKit = {};
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.Format) == 'undefined') {
|
||||
MochiKit.Format = {};
|
||||
}
|
||||
|
||||
MochiKit.Format.NAME = "MochiKit.Format";
|
||||
MochiKit.Format.VERSION = "1.3.1";
|
||||
MochiKit.Format.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
MochiKit.Format.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) {
|
||||
return function (num) {
|
||||
num = parseFloat(num);
|
||||
if (typeof(num) == "undefined" || num === null || isNaN(num)) {
|
||||
return placeholder;
|
||||
}
|
||||
var curheader = header;
|
||||
var curfooter = footer;
|
||||
if (num < 0) {
|
||||
num = -num;
|
||||
} else {
|
||||
curheader = curheader.replace(/-/, "");
|
||||
}
|
||||
var me = arguments.callee;
|
||||
var fmt = MochiKit.Format.formatLocale(locale);
|
||||
if (isPercent) {
|
||||
num = num * 100.0;
|
||||
curfooter = fmt.percent + curfooter;
|
||||
}
|
||||
num = MochiKit.Format.roundToFixed(num, precision);
|
||||
var parts = num.split(/\./);
|
||||
var whole = parts[0];
|
||||
var frac = (parts.length == 1) ? "" : parts[1];
|
||||
var res = "";
|
||||
while (whole.length < leadingZeros) {
|
||||
whole = "0" + whole;
|
||||
}
|
||||
if (separatorAt) {
|
||||
while (whole.length > separatorAt) {
|
||||
var i = whole.length - separatorAt;
|
||||
//res = res + fmt.separator + whole.substring(i, whole.length);
|
||||
res = fmt.separator + whole.substring(i, whole.length) + res;
|
||||
whole = whole.substring(0, i);
|
||||
}
|
||||
}
|
||||
res = whole + res;
|
||||
if (precision > 0) {
|
||||
while (frac.length < trailingZeros) {
|
||||
frac = frac + "0";
|
||||
}
|
||||
res = res + fmt.decimal + frac;
|
||||
}
|
||||
return curheader + res + curfooter;
|
||||
};
|
||||
};
|
||||
|
||||
MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) {
|
||||
// http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
|
||||
// | 0 | leading or trailing zeros
|
||||
// | # | just the number
|
||||
// | , | separator
|
||||
// | . | decimal separator
|
||||
// | % | Multiply by 100 and format as percent
|
||||
if (typeof(placeholder) == "undefined") {
|
||||
placeholder = "";
|
||||
}
|
||||
var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
|
||||
if (!match) {
|
||||
throw TypeError("Invalid pattern");
|
||||
}
|
||||
var header = pattern.substr(0, match.index);
|
||||
var footer = pattern.substr(match.index + match[0].length);
|
||||
if (header.search(/-/) == -1) {
|
||||
header = header + "-";
|
||||
}
|
||||
var whole = match[1];
|
||||
var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : "";
|
||||
var isPercent = (typeof(match[3]) == "string" && match[3] != "");
|
||||
var tmp = whole.split(/,/);
|
||||
var separatorAt;
|
||||
if (typeof(locale) == "undefined") {
|
||||
locale = "default";
|
||||
}
|
||||
if (tmp.length == 1) {
|
||||
separatorAt = null;
|
||||
} else {
|
||||
separatorAt = tmp[1].length;
|
||||
}
|
||||
var leadingZeros = whole.length - whole.replace(/0/g, "").length;
|
||||
var trailingZeros = frac.length - frac.replace(/0/g, "").length;
|
||||
var precision = frac.length;
|
||||
var rval = MochiKit.Format._numberFormatter(
|
||||
placeholder, header, footer, locale, isPercent, precision,
|
||||
leadingZeros, separatorAt, trailingZeros
|
||||
);
|
||||
var m = MochiKit.Base;
|
||||
if (m) {
|
||||
var fn = arguments.callee;
|
||||
var args = m.concat(arguments);
|
||||
rval.repr = function () {
|
||||
return [
|
||||
self.NAME,
|
||||
"(",
|
||||
map(m.repr, args).join(", "),
|
||||
")"
|
||||
].join("");
|
||||
};
|
||||
}
|
||||
return rval;
|
||||
};
|
||||
|
||||
MochiKit.Format.formatLocale = function (locale) {
|
||||
if (typeof(locale) == "undefined" || locale === null) {
|
||||
locale = "default";
|
||||
}
|
||||
if (typeof(locale) == "string") {
|
||||
var rval = MochiKit.Format.LOCALE[locale];
|
||||
if (typeof(rval) == "string") {
|
||||
rval = arguments.callee(rval);
|
||||
MochiKit.Format.LOCALE[locale] = rval;
|
||||
}
|
||||
return rval;
|
||||
} else {
|
||||
return locale;
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Format.twoDigitAverage = function (numerator, denominator) {
|
||||
if (denominator) {
|
||||
var res = numerator / denominator;
|
||||
if (!isNaN(res)) {
|
||||
return MochiKit.Format.twoDigitFloat(numerator / denominator);
|
||||
}
|
||||
}
|
||||
return "0";
|
||||
};
|
||||
|
||||
MochiKit.Format.twoDigitFloat = function (someFloat) {
|
||||
var sign = (someFloat < 0 ? '-' : '');
|
||||
var s = Math.floor(Math.abs(someFloat) * 100).toString();
|
||||
if (s == '0') {
|
||||
return s;
|
||||
}
|
||||
if (s.length < 3) {
|
||||
while (s.charAt(s.length - 1) == '0') {
|
||||
s = s.substring(0, s.length - 1);
|
||||
}
|
||||
return sign + '0.' + s;
|
||||
}
|
||||
var head = sign + s.substring(0, s.length - 2);
|
||||
var tail = s.substring(s.length - 2, s.length);
|
||||
if (tail == '00') {
|
||||
return head;
|
||||
} else if (tail.charAt(1) == '0') {
|
||||
return head + '.' + tail.charAt(0);
|
||||
} else {
|
||||
return head + '.' + tail;
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Format.lstrip = function (str, /* optional */chars) {
|
||||
str = str + "";
|
||||
if (typeof(str) != "string") {
|
||||
return null;
|
||||
}
|
||||
if (!chars) {
|
||||
return str.replace(/^\s+/, "");
|
||||
} else {
|
||||
return str.replace(new RegExp("^[" + chars + "]+"), "");
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Format.rstrip = function (str, /* optional */chars) {
|
||||
str = str + "";
|
||||
if (typeof(str) != "string") {
|
||||
return null;
|
||||
}
|
||||
if (!chars) {
|
||||
return str.replace(/\s+$/, "");
|
||||
} else {
|
||||
return str.replace(new RegExp("[" + chars + "]+$"), "");
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Format.strip = function (str, /* optional */chars) {
|
||||
var self = MochiKit.Format;
|
||||
return self.rstrip(self.lstrip(str, chars), chars);
|
||||
};
|
||||
|
||||
MochiKit.Format.truncToFixed = function (aNumber, precision) {
|
||||
aNumber = Math.floor(aNumber * Math.pow(10, precision));
|
||||
var res = (aNumber * Math.pow(10, -precision)).toFixed(precision);
|
||||
if (res.charAt(0) == ".") {
|
||||
res = "0" + res;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
MochiKit.Format.roundToFixed = function (aNumber, precision) {
|
||||
return MochiKit.Format.truncToFixed(
|
||||
aNumber + 0.5 * Math.pow(10, -precision),
|
||||
precision
|
||||
);
|
||||
};
|
||||
|
||||
MochiKit.Format.percentFormat = function (someFloat) {
|
||||
return MochiKit.Format.twoDigitFloat(100 * someFloat) + '%';
|
||||
};
|
||||
|
||||
MochiKit.Format.EXPORT = [
|
||||
"truncToFixed",
|
||||
"roundToFixed",
|
||||
"numberFormatter",
|
||||
"formatLocale",
|
||||
"twoDigitAverage",
|
||||
"twoDigitFloat",
|
||||
"percentFormat",
|
||||
"lstrip",
|
||||
"rstrip",
|
||||
"strip"
|
||||
];
|
||||
|
||||
MochiKit.Format.LOCALE = {
|
||||
en_US: {separator: ",", decimal: ".", percent: "%"},
|
||||
de_DE: {separator: ".", decimal: ",", percent: "%"},
|
||||
fr_FR: {separator: " ", decimal: ",", percent: "%"},
|
||||
"default": "en_US"
|
||||
};
|
||||
|
||||
MochiKit.Format.EXPORT_OK = [];
|
||||
MochiKit.Format.EXPORT_TAGS = {
|
||||
':all': MochiKit.Format.EXPORT,
|
||||
':common': MochiKit.Format.EXPORT
|
||||
};
|
||||
|
||||
MochiKit.Format.__new__ = function () {
|
||||
// MochiKit.Base.nameFunctions(this);
|
||||
var base = this.NAME + ".";
|
||||
var k, v, o;
|
||||
for (k in this.LOCALE) {
|
||||
o = this.LOCALE[k];
|
||||
if (typeof(o) == "object") {
|
||||
o.repr = function () { return this.NAME; };
|
||||
o.NAME = base + "LOCALE." + k;
|
||||
}
|
||||
}
|
||||
for (k in this) {
|
||||
o = this[k];
|
||||
if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
|
||||
try {
|
||||
o.NAME = base + k;
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Format.__new__();
|
||||
|
||||
if (typeof(MochiKit.Base) != "undefined") {
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Format);
|
||||
} else {
|
||||
(function (globals, module) {
|
||||
if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
|
||||
|| (typeof(MochiKit.__compat__) == 'boolean' && MochiKit.__compat__)) {
|
||||
var all = module.EXPORT_TAGS[":all"];
|
||||
for (var i = 0; i < all.length; i++) {
|
||||
globals[all[i]] = module[all[i]];
|
||||
}
|
||||
}
|
||||
})(this, MochiKit.Format);
|
||||
}
|
||||
@@ -1,789 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.Iter 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.Iter');
|
||||
dojo.require('MochiKit.Base');
|
||||
}
|
||||
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use("MochiKit.Base", []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.Base) == 'undefined') {
|
||||
throw "";
|
||||
}
|
||||
} catch (e) {
|
||||
throw "MochiKit.Iter depends on MochiKit.Base!";
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.Iter) == 'undefined') {
|
||||
MochiKit.Iter = {};
|
||||
}
|
||||
|
||||
MochiKit.Iter.NAME = "MochiKit.Iter";
|
||||
MochiKit.Iter.VERSION = "1.3.1";
|
||||
MochiKit.Base.update(MochiKit.Iter, {
|
||||
__repr__: function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
toString: function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
|
||||
MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
|
||||
},
|
||||
|
||||
iter: function (iterable, /* optional */ sentinel) {
|
||||
var self = MochiKit.Iter;
|
||||
if (arguments.length == 2) {
|
||||
return self.takewhile(
|
||||
function (a) { return a != sentinel; },
|
||||
iterable
|
||||
);
|
||||
}
|
||||
if (typeof(iterable.next) == 'function') {
|
||||
return iterable;
|
||||
} else if (typeof(iterable.iter) == 'function') {
|
||||
return iterable.iter();
|
||||
}
|
||||
try {
|
||||
return self.iteratorRegistry.match(iterable);
|
||||
} catch (e) {
|
||||
var m = MochiKit.Base;
|
||||
if (e == m.NotFound) {
|
||||
e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
count: function (n) {
|
||||
if (!n) {
|
||||
n = 0;
|
||||
}
|
||||
var m = MochiKit.Base;
|
||||
return {
|
||||
repr: function () { return "count(" + n + ")"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: m.counter(n)
|
||||
};
|
||||
},
|
||||
|
||||
cycle: function (p) {
|
||||
var self = MochiKit.Iter;
|
||||
var m = MochiKit.Base;
|
||||
var lst = [];
|
||||
var iterator = self.iter(p);
|
||||
return {
|
||||
repr: function () { return "cycle(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
try {
|
||||
var rval = iterator.next();
|
||||
lst.push(rval);
|
||||
return rval;
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
if (lst.length === 0) {
|
||||
this.next = function () {
|
||||
throw self.StopIteration;
|
||||
};
|
||||
} else {
|
||||
var i = -1;
|
||||
this.next = function () {
|
||||
i = (i + 1) % lst.length;
|
||||
return lst[i];
|
||||
};
|
||||
}
|
||||
return this.next();
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
repeat: function (elem, /* optional */n) {
|
||||
var m = MochiKit.Base;
|
||||
if (typeof(n) == 'undefined') {
|
||||
return {
|
||||
repr: function () {
|
||||
return "repeat(" + m.repr(elem) + ")";
|
||||
},
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
repr: function () {
|
||||
return "repeat(" + m.repr(elem) + ", " + n + ")";
|
||||
},
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
if (n <= 0) {
|
||||
throw MochiKit.Iter.StopIteration;
|
||||
}
|
||||
n -= 1;
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
next: function (iterator) {
|
||||
return iterator.next();
|
||||
},
|
||||
|
||||
izip: function (p, q/*, ...*/) {
|
||||
var m = MochiKit.Base;
|
||||
var next = MochiKit.Iter.next;
|
||||
var iterables = m.map(iter, arguments);
|
||||
return {
|
||||
repr: function () { return "izip(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () { return m.map(next, iterables); }
|
||||
};
|
||||
},
|
||||
|
||||
ifilter: function (pred, seq) {
|
||||
var m = MochiKit.Base;
|
||||
seq = MochiKit.Iter.iter(seq);
|
||||
if (pred === null) {
|
||||
pred = m.operator.truth;
|
||||
}
|
||||
return {
|
||||
repr: function () { return "ifilter(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
while (true) {
|
||||
var rval = seq.next();
|
||||
if (pred(rval)) {
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
// mozilla warnings aren't too bright
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
ifilterfalse: function (pred, seq) {
|
||||
var m = MochiKit.Base;
|
||||
seq = MochiKit.Iter.iter(seq);
|
||||
if (pred === null) {
|
||||
pred = m.operator.truth;
|
||||
}
|
||||
return {
|
||||
repr: function () { return "ifilterfalse(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
while (true) {
|
||||
var rval = seq.next();
|
||||
if (!pred(rval)) {
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
// mozilla warnings aren't too bright
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
islice: function (seq/*, [start,] stop[, step] */) {
|
||||
var self = MochiKit.Iter;
|
||||
var m = MochiKit.Base;
|
||||
seq = self.iter(seq);
|
||||
var start = 0;
|
||||
var stop = 0;
|
||||
var step = 1;
|
||||
var i = -1;
|
||||
if (arguments.length == 2) {
|
||||
stop = arguments[1];
|
||||
} else if (arguments.length == 3) {
|
||||
start = arguments[1];
|
||||
stop = arguments[2];
|
||||
} else {
|
||||
start = arguments[1];
|
||||
stop = arguments[2];
|
||||
step = arguments[3];
|
||||
}
|
||||
return {
|
||||
repr: function () {
|
||||
return "islice(" + ["...", start, stop, step].join(", ") + ")";
|
||||
},
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
var rval;
|
||||
while (i < start) {
|
||||
rval = seq.next();
|
||||
i++;
|
||||
}
|
||||
if (start >= stop) {
|
||||
throw self.StopIteration;
|
||||
}
|
||||
start += step;
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
imap: function (fun, p, q/*, ...*/) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
var iterables = m.map(self.iter, m.extend(null, arguments, 1));
|
||||
var map = m.map;
|
||||
var next = self.next;
|
||||
return {
|
||||
repr: function () { return "imap(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
return fun.apply(this, map(next, iterables));
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
applymap: function (fun, seq, self) {
|
||||
seq = MochiKit.Iter.iter(seq);
|
||||
var m = MochiKit.Base;
|
||||
return {
|
||||
repr: function () { return "applymap(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
return fun.apply(self, seq.next());
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
chain: function (p, q/*, ...*/) {
|
||||
// dumb fast path
|
||||
var self = MochiKit.Iter;
|
||||
var m = MochiKit.Base;
|
||||
if (arguments.length == 1) {
|
||||
return self.iter(arguments[0]);
|
||||
}
|
||||
var argiter = m.map(self.iter, arguments);
|
||||
return {
|
||||
repr: function () { return "chain(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
while (argiter.length > 1) {
|
||||
try {
|
||||
return argiter[0].next();
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
argiter.shift();
|
||||
}
|
||||
}
|
||||
if (argiter.length == 1) {
|
||||
// optimize last element
|
||||
var arg = argiter.shift();
|
||||
this.next = m.bind("next", arg);
|
||||
return this.next();
|
||||
}
|
||||
throw self.StopIteration;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
takewhile: function (pred, seq) {
|
||||
var self = MochiKit.Iter;
|
||||
seq = self.iter(seq);
|
||||
return {
|
||||
repr: function () { return "takewhile(...)"; },
|
||||
toString: MochiKit.Base.forwardCall("repr"),
|
||||
next: function () {
|
||||
var rval = seq.next();
|
||||
if (!pred(rval)) {
|
||||
this.next = function () {
|
||||
throw self.StopIteration;
|
||||
};
|
||||
this.next();
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
dropwhile: function (pred, seq) {
|
||||
seq = MochiKit.Iter.iter(seq);
|
||||
var m = MochiKit.Base;
|
||||
var bind = m.bind;
|
||||
return {
|
||||
"repr": function () { return "dropwhile(...)"; },
|
||||
"toString": m.forwardCall("repr"),
|
||||
"next": function () {
|
||||
while (true) {
|
||||
var rval = seq.next();
|
||||
if (!pred(rval)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.next = bind("next", seq);
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_tee: function (ident, sync, iterable) {
|
||||
sync.pos[ident] = -1;
|
||||
var m = MochiKit.Base;
|
||||
var listMin = m.listMin;
|
||||
return {
|
||||
repr: function () { return "tee(" + ident + ", ...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
var rval;
|
||||
var i = sync.pos[ident];
|
||||
|
||||
if (i == sync.max) {
|
||||
rval = iterable.next();
|
||||
sync.deque.push(rval);
|
||||
sync.max += 1;
|
||||
sync.pos[ident] += 1;
|
||||
} else {
|
||||
rval = sync.deque[i - sync.min];
|
||||
sync.pos[ident] += 1;
|
||||
if (i == sync.min && listMin(sync.pos) != sync.min) {
|
||||
sync.min += 1;
|
||||
sync.deque.shift();
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
tee: function (iterable, n/* = 2 */) {
|
||||
var rval = [];
|
||||
var sync = {
|
||||
"pos": [],
|
||||
"deque": [],
|
||||
"max": -1,
|
||||
"min": -1
|
||||
};
|
||||
if (arguments.length == 1) {
|
||||
n = 2;
|
||||
}
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
var _tee = self._tee;
|
||||
for (var i = 0; i < n; i++) {
|
||||
rval.push(_tee(i, sync, iterable));
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
list: function (iterable) {
|
||||
// Fast-path for Array and Array-like
|
||||
var m = MochiKit.Base;
|
||||
if (typeof(iterable.slice) == 'function') {
|
||||
return iterable.slice();
|
||||
} else if (m.isArrayLike(iterable)) {
|
||||
return m.concat(iterable);
|
||||
}
|
||||
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
var rval = [];
|
||||
try {
|
||||
while (true) {
|
||||
rval.push(iterable.next());
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
// mozilla warnings aren't too bright
|
||||
return undefined;
|
||||
},
|
||||
|
||||
|
||||
reduce: function (fn, iterable, /* optional */initial) {
|
||||
var i = 0;
|
||||
var x = initial;
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
if (arguments.length < 3) {
|
||||
try {
|
||||
x = iterable.next();
|
||||
} catch (e) {
|
||||
if (e == self.StopIteration) {
|
||||
e = new TypeError("reduce() of empty sequence with no initial value");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
try {
|
||||
while (true) {
|
||||
x = fn(x, iterable.next());
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
},
|
||||
|
||||
range: function (/* [start,] stop[, step] */) {
|
||||
var start = 0;
|
||||
var stop = 0;
|
||||
var step = 1;
|
||||
if (arguments.length == 1) {
|
||||
stop = arguments[0];
|
||||
} else if (arguments.length == 2) {
|
||||
start = arguments[0];
|
||||
stop = arguments[1];
|
||||
} else if (arguments.length == 3) {
|
||||
start = arguments[0];
|
||||
stop = arguments[1];
|
||||
step = arguments[2];
|
||||
} else {
|
||||
throw new TypeError("range() takes 1, 2, or 3 arguments!");
|
||||
}
|
||||
if (step === 0) {
|
||||
throw new TypeError("range() step must not be 0");
|
||||
}
|
||||
return {
|
||||
next: function () {
|
||||
if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
|
||||
throw MochiKit.Iter.StopIteration;
|
||||
}
|
||||
var rval = start;
|
||||
start += step;
|
||||
return rval;
|
||||
},
|
||||
repr: function () {
|
||||
return "range(" + [start, stop, step].join(", ") + ")";
|
||||
},
|
||||
toString: MochiKit.Base.forwardCall("repr")
|
||||
};
|
||||
},
|
||||
|
||||
sum: function (iterable, start/* = 0 */) {
|
||||
var x = start || 0;
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
try {
|
||||
while (true) {
|
||||
x += iterable.next();
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
},
|
||||
|
||||
exhaust: function (iterable) {
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
try {
|
||||
while (true) {
|
||||
iterable.next();
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
forEach: function (iterable, func, /* optional */self) {
|
||||
var m = MochiKit.Base;
|
||||
if (arguments.length > 2) {
|
||||
func = m.bind(func, self);
|
||||
}
|
||||
// fast path for array
|
||||
if (m.isArrayLike(iterable)) {
|
||||
try {
|
||||
for (var i = 0; i < iterable.length; i++) {
|
||||
func(iterable[i]);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != MochiKit.Iter.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self = MochiKit.Iter;
|
||||
self.exhaust(self.imap(func, iterable));
|
||||
}
|
||||
},
|
||||
|
||||
every: function (iterable, func) {
|
||||
var self = MochiKit.Iter;
|
||||
try {
|
||||
self.ifilterfalse(func, iterable).next();
|
||||
return false;
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
sorted: function (iterable, /* optional */cmp) {
|
||||
var rval = MochiKit.Iter.list(iterable);
|
||||
if (arguments.length == 1) {
|
||||
cmp = MochiKit.Base.compare;
|
||||
}
|
||||
rval.sort(cmp);
|
||||
return rval;
|
||||
},
|
||||
|
||||
reversed: function (iterable) {
|
||||
var rval = MochiKit.Iter.list(iterable);
|
||||
rval.reverse();
|
||||
return rval;
|
||||
},
|
||||
|
||||
some: function (iterable, func) {
|
||||
var self = MochiKit.Iter;
|
||||
try {
|
||||
self.ifilter(func, iterable).next();
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
iextend: function (lst, iterable) {
|
||||
if (MochiKit.Base.isArrayLike(iterable)) {
|
||||
// fast-path for array-like
|
||||
for (var i = 0; i < iterable.length; i++) {
|
||||
lst.push(iterable[i]);
|
||||
}
|
||||
} else {
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
try {
|
||||
while (true) {
|
||||
lst.push(iterable.next());
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lst;
|
||||
},
|
||||
|
||||
groupby: function(iterable, /* optional */ keyfunc) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
if (arguments.length < 2) {
|
||||
keyfunc = m.operator.identity;
|
||||
}
|
||||
iterable = self.iter(iterable);
|
||||
|
||||
// shared
|
||||
var pk = undefined;
|
||||
var k = undefined;
|
||||
var v;
|
||||
|
||||
function fetch() {
|
||||
v = iterable.next();
|
||||
k = keyfunc(v);
|
||||
};
|
||||
|
||||
function eat() {
|
||||
var ret = v;
|
||||
v = undefined;
|
||||
return ret;
|
||||
};
|
||||
|
||||
var first = true;
|
||||
return {
|
||||
repr: function () { return "groupby(...)"; },
|
||||
next: function() {
|
||||
// iterator-next
|
||||
|
||||
// iterate until meet next group
|
||||
while (k == pk) {
|
||||
fetch();
|
||||
if (first) {
|
||||
first = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pk = k;
|
||||
return [k, {
|
||||
next: function() {
|
||||
// subiterator-next
|
||||
if (v == undefined) { // Is there something to eat?
|
||||
fetch();
|
||||
}
|
||||
if (k != pk) {
|
||||
throw self.StopIteration;
|
||||
}
|
||||
return eat();
|
||||
}
|
||||
}];
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
groupby_as_array: function (iterable, /* optional */ keyfunc) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
if (arguments.length < 2) {
|
||||
keyfunc = m.operator.identity;
|
||||
}
|
||||
|
||||
iterable = self.iter(iterable);
|
||||
var result = [];
|
||||
var first = true;
|
||||
var prev_key;
|
||||
while (true) {
|
||||
try {
|
||||
var value = iterable.next();
|
||||
var key = keyfunc(value);
|
||||
} catch (e) {
|
||||
if (e == self.StopIteration) {
|
||||
break;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
if (first || key != prev_key) {
|
||||
var values = [];
|
||||
result.push([key, values]);
|
||||
}
|
||||
values.push(value);
|
||||
first = false;
|
||||
prev_key = key;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
arrayLikeIter: function (iterable) {
|
||||
var i = 0;
|
||||
return {
|
||||
repr: function () { return "arrayLikeIter(...)"; },
|
||||
toString: MochiKit.Base.forwardCall("repr"),
|
||||
next: function () {
|
||||
if (i >= iterable.length) {
|
||||
throw MochiKit.Iter.StopIteration;
|
||||
}
|
||||
return iterable[i++];
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
hasIterateNext: function (iterable) {
|
||||
return (iterable && typeof(iterable.iterateNext) == "function");
|
||||
},
|
||||
|
||||
iterateNextIter: function (iterable) {
|
||||
return {
|
||||
repr: function () { return "iterateNextIter(...)"; },
|
||||
toString: MochiKit.Base.forwardCall("repr"),
|
||||
next: function () {
|
||||
var rval = iterable.iterateNext();
|
||||
if (rval === null || rval === undefined) {
|
||||
throw MochiKit.Iter.StopIteration;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
MochiKit.Iter.EXPORT_OK = [
|
||||
"iteratorRegistry",
|
||||
"arrayLikeIter",
|
||||
"hasIterateNext",
|
||||
"iterateNextIter",
|
||||
];
|
||||
|
||||
MochiKit.Iter.EXPORT = [
|
||||
"StopIteration",
|
||||
"registerIteratorFactory",
|
||||
"iter",
|
||||
"count",
|
||||
"cycle",
|
||||
"repeat",
|
||||
"next",
|
||||
"izip",
|
||||
"ifilter",
|
||||
"ifilterfalse",
|
||||
"islice",
|
||||
"imap",
|
||||
"applymap",
|
||||
"chain",
|
||||
"takewhile",
|
||||
"dropwhile",
|
||||
"tee",
|
||||
"list",
|
||||
"reduce",
|
||||
"range",
|
||||
"sum",
|
||||
"exhaust",
|
||||
"forEach",
|
||||
"every",
|
||||
"sorted",
|
||||
"reversed",
|
||||
"some",
|
||||
"iextend",
|
||||
"groupby",
|
||||
"groupby_as_array"
|
||||
];
|
||||
|
||||
MochiKit.Iter.__new__ = function () {
|
||||
var m = MochiKit.Base;
|
||||
this.StopIteration = new m.NamedError("StopIteration");
|
||||
this.iteratorRegistry = new m.AdapterRegistry();
|
||||
// Register the iterator factory for arrays
|
||||
this.registerIteratorFactory(
|
||||
"arrayLike",
|
||||
m.isArrayLike,
|
||||
this.arrayLikeIter
|
||||
);
|
||||
|
||||
this.registerIteratorFactory(
|
||||
"iterateNext",
|
||||
this.hasIterateNext,
|
||||
this.iterateNextIter
|
||||
);
|
||||
|
||||
this.EXPORT_TAGS = {
|
||||
":common": this.EXPORT,
|
||||
":all": m.concat(this.EXPORT, this.EXPORT_OK)
|
||||
};
|
||||
|
||||
m.nameFunctions(this);
|
||||
|
||||
};
|
||||
|
||||
MochiKit.Iter.__new__();
|
||||
|
||||
//
|
||||
// XXX: Internet Explorer blows
|
||||
//
|
||||
if (!MochiKit.__compat__) {
|
||||
reduce = MochiKit.Iter.reduce;
|
||||
}
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Iter);
|
||||
@@ -1,290 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.Logging 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.Logging');
|
||||
dojo.require('MochiKit.Base');
|
||||
}
|
||||
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use("MochiKit.Base", []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.Base) == 'undefined') {
|
||||
throw "";
|
||||
}
|
||||
} catch (e) {
|
||||
throw "MochiKit.Logging depends on MochiKit.Base!";
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.Logging) == 'undefined') {
|
||||
MochiKit.Logging = {};
|
||||
}
|
||||
|
||||
MochiKit.Logging.NAME = "MochiKit.Logging";
|
||||
MochiKit.Logging.VERSION = "1.3.1";
|
||||
MochiKit.Logging.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
MochiKit.Logging.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
|
||||
MochiKit.Logging.EXPORT = [
|
||||
"LogLevel",
|
||||
"LogMessage",
|
||||
"Logger",
|
||||
"alertListener",
|
||||
"logger",
|
||||
"log",
|
||||
"logError",
|
||||
"logDebug",
|
||||
"logFatal",
|
||||
"logWarning"
|
||||
];
|
||||
|
||||
|
||||
MochiKit.Logging.EXPORT_OK = [
|
||||
"logLevelAtLeast",
|
||||
"isLogMessage",
|
||||
"compareLogMessage"
|
||||
];
|
||||
|
||||
|
||||
MochiKit.Logging.LogMessage = function (num, level, info) {
|
||||
this.num = num;
|
||||
this.level = level;
|
||||
this.info = info;
|
||||
this.timestamp = new Date();
|
||||
};
|
||||
|
||||
MochiKit.Logging.LogMessage.prototype = {
|
||||
repr: function () {
|
||||
var m = MochiKit.Base;
|
||||
return 'LogMessage(' +
|
||||
m.map(
|
||||
m.repr,
|
||||
[this.num, this.level, this.info]
|
||||
).join(', ') + ')';
|
||||
},
|
||||
toString: MochiKit.Base.forwardCall("repr")
|
||||
};
|
||||
|
||||
MochiKit.Base.update(MochiKit.Logging, {
|
||||
logLevelAtLeast: function (minLevel) {
|
||||
var self = MochiKit.Logging;
|
||||
if (typeof(minLevel) == 'string') {
|
||||
minLevel = self.LogLevel[minLevel];
|
||||
}
|
||||
return function (msg) {
|
||||
var msgLevel = msg.level;
|
||||
if (typeof(msgLevel) == 'string') {
|
||||
msgLevel = self.LogLevel[msgLevel];
|
||||
}
|
||||
return msgLevel >= minLevel;
|
||||
};
|
||||
},
|
||||
|
||||
isLogMessage: function (/* ... */) {
|
||||
var LogMessage = MochiKit.Logging.LogMessage;
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (!(arguments[i] instanceof LogMessage)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
compareLogMessage: function (a, b) {
|
||||
return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]);
|
||||
},
|
||||
|
||||
alertListener: function (msg) {
|
||||
alert(
|
||||
"num: " + msg.num +
|
||||
"\nlevel: " + msg.level +
|
||||
"\ninfo: " + msg.info.join(" ")
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
MochiKit.Logging.Logger = function (/* optional */maxSize) {
|
||||
this.counter = 0;
|
||||
if (typeof(maxSize) == 'undefined' || maxSize === null) {
|
||||
maxSize = -1;
|
||||
}
|
||||
this.maxSize = maxSize;
|
||||
this._messages = [];
|
||||
this.listeners = {};
|
||||
this.useNativeConsole = false;
|
||||
};
|
||||
|
||||
MochiKit.Logging.Logger.prototype = {
|
||||
clear: function () {
|
||||
this._messages.splice(0, this._messages.length);
|
||||
},
|
||||
|
||||
logToConsole: function (msg) {
|
||||
if (typeof(window) != "undefined" && window.console
|
||||
&& window.console.log) {
|
||||
// Safari
|
||||
window.console.log(msg);
|
||||
} else if (typeof(opera) != "undefined" && opera.postError) {
|
||||
// Opera
|
||||
opera.postError(msg);
|
||||
} else if (typeof(printfire) == "function") {
|
||||
// FireBug
|
||||
printfire(msg);
|
||||
}
|
||||
},
|
||||
|
||||
dispatchListeners: function (msg) {
|
||||
for (var k in this.listeners) {
|
||||
var pair = this.listeners[k];
|
||||
if (pair.ident != k || (pair[0] && !pair[0](msg))) {
|
||||
continue;
|
||||
}
|
||||
pair[1](msg);
|
||||
}
|
||||
},
|
||||
|
||||
addListener: function (ident, filter, listener) {
|
||||
if (typeof(filter) == 'string') {
|
||||
filter = MochiKit.Logging.logLevelAtLeast(filter);
|
||||
}
|
||||
var entry = [filter, listener];
|
||||
entry.ident = ident;
|
||||
this.listeners[ident] = entry;
|
||||
},
|
||||
|
||||
removeListener: function (ident) {
|
||||
delete this.listeners[ident];
|
||||
},
|
||||
|
||||
baseLog: function (level, message/*, ...*/) {
|
||||
var msg = new MochiKit.Logging.LogMessage(
|
||||
this.counter,
|
||||
level,
|
||||
MochiKit.Base.extend(null, arguments, 1)
|
||||
);
|
||||
this._messages.push(msg);
|
||||
this.dispatchListeners(msg);
|
||||
if (this.useNativeConsole) {
|
||||
this.logToConsole(msg.level + ": " + msg.info.join(" "));
|
||||
}
|
||||
this.counter += 1;
|
||||
while (this.maxSize >= 0 && this._messages.length > this.maxSize) {
|
||||
this._messages.shift();
|
||||
}
|
||||
},
|
||||
|
||||
getMessages: function (howMany) {
|
||||
var firstMsg = 0;
|
||||
if (!(typeof(howMany) == 'undefined' || howMany === null)) {
|
||||
firstMsg = Math.max(0, this._messages.length - howMany);
|
||||
}
|
||||
return this._messages.slice(firstMsg);
|
||||
},
|
||||
|
||||
getMessageText: function (howMany) {
|
||||
if (typeof(howMany) == 'undefined' || howMany === null) {
|
||||
howMany = 30;
|
||||
}
|
||||
var messages = this.getMessages(howMany);
|
||||
if (messages.length) {
|
||||
var lst = map(function (m) {
|
||||
return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
|
||||
}, messages);
|
||||
lst.unshift('LAST ' + messages.length + ' MESSAGES:');
|
||||
return lst.join('');
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
debuggingBookmarklet: function (inline) {
|
||||
if (typeof(MochiKit.LoggingPane) == "undefined") {
|
||||
alert(this.getMessageText());
|
||||
} else {
|
||||
MochiKit.LoggingPane.createLoggingPane(inline || false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
MochiKit.Logging.__new__ = function () {
|
||||
this.LogLevel = {
|
||||
ERROR: 40,
|
||||
FATAL: 50,
|
||||
WARNING: 30,
|
||||
INFO: 20,
|
||||
DEBUG: 10
|
||||
};
|
||||
|
||||
var m = MochiKit.Base;
|
||||
m.registerComparator("LogMessage",
|
||||
this.isLogMessage,
|
||||
this.compareLogMessage
|
||||
);
|
||||
|
||||
var partial = m.partial;
|
||||
|
||||
var Logger = this.Logger;
|
||||
var baseLog = Logger.prototype.baseLog;
|
||||
m.update(this.Logger.prototype, {
|
||||
debug: partial(baseLog, 'DEBUG'),
|
||||
log: partial(baseLog, 'INFO'),
|
||||
error: partial(baseLog, 'ERROR'),
|
||||
fatal: partial(baseLog, 'FATAL'),
|
||||
warning: partial(baseLog, 'WARNING')
|
||||
});
|
||||
|
||||
// indirectly find logger so it can be replaced
|
||||
var self = this;
|
||||
var connectLog = function (name) {
|
||||
return function () {
|
||||
self.logger[name].apply(self.logger, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
this.log = connectLog('log');
|
||||
this.logError = connectLog('error');
|
||||
this.logDebug = connectLog('debug');
|
||||
this.logFatal = connectLog('fatal');
|
||||
this.logWarning = connectLog('warning');
|
||||
this.logger = new Logger();
|
||||
this.logger.useNativeConsole = true;
|
||||
|
||||
this.EXPORT_TAGS = {
|
||||
":common": this.EXPORT,
|
||||
":all": m.concat(this.EXPORT, this.EXPORT_OK)
|
||||
};
|
||||
|
||||
m.nameFunctions(this);
|
||||
|
||||
};
|
||||
|
||||
if (typeof(printfire) == "undefined" &&
|
||||
typeof(document) != "undefined" && document.createEvent &&
|
||||
typeof(dispatchEvent) != "undefined") {
|
||||
// FireBug really should be less lame about this global function
|
||||
printfire = function () {
|
||||
printfire.args = arguments;
|
||||
var ev = document.createEvent("Events");
|
||||
ev.initEvent("printfire", false, true);
|
||||
dispatchEvent(ev);
|
||||
};
|
||||
}
|
||||
|
||||
MochiKit.Logging.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Logging);
|
||||
@@ -1,356 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.LoggingPane 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.LoggingPane');
|
||||
dojo.require('MochiKit.Logging');
|
||||
dojo.require('MochiKit.Base');
|
||||
}
|
||||
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use("MochiKit.Logging", []);
|
||||
JSAN.use("MochiKit.Base", []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.Base) == 'undefined' || typeof(MochiKit.Logging) == 'undefined') {
|
||||
throw "";
|
||||
}
|
||||
} catch (e) {
|
||||
throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!";
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.LoggingPane) == 'undefined') {
|
||||
MochiKit.LoggingPane = {};
|
||||
}
|
||||
|
||||
MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane";
|
||||
MochiKit.LoggingPane.VERSION = "1.3.1";
|
||||
MochiKit.LoggingPane.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
MochiKit.LoggingPane.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) {
|
||||
var m = MochiKit.LoggingPane;
|
||||
inline = !(!inline);
|
||||
if (m._loggingPane && m._loggingPane.inline != inline) {
|
||||
m._loggingPane.closePane();
|
||||
m._loggingPane = null;
|
||||
}
|
||||
if (!m._loggingPane || m._loggingPane.closed) {
|
||||
m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger);
|
||||
}
|
||||
return m._loggingPane;
|
||||
};
|
||||
|
||||
MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) {
|
||||
/* Use a div if inline, pop up a window if not */
|
||||
/* Create the elements */
|
||||
if (typeof(logger) == "undefined" || logger === null) {
|
||||
logger = MochiKit.Logging.logger;
|
||||
}
|
||||
this.logger = logger;
|
||||
var update = MochiKit.Base.update;
|
||||
var updatetree = MochiKit.Base.updatetree;
|
||||
var bind = MochiKit.Base.bind;
|
||||
var clone = MochiKit.Base.clone;
|
||||
var win = window;
|
||||
var uid = "_MochiKit_LoggingPane";
|
||||
if (typeof(MochiKit.DOM) != "undefined") {
|
||||
win = MochiKit.DOM.currentWindow();
|
||||
}
|
||||
if (!inline) {
|
||||
// name the popup with the base URL for uniqueness
|
||||
var url = win.location.href.split("?")[0].replace(/[:\/.><&]/g, "_");
|
||||
var name = uid + "_" + url;
|
||||
var nwin = win.open("", name, "dependent,resizable,height=200");
|
||||
if (!nwin) {
|
||||
alert("Not able to open debugging window due to pop-up blocking.");
|
||||
return undefined;
|
||||
}
|
||||
nwin.document.write(
|
||||
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
|
||||
+ '"http://www.w3.org/TR/html4/loose.dtd">'
|
||||
+ '<html><head><title>[MochiKit.LoggingPane]</title></head>'
|
||||
+ '<body></body></html>'
|
||||
);
|
||||
nwin.document.close();
|
||||
nwin.document.title += ' ' + win.document.title;
|
||||
win = nwin;
|
||||
}
|
||||
var doc = win.document;
|
||||
this.doc = doc;
|
||||
|
||||
// Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
|
||||
var debugPane = doc.getElementById(uid);
|
||||
var existing_pane = !!debugPane;
|
||||
if (debugPane && typeof(debugPane.loggingPane) != "undefined") {
|
||||
debugPane.loggingPane.logger = this.logger;
|
||||
debugPane.loggingPane.buildAndApplyFilter();
|
||||
return debugPane.loggingPane;
|
||||
}
|
||||
|
||||
if (existing_pane) {
|
||||
// clear any existing contents
|
||||
var child;
|
||||
while ((child = debugPane.firstChild)) {
|
||||
debugPane.removeChild(child);
|
||||
}
|
||||
} else {
|
||||
debugPane = doc.createElement("div");
|
||||
debugPane.id = uid;
|
||||
}
|
||||
debugPane.loggingPane = this;
|
||||
var levelFilterField = doc.createElement("input");
|
||||
var infoFilterField = doc.createElement("input");
|
||||
var filterButton = doc.createElement("button");
|
||||
var loadButton = doc.createElement("button");
|
||||
var clearButton = doc.createElement("button");
|
||||
var closeButton = doc.createElement("button");
|
||||
var logPaneArea = doc.createElement("div");
|
||||
var logPane = doc.createElement("div");
|
||||
|
||||
/* Set up the functions */
|
||||
var listenerId = uid + "_Listener";
|
||||
this.colorTable = clone(this.colorTable);
|
||||
var messages = [];
|
||||
var messageFilter = null;
|
||||
|
||||
var messageLevel = function (msg) {
|
||||
var level = msg.level;
|
||||
if (typeof(level) == "number") {
|
||||
level = MochiKit.Logging.LogLevel[level];
|
||||
}
|
||||
return level;
|
||||
};
|
||||
|
||||
var messageText = function (msg) {
|
||||
return msg.info.join(" ");
|
||||
};
|
||||
|
||||
var addMessageText = bind(function (msg) {
|
||||
var level = messageLevel(msg);
|
||||
var text = messageText(msg);
|
||||
var c = this.colorTable[level];
|
||||
var p = doc.createElement("span");
|
||||
p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level;
|
||||
p.style.cssText = "margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: " + c;
|
||||
p.appendChild(doc.createTextNode(level + ": " + text));
|
||||
logPane.appendChild(p);
|
||||
logPane.appendChild(doc.createElement("br"));
|
||||
if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) {
|
||||
logPaneArea.scrollTop = 0;
|
||||
} else {
|
||||
logPaneArea.scrollTop = logPaneArea.scrollHeight;
|
||||
}
|
||||
}, this);
|
||||
|
||||
var addMessage = function (msg) {
|
||||
messages[messages.length] = msg;
|
||||
addMessageText(msg);
|
||||
};
|
||||
|
||||
var buildMessageFilter = function () {
|
||||
var levelre, infore;
|
||||
try {
|
||||
/* Catch any exceptions that might arise due to invalid regexes */
|
||||
levelre = new RegExp(levelFilterField.value);
|
||||
infore = new RegExp(infoFilterField.value);
|
||||
} catch(e) {
|
||||
/* If there was an error with the regexes, do no filtering */
|
||||
logDebug("Error in filter regex: " + e.message);
|
||||
return null;
|
||||
}
|
||||
|
||||
return function (msg) {
|
||||
return (
|
||||
levelre.test(messageLevel(msg)) &&
|
||||
infore.test(messageText(msg))
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
var clearMessagePane = function () {
|
||||
while (logPane.firstChild) {
|
||||
logPane.removeChild(logPane.firstChild);
|
||||
}
|
||||
};
|
||||
|
||||
var clearMessages = function () {
|
||||
messages = [];
|
||||
clearMessagePane();
|
||||
};
|
||||
|
||||
var closePane = bind(function () {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
this.closed = true;
|
||||
if (MochiKit.LoggingPane._loggingPane == this) {
|
||||
MochiKit.LoggingPane._loggingPane = null;
|
||||
}
|
||||
this.logger.removeListener(listenerId);
|
||||
|
||||
debugPane.loggingPane = null;
|
||||
|
||||
if (inline) {
|
||||
debugPane.parentNode.removeChild(debugPane);
|
||||
} else {
|
||||
this.win.close();
|
||||
}
|
||||
}, this);
|
||||
|
||||
var filterMessages = function () {
|
||||
clearMessagePane();
|
||||
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
var msg = messages[i];
|
||||
if (messageFilter === null || messageFilter(msg)) {
|
||||
addMessageText(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.buildAndApplyFilter = function () {
|
||||
messageFilter = buildMessageFilter();
|
||||
|
||||
filterMessages();
|
||||
|
||||
this.logger.removeListener(listenerId);
|
||||
this.logger.addListener(listenerId, messageFilter, addMessage);
|
||||
};
|
||||
|
||||
|
||||
var loadMessages = bind(function () {
|
||||
messages = this.logger.getMessages();
|
||||
filterMessages();
|
||||
}, this);
|
||||
|
||||
var filterOnEnter = bind(function (event) {
|
||||
event = event || window.event;
|
||||
key = event.which || event.keyCode;
|
||||
if (key == 13) {
|
||||
this.buildAndApplyFilter();
|
||||
}
|
||||
}, this);
|
||||
|
||||
/* Create the debug pane */
|
||||
var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
|
||||
if (inline) {
|
||||
style += "; height: 10em; border-top: 2px solid black";
|
||||
} else {
|
||||
style += "; height: 100%;";
|
||||
}
|
||||
debugPane.style.cssText = style;
|
||||
|
||||
if (!existing_pane) {
|
||||
doc.body.appendChild(debugPane);
|
||||
}
|
||||
|
||||
/* Create the filter fields */
|
||||
style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
|
||||
|
||||
updatetree(levelFilterField, {
|
||||
"value": "FATAL|ERROR|WARNING|INFO|DEBUG",
|
||||
"onkeypress": filterOnEnter,
|
||||
"style": style
|
||||
});
|
||||
debugPane.appendChild(levelFilterField);
|
||||
|
||||
updatetree(infoFilterField, {
|
||||
"value": ".*",
|
||||
"onkeypress": filterOnEnter,
|
||||
"style": style
|
||||
});
|
||||
debugPane.appendChild(infoFilterField);
|
||||
|
||||
/* Create the buttons */
|
||||
style = "width: 8%; display:inline; font: " + this.logFont;
|
||||
|
||||
filterButton.appendChild(doc.createTextNode("Filter"));
|
||||
filterButton.onclick = bind("buildAndApplyFilter", this);
|
||||
filterButton.style.cssText = style;
|
||||
debugPane.appendChild(filterButton);
|
||||
|
||||
loadButton.appendChild(doc.createTextNode("Load"));
|
||||
loadButton.onclick = loadMessages;
|
||||
loadButton.style.cssText = style;
|
||||
debugPane.appendChild(loadButton);
|
||||
|
||||
clearButton.appendChild(doc.createTextNode("Clear"));
|
||||
clearButton.onclick = clearMessages;
|
||||
clearButton.style.cssText = style;
|
||||
debugPane.appendChild(clearButton);
|
||||
|
||||
closeButton.appendChild(doc.createTextNode("Close"));
|
||||
closeButton.onclick = closePane;
|
||||
closeButton.style.cssText = style;
|
||||
debugPane.appendChild(closeButton);
|
||||
|
||||
/* Create the logging pane */
|
||||
logPaneArea.style.cssText = "overflow: auto; width: 100%";
|
||||
logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
|
||||
|
||||
logPaneArea.appendChild(logPane);
|
||||
debugPane.appendChild(logPaneArea);
|
||||
|
||||
this.buildAndApplyFilter();
|
||||
loadMessages();
|
||||
|
||||
if (inline) {
|
||||
this.win = undefined;
|
||||
} else {
|
||||
this.win = win;
|
||||
}
|
||||
this.inline = inline;
|
||||
this.closePane = closePane;
|
||||
this.closed = false;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
MochiKit.LoggingPane.LoggingPane.prototype = {
|
||||
"logFont": "8pt Verdana,sans-serif",
|
||||
"colorTable": {
|
||||
"ERROR": "red",
|
||||
"FATAL": "darkred",
|
||||
"WARNING": "blue",
|
||||
"INFO": "black",
|
||||
"DEBUG": "green"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
MochiKit.LoggingPane.EXPORT_OK = [
|
||||
"LoggingPane"
|
||||
];
|
||||
|
||||
MochiKit.LoggingPane.EXPORT = [
|
||||
"createLoggingPane"
|
||||
];
|
||||
|
||||
MochiKit.LoggingPane.__new__ = function () {
|
||||
this.EXPORT_TAGS = {
|
||||
":common": this.EXPORT,
|
||||
":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
|
||||
};
|
||||
|
||||
MochiKit.Base.nameFunctions(this);
|
||||
|
||||
MochiKit.LoggingPane._loggingPane = null;
|
||||
|
||||
};
|
||||
|
||||
MochiKit.LoggingPane.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);
|
||||
152
mozilla/webtools/new-graph/js/mochikit/MochiKit.js
vendored
@@ -1,152 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.MochiKit 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
if (typeof(MochiKit) == 'undefined') {
|
||||
MochiKit = {};
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.MochiKit) == 'undefined') {
|
||||
MochiKit.MochiKit = {};
|
||||
}
|
||||
|
||||
MochiKit.MochiKit.NAME = "MochiKit.MochiKit";
|
||||
MochiKit.MochiKit.VERSION = "1.3.1";
|
||||
MochiKit.MochiKit.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
MochiKit.MochiKit.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
MochiKit.MochiKit.SUBMODULES = [
|
||||
"Base",
|
||||
"Iter",
|
||||
"Logging",
|
||||
"DateTime",
|
||||
"Format",
|
||||
"Async",
|
||||
"DOM",
|
||||
"LoggingPane",
|
||||
"Color",
|
||||
"Signal",
|
||||
"Visual"
|
||||
];
|
||||
|
||||
if (typeof(JSAN) != 'undefined' || typeof(dojo) != 'undefined') {
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.MochiKit');
|
||||
dojo.require("MochiKit.*");
|
||||
}
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
// hopefully this makes it easier for static analysis?
|
||||
JSAN.use("MochiKit.Base", []);
|
||||
JSAN.use("MochiKit.Iter", []);
|
||||
JSAN.use("MochiKit.Logging", []);
|
||||
JSAN.use("MochiKit.DateTime", []);
|
||||
JSAN.use("MochiKit.Format", []);
|
||||
JSAN.use("MochiKit.Async", []);
|
||||
JSAN.use("MochiKit.DOM", []);
|
||||
JSAN.use("MochiKit.LoggingPane", []);
|
||||
JSAN.use("MochiKit.Color", []);
|
||||
JSAN.use("MochiKit.Signal", []);
|
||||
JSAN.use("MochiKit.Visual", []);
|
||||
}
|
||||
(function () {
|
||||
var extend = MochiKit.Base.extend;
|
||||
var self = MochiKit.MochiKit;
|
||||
var modules = self.SUBMODULES;
|
||||
var EXPORT = [];
|
||||
var EXPORT_OK = [];
|
||||
var EXPORT_TAGS = {};
|
||||
var i, k, m, all;
|
||||
for (i = 0; i < modules.length; i++) {
|
||||
m = MochiKit[modules[i]];
|
||||
extend(EXPORT, m.EXPORT);
|
||||
extend(EXPORT_OK, m.EXPORT_OK);
|
||||
for (k in m.EXPORT_TAGS) {
|
||||
EXPORT_TAGS[k] = extend(EXPORT_TAGS[k], m.EXPORT_TAGS[k]);
|
||||
}
|
||||
all = m.EXPORT_TAGS[":all"];
|
||||
if (!all) {
|
||||
all = extend(null, m.EXPORT, m.EXPORT_OK);
|
||||
}
|
||||
var j;
|
||||
for (j = 0; j < all.length; j++) {
|
||||
k = all[j];
|
||||
self[k] = m[k];
|
||||
}
|
||||
}
|
||||
self.EXPORT = EXPORT;
|
||||
self.EXPORT_OK = EXPORT_OK;
|
||||
self.EXPORT_TAGS = EXPORT_TAGS;
|
||||
}());
|
||||
|
||||
} else {
|
||||
if (typeof(MochiKit.__compat__) == 'undefined') {
|
||||
MochiKit.__compat__ = true;
|
||||
}
|
||||
(function () {
|
||||
var scripts = document.getElementsByTagName("script");
|
||||
var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
var base = null;
|
||||
var baseElem = null;
|
||||
var allScripts = {};
|
||||
var i;
|
||||
for (i = 0; i < scripts.length; i++) {
|
||||
var src = scripts[i].getAttribute("src");
|
||||
if (!src) {
|
||||
continue;
|
||||
}
|
||||
allScripts[src] = true;
|
||||
if (src.match(/MochiKit.js$/)) {
|
||||
base = src.substring(0, src.lastIndexOf('MochiKit.js'));
|
||||
baseElem = scripts[i];
|
||||
}
|
||||
}
|
||||
if (base === null) {
|
||||
return;
|
||||
}
|
||||
var modules = MochiKit.MochiKit.SUBMODULES;
|
||||
for (var i = 0; i < modules.length; i++) {
|
||||
if (MochiKit[modules[i]]) {
|
||||
continue;
|
||||
}
|
||||
var uri = base + modules[i] + '.js';
|
||||
if (uri in allScripts) {
|
||||
continue;
|
||||
}
|
||||
if (document.documentElement &&
|
||||
document.documentElement.namespaceURI == kXULNSURI) {
|
||||
// XUL
|
||||
var s = document.createElementNS(kXULNSURI, 'script');
|
||||
s.setAttribute("id", "MochiKit_" + base + modules[i]);
|
||||
s.setAttribute("src", uri);
|
||||
s.setAttribute("type", "application/x-javascript");
|
||||
baseElem.parentNode.appendChild(s);
|
||||
} else {
|
||||
// HTML
|
||||
/*
|
||||
DOM can not be used here because Safari does
|
||||
deferred loading of scripts unless they are
|
||||
in the document or inserted with document.write
|
||||
|
||||
This is not XHTML compliant. If you want XHTML
|
||||
compliance then you must use the packed version of MochiKit
|
||||
or include each script individually (basically unroll
|
||||
these document.write calls into your XHTML source)
|
||||
|
||||
*/
|
||||
document.write('<script src="' + uri +
|
||||
'" type="text/javascript"></script>');
|
||||
}
|
||||
};
|
||||
})();
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.MockDOM 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
if (typeof(MochiKit) == "undefined") {
|
||||
var MochiKit = {};
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.MockDOM) == "undefined") {
|
||||
MochiKit.MockDOM = {};
|
||||
}
|
||||
|
||||
MochiKit.MockDOM.NAME = "MochiKit.MockDOM";
|
||||
MochiKit.MockDOM.VERSION = "1.3.1";
|
||||
|
||||
MochiKit.MockDOM.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
MochiKit.MockDOM.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
MochiKit.MockDOM.createDocument = function () {
|
||||
var doc = new MochiKit.MockDOM.MockElement("DOCUMENT");
|
||||
doc.body = doc.createElement("BODY");
|
||||
doc.appendChild(doc.body);
|
||||
return doc;
|
||||
};
|
||||
|
||||
MochiKit.MockDOM.MockElement = function (name, data) {
|
||||
this.nodeName = name.toUpperCase();
|
||||
if (typeof(data) == "string") {
|
||||
this.nodeValue = data;
|
||||
this.nodeType = 3;
|
||||
} else {
|
||||
this.nodeType = 1;
|
||||
this.childNodes = [];
|
||||
}
|
||||
if (name.substring(0, 1) == "<") {
|
||||
var nameattr = name.substring(
|
||||
name.indexOf('"') + 1, name.lastIndexOf('"'));
|
||||
name = name.substring(1, name.indexOf(" "));
|
||||
this.nodeName = name.toUpperCase();
|
||||
this.setAttribute("name", nameattr);
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.MockDOM.MockElement.prototype = {
|
||||
createElement: function (nodeName) {
|
||||
return new MochiKit.MockDOM.MockElement(nodeName);
|
||||
},
|
||||
createTextNode: function (text) {
|
||||
return new MochiKit.MockDOM.MockElement("text", text);
|
||||
},
|
||||
setAttribute: function (name, value) {
|
||||
this[name] = value;
|
||||
},
|
||||
getAttribute: function (name) {
|
||||
return this[name];
|
||||
},
|
||||
appendChild: function (child) {
|
||||
this.childNodes.push(child);
|
||||
},
|
||||
toString: function () {
|
||||
return "MockElement(" + this.nodeName + ")";
|
||||
}
|
||||
};
|
||||
@@ -1,680 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.Signal 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.Signal');
|
||||
dojo.require('MochiKit.Base');
|
||||
dojo.require('MochiKit.DOM');
|
||||
}
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use('MochiKit.Base', []);
|
||||
JSAN.use('MochiKit.DOM', []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.Base) == 'undefined') {
|
||||
throw '';
|
||||
}
|
||||
} catch (e) {
|
||||
throw 'MochiKit.Signal depends on MochiKit.Base!';
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.DOM) == 'undefined') {
|
||||
throw '';
|
||||
}
|
||||
} catch (e) {
|
||||
throw 'MochiKit.Signal depends on MochiKit.DOM!';
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.Signal) == 'undefined') {
|
||||
MochiKit.Signal = {};
|
||||
}
|
||||
|
||||
MochiKit.Signal.NAME = 'MochiKit.Signal';
|
||||
MochiKit.Signal.VERSION = '1.3.1';
|
||||
|
||||
MochiKit.Signal._observers = [];
|
||||
|
||||
MochiKit.Signal.Event = function (src, e) {
|
||||
this._event = e || window.event;
|
||||
this._src = src;
|
||||
};
|
||||
|
||||
MochiKit.Base.update(MochiKit.Signal.Event.prototype, {
|
||||
|
||||
__repr__: function() {
|
||||
var repr = MochiKit.Base.repr;
|
||||
var str = '{event(): ' + repr(this.event()) +
|
||||
', src(): ' + repr(this.src()) +
|
||||
', type(): ' + repr(this.type()) +
|
||||
', target(): ' + repr(this.target()) +
|
||||
', modifier(): ' + '{alt: ' + repr(this.modifier().alt) +
|
||||
', ctrl: ' + repr(this.modifier().ctrl) +
|
||||
', meta: ' + repr(this.modifier().meta) +
|
||||
', shift: ' + repr(this.modifier().shift) +
|
||||
', any: ' + repr(this.modifier().any) + '}';
|
||||
|
||||
if (this.type() && this.type().indexOf('key') === 0) {
|
||||
str += ', key(): {code: ' + repr(this.key().code) +
|
||||
', string: ' + repr(this.key().string) + '}';
|
||||
}
|
||||
|
||||
if (this.type() && (
|
||||
this.type().indexOf('mouse') === 0 ||
|
||||
this.type().indexOf('click') != -1 ||
|
||||
this.type() == 'contextmenu')) {
|
||||
|
||||
str += ', mouse(): {page: ' + repr(this.mouse().page) +
|
||||
', client: ' + repr(this.mouse().client);
|
||||
|
||||
if (this.type() != 'mousemove') {
|
||||
str += ', button: {left: ' + repr(this.mouse().button.left) +
|
||||
', middle: ' + repr(this.mouse().button.middle) +
|
||||
', right: ' + repr(this.mouse().button.right) + '}}';
|
||||
} else {
|
||||
str += '}';
|
||||
}
|
||||
}
|
||||
if (this.type() == 'mouseover' || this.type() == 'mouseout') {
|
||||
str += ', relatedTarget(): ' + repr(this.relatedTarget());
|
||||
}
|
||||
str += '}';
|
||||
return str;
|
||||
},
|
||||
|
||||
toString: function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
src: function () {
|
||||
return this._src;
|
||||
},
|
||||
|
||||
event: function () {
|
||||
return this._event;
|
||||
},
|
||||
|
||||
type: function () {
|
||||
return this._event.type || undefined;
|
||||
},
|
||||
|
||||
target: function () {
|
||||
return this._event.target || this._event.srcElement;
|
||||
},
|
||||
|
||||
relatedTarget: function () {
|
||||
if (this.type() == 'mouseover') {
|
||||
return (this._event.relatedTarget ||
|
||||
this._event.fromElement);
|
||||
} else if (this.type() == 'mouseout') {
|
||||
return (this._event.relatedTarget ||
|
||||
this._event.toElement);
|
||||
}
|
||||
// throw new Error("relatedTarget only available for 'mouseover' and 'mouseout'");
|
||||
return undefined;
|
||||
},
|
||||
|
||||
modifier: function () {
|
||||
var m = {};
|
||||
m.alt = this._event.altKey;
|
||||
m.ctrl = this._event.ctrlKey;
|
||||
m.meta = this._event.metaKey || false; // IE and Opera punt here
|
||||
m.shift = this._event.shiftKey;
|
||||
m.any = m.alt || m.ctrl || m.shift || m.meta;
|
||||
return m;
|
||||
},
|
||||
|
||||
key: function () {
|
||||
var k = {};
|
||||
if (this.type() && this.type().indexOf('key') === 0) {
|
||||
|
||||
/*
|
||||
|
||||
If you're looking for a special key, look for it in keydown or
|
||||
keyup, but never keypress. If you're looking for a Unicode
|
||||
chracter, look for it with keypress, but never keyup or
|
||||
keydown.
|
||||
|
||||
Notes:
|
||||
|
||||
FF key event behavior:
|
||||
key event charCode keyCode
|
||||
DOWN ku,kd 0 40
|
||||
DOWN kp 0 40
|
||||
ESC ku,kd 0 27
|
||||
ESC kp 0 27
|
||||
a ku,kd 0 65
|
||||
a kp 97 0
|
||||
shift+a ku,kd 0 65
|
||||
shift+a kp 65 0
|
||||
1 ku,kd 0 49
|
||||
1 kp 49 0
|
||||
shift+1 ku,kd 0 0
|
||||
shift+1 kp 33 0
|
||||
|
||||
IE key event behavior:
|
||||
(IE doesn't fire keypress events for special keys.)
|
||||
key event keyCode
|
||||
DOWN ku,kd 40
|
||||
DOWN kp undefined
|
||||
ESC ku,kd 27
|
||||
ESC kp 27
|
||||
a ku,kd 65
|
||||
a kp 97
|
||||
shift+a ku,kd 65
|
||||
shift+a kp 65
|
||||
1 ku,kd 49
|
||||
1 kp 49
|
||||
shift+1 ku,kd 49
|
||||
shift+1 kp 33
|
||||
|
||||
Safari key event behavior:
|
||||
(Safari sets charCode and keyCode to something crazy for
|
||||
special keys.)
|
||||
key event charCode keyCode
|
||||
DOWN ku,kd 63233 40
|
||||
DOWN kp 63233 63233
|
||||
ESC ku,kd 27 27
|
||||
ESC kp 27 27
|
||||
a ku,kd 97 65
|
||||
a kp 97 97
|
||||
shift+a ku,kd 65 65
|
||||
shift+a kp 65 65
|
||||
1 ku,kd 49 49
|
||||
1 kp 49 49
|
||||
shift+1 ku,kd 33 49
|
||||
shift+1 kp 33 33
|
||||
|
||||
*/
|
||||
|
||||
/* look for special keys here */
|
||||
if (this.type() == 'keydown' || this.type() == 'keyup') {
|
||||
k.code = this._event.keyCode;
|
||||
k.string = (MochiKit.Signal._specialKeys[k.code] ||
|
||||
'KEY_UNKNOWN');
|
||||
return k;
|
||||
|
||||
/* look for characters here */
|
||||
} else if (this.type() == 'keypress') {
|
||||
|
||||
/*
|
||||
|
||||
Special key behavior:
|
||||
|
||||
IE: does not fire keypress events for special keys
|
||||
FF: sets charCode to 0, and sets the correct keyCode
|
||||
Safari: sets keyCode and charCode to something stupid
|
||||
|
||||
*/
|
||||
|
||||
k.code = 0;
|
||||
k.string = '';
|
||||
|
||||
if (typeof(this._event.charCode) != 'undefined' &&
|
||||
this._event.charCode !== 0 &&
|
||||
!MochiKit.Signal._specialMacKeys[this._event.charCode]) {
|
||||
k.code = this._event.charCode;
|
||||
k.string = String.fromCharCode(k.code);
|
||||
} else if (this._event.keyCode &&
|
||||
typeof(this._event.charCode) == 'undefined') { // IE
|
||||
k.code = this._event.keyCode;
|
||||
k.string = String.fromCharCode(k.code);
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
}
|
||||
// throw new Error('This is not a key event');
|
||||
return undefined;
|
||||
},
|
||||
|
||||
mouse: function () {
|
||||
var m = {};
|
||||
var e = this._event;
|
||||
|
||||
if (this.type() && (
|
||||
this.type().indexOf('mouse') === 0 ||
|
||||
this.type().indexOf('click') != -1 ||
|
||||
this.type() == 'contextmenu')) {
|
||||
|
||||
m.client = new MochiKit.DOM.Coordinates(0, 0);
|
||||
if (e.clientX || e.clientY) {
|
||||
m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX;
|
||||
m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY;
|
||||
}
|
||||
|
||||
m.page = new MochiKit.DOM.Coordinates(0, 0);
|
||||
if (e.pageX || e.pageY) {
|
||||
m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX;
|
||||
m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY;
|
||||
} else {
|
||||
/*
|
||||
|
||||
IE keeps the document offset in:
|
||||
document.documentElement.clientTop ||
|
||||
document.body.clientTop
|
||||
|
||||
and:
|
||||
document.documentElement.clientLeft ||
|
||||
document.body.clientLeft
|
||||
|
||||
see:
|
||||
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
|
||||
|
||||
The offset is (2,2) in standards mode and (0,0) in quirks
|
||||
mode.
|
||||
|
||||
*/
|
||||
|
||||
var de = MochiKit.DOM._document.documentElement;
|
||||
var b = MochiKit.DOM._document.body;
|
||||
|
||||
m.page.x = e.clientX +
|
||||
(de.scrollLeft || b.scrollLeft) -
|
||||
(de.clientLeft || b.clientLeft);
|
||||
|
||||
m.page.y = e.clientY +
|
||||
(de.scrollTop || b.scrollTop) -
|
||||
(de.clientTop || b.clientTop);
|
||||
|
||||
}
|
||||
if (this.type() != 'mousemove') {
|
||||
m.button = {};
|
||||
m.button.left = false;
|
||||
m.button.right = false;
|
||||
m.button.middle = false;
|
||||
|
||||
/* we could check e.button, but which is more consistent */
|
||||
if (e.which) {
|
||||
m.button.left = (e.which == 1);
|
||||
m.button.middle = (e.which == 2);
|
||||
m.button.right = (e.which == 3);
|
||||
|
||||
/*
|
||||
|
||||
Mac browsers and right click:
|
||||
|
||||
- Safari doesn't fire any click events on a right
|
||||
click:
|
||||
http://bugzilla.opendarwin.org/show_bug.cgi?id=6595
|
||||
|
||||
- Firefox fires the event, and sets ctrlKey = true
|
||||
|
||||
- Opera fires the event, and sets metaKey = true
|
||||
|
||||
oncontextmenu is fired on right clicks between
|
||||
browsers and across platforms.
|
||||
|
||||
*/
|
||||
|
||||
} else {
|
||||
m.button.left = !!(e.button & 1);
|
||||
m.button.right = !!(e.button & 2);
|
||||
m.button.middle = !!(e.button & 4);
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
// throw new Error('This is not a mouse event');
|
||||
return undefined;
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
this.stopPropagation();
|
||||
this.preventDefault();
|
||||
},
|
||||
|
||||
stopPropagation: function () {
|
||||
if (this._event.stopPropagation) {
|
||||
this._event.stopPropagation();
|
||||
} else {
|
||||
this._event.cancelBubble = true;
|
||||
}
|
||||
},
|
||||
|
||||
preventDefault: function () {
|
||||
if (this._event.preventDefault) {
|
||||
this._event.preventDefault();
|
||||
} else {
|
||||
this._event.returnValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/* Safari sets keyCode to these special values onkeypress. */
|
||||
MochiKit.Signal._specialMacKeys = {
|
||||
3: 'KEY_ENTER',
|
||||
63289: 'KEY_NUM_PAD_CLEAR',
|
||||
63276: 'KEY_PAGE_UP',
|
||||
63277: 'KEY_PAGE_DOWN',
|
||||
63275: 'KEY_END',
|
||||
63273: 'KEY_HOME',
|
||||
63234: 'KEY_ARROW_LEFT',
|
||||
63232: 'KEY_ARROW_UP',
|
||||
63235: 'KEY_ARROW_RIGHT',
|
||||
63233: 'KEY_ARROW_DOWN',
|
||||
63302: 'KEY_INSERT',
|
||||
63272: 'KEY_DELETE'
|
||||
};
|
||||
|
||||
/* for KEY_F1 - KEY_F12 */
|
||||
for (i = 63236; i <= 63242; i++) {
|
||||
MochiKit.Signal._specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1); // no F0
|
||||
}
|
||||
|
||||
/* Standard keyboard key codes. */
|
||||
MochiKit.Signal._specialKeys = {
|
||||
8: 'KEY_BACKSPACE',
|
||||
9: 'KEY_TAB',
|
||||
12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
|
||||
13: 'KEY_ENTER',
|
||||
16: 'KEY_SHIFT',
|
||||
17: 'KEY_CTRL',
|
||||
18: 'KEY_ALT',
|
||||
19: 'KEY_PAUSE',
|
||||
20: 'KEY_CAPS_LOCK',
|
||||
27: 'KEY_ESCAPE',
|
||||
32: 'KEY_SPACEBAR',
|
||||
33: 'KEY_PAGE_UP',
|
||||
34: 'KEY_PAGE_DOWN',
|
||||
35: 'KEY_END',
|
||||
36: 'KEY_HOME',
|
||||
37: 'KEY_ARROW_LEFT',
|
||||
38: 'KEY_ARROW_UP',
|
||||
39: 'KEY_ARROW_RIGHT',
|
||||
40: 'KEY_ARROW_DOWN',
|
||||
44: 'KEY_PRINT_SCREEN',
|
||||
45: 'KEY_INSERT',
|
||||
46: 'KEY_DELETE',
|
||||
59: 'KEY_SEMICOLON', // weird, for Safari and IE only
|
||||
91: 'KEY_WINDOWS_LEFT',
|
||||
92: 'KEY_WINDOWS_RIGHT',
|
||||
93: 'KEY_SELECT',
|
||||
106: 'KEY_NUM_PAD_ASTERISK',
|
||||
107: 'KEY_NUM_PAD_PLUS_SIGN',
|
||||
109: 'KEY_NUM_PAD_HYPHEN-MINUS',
|
||||
110: 'KEY_NUM_PAD_FULL_STOP',
|
||||
111: 'KEY_NUM_PAD_SOLIDUS',
|
||||
144: 'KEY_NUM_LOCK',
|
||||
145: 'KEY_SCROLL_LOCK',
|
||||
186: 'KEY_SEMICOLON',
|
||||
187: 'KEY_EQUALS_SIGN',
|
||||
188: 'KEY_COMMA',
|
||||
189: 'KEY_HYPHEN-MINUS',
|
||||
190: 'KEY_FULL_STOP',
|
||||
191: 'KEY_SOLIDUS',
|
||||
192: 'KEY_GRAVE_ACCENT',
|
||||
219: 'KEY_LEFT_SQUARE_BRACKET',
|
||||
220: 'KEY_REVERSE_SOLIDUS',
|
||||
221: 'KEY_RIGHT_SQUARE_BRACKET',
|
||||
222: 'KEY_APOSTROPHE'
|
||||
// undefined: 'KEY_UNKNOWN'
|
||||
};
|
||||
|
||||
/* for KEY_0 - KEY_9 */
|
||||
for (var i = 48; i <= 57; i++) {
|
||||
MochiKit.Signal._specialKeys[i] = 'KEY_' + (i - 48);
|
||||
}
|
||||
|
||||
/* for KEY_A - KEY_Z */
|
||||
for (i = 65; i <= 90; i++) {
|
||||
MochiKit.Signal._specialKeys[i] = 'KEY_' + String.fromCharCode(i);
|
||||
}
|
||||
|
||||
/* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
|
||||
for (i = 96; i <= 105; i++) {
|
||||
MochiKit.Signal._specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
|
||||
}
|
||||
|
||||
/* for KEY_F1 - KEY_F12 */
|
||||
for (i = 112; i <= 123; i++) {
|
||||
MochiKit.Signal._specialKeys[i] = 'KEY_F' + (i - 112 + 1); // no F0
|
||||
}
|
||||
|
||||
MochiKit.Base.update(MochiKit.Signal, {
|
||||
|
||||
__repr__: function () {
|
||||
return '[' + this.NAME + ' ' + this.VERSION + ']';
|
||||
},
|
||||
|
||||
toString: function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
_unloadCache: function () {
|
||||
var self = MochiKit.Signal;
|
||||
var observers = self._observers;
|
||||
|
||||
for (var i = 0; i < observers.length; i++) {
|
||||
self._disconnect(observers[i]);
|
||||
}
|
||||
|
||||
delete self._observers;
|
||||
|
||||
try {
|
||||
window.onload = undefined;
|
||||
} catch(e) {
|
||||
// pass
|
||||
}
|
||||
|
||||
try {
|
||||
window.onunload = undefined;
|
||||
} catch(e) {
|
||||
// pass
|
||||
}
|
||||
},
|
||||
|
||||
_listener: function (src, func, obj, isDOM) {
|
||||
var E = MochiKit.Signal.Event;
|
||||
if (!isDOM) {
|
||||
return MochiKit.Base.bind(func, obj);
|
||||
}
|
||||
obj = obj || src;
|
||||
if (typeof(func) == "string") {
|
||||
return function (nativeEvent) {
|
||||
obj[func].apply(obj, [new E(src, nativeEvent)]);
|
||||
};
|
||||
} else {
|
||||
return function (nativeEvent) {
|
||||
func.apply(obj, [new E(src, nativeEvent)]);
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
connect: function (src, sig, objOrFunc/* optional */, funcOrStr) {
|
||||
src = MochiKit.DOM.getElement(src);
|
||||
var self = MochiKit.Signal;
|
||||
|
||||
if (typeof(sig) != 'string') {
|
||||
throw new Error("'sig' must be a string");
|
||||
}
|
||||
|
||||
var obj = null;
|
||||
var func = null;
|
||||
if (typeof(funcOrStr) != 'undefined') {
|
||||
obj = objOrFunc;
|
||||
func = funcOrStr;
|
||||
if (typeof(funcOrStr) == 'string') {
|
||||
if (typeof(objOrFunc[funcOrStr]) != "function") {
|
||||
throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
|
||||
}
|
||||
} else if (typeof(funcOrStr) != 'function') {
|
||||
throw new Error("'funcOrStr' must be a function or string");
|
||||
}
|
||||
} else if (typeof(objOrFunc) != "function") {
|
||||
throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
|
||||
} else {
|
||||
func = objOrFunc;
|
||||
}
|
||||
if (typeof(obj) == 'undefined' || obj === null) {
|
||||
obj = src;
|
||||
}
|
||||
|
||||
var isDOM = !!(src.addEventListener || src.attachEvent);
|
||||
var listener = self._listener(src, func, obj, isDOM);
|
||||
|
||||
if (src.addEventListener) {
|
||||
src.addEventListener(sig.substr(2), listener, false);
|
||||
} else if (src.attachEvent) {
|
||||
src.attachEvent(sig, listener); // useCapture unsupported
|
||||
}
|
||||
|
||||
var ident = [src, sig, listener, isDOM, objOrFunc, funcOrStr];
|
||||
self._observers.push(ident);
|
||||
|
||||
|
||||
return ident;
|
||||
},
|
||||
|
||||
_disconnect: function (ident) {
|
||||
// check isDOM
|
||||
if (!ident[3]) { return; }
|
||||
var src = ident[0];
|
||||
var sig = ident[1];
|
||||
var listener = ident[2];
|
||||
if (src.removeEventListener) {
|
||||
src.removeEventListener(sig.substr(2), listener, false);
|
||||
} else if (src.detachEvent) {
|
||||
src.detachEvent(sig, listener); // useCapture unsupported
|
||||
} else {
|
||||
throw new Error("'src' must be a DOM element");
|
||||
}
|
||||
},
|
||||
|
||||
disconnect: function (ident) {
|
||||
var self = MochiKit.Signal;
|
||||
var observers = self._observers;
|
||||
var m = MochiKit.Base;
|
||||
if (arguments.length > 1) {
|
||||
// compatibility API
|
||||
var src = MochiKit.DOM.getElement(arguments[0]);
|
||||
var sig = arguments[1];
|
||||
var obj = arguments[2];
|
||||
var func = arguments[3];
|
||||
for (var i = observers.length - 1; i >= 0; i--) {
|
||||
var o = observers[i];
|
||||
if (o[0] === src && o[1] === sig && o[4] === obj && o[5] === func) {
|
||||
self._disconnect(o);
|
||||
observers.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var idx = m.findIdentical(observers, ident);
|
||||
if (idx >= 0) {
|
||||
self._disconnect(ident);
|
||||
observers.splice(idx, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
disconnectAll: function(src/* optional */, sig) {
|
||||
src = MochiKit.DOM.getElement(src);
|
||||
var m = MochiKit.Base;
|
||||
var signals = m.flattenArguments(m.extend(null, arguments, 1));
|
||||
var self = MochiKit.Signal;
|
||||
var disconnect = self._disconnect;
|
||||
var observers = self._observers;
|
||||
if (signals.length === 0) {
|
||||
// disconnect all
|
||||
for (var i = observers.length - 1; i >= 0; i--) {
|
||||
var ident = observers[i];
|
||||
if (ident[0] === src) {
|
||||
disconnect(ident);
|
||||
observers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var sigs = {};
|
||||
for (var i = 0; i < signals.length; i++) {
|
||||
sigs[signals[i]] = true;
|
||||
}
|
||||
for (var i = observers.length - 1; i >= 0; i--) {
|
||||
var ident = observers[i];
|
||||
if (ident[0] === src && ident[1] in sigs) {
|
||||
disconnect(ident);
|
||||
observers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
signal: function (src, sig) {
|
||||
var observers = MochiKit.Signal._observers;
|
||||
src = MochiKit.DOM.getElement(src);
|
||||
var args = MochiKit.Base.extend(null, arguments, 2);
|
||||
var errors = [];
|
||||
for (var i = 0; i < observers.length; i++) {
|
||||
var ident = observers[i];
|
||||
if (ident[0] === src && ident[1] === sig) {
|
||||
try {
|
||||
ident[2].apply(src, args);
|
||||
} catch (e) {
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors.length == 1) {
|
||||
throw errors[0];
|
||||
} else if (errors.length > 1) {
|
||||
var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
|
||||
e.errors = errors;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
MochiKit.Signal.EXPORT_OK = [];
|
||||
|
||||
MochiKit.Signal.EXPORT = [
|
||||
'connect',
|
||||
'disconnect',
|
||||
'signal',
|
||||
'disconnectAll'
|
||||
];
|
||||
|
||||
MochiKit.Signal.__new__ = function (win) {
|
||||
var m = MochiKit.Base;
|
||||
this._document = document;
|
||||
this._window = win;
|
||||
|
||||
try {
|
||||
this.connect(window, 'onunload', this._unloadCache);
|
||||
} catch (e) {
|
||||
// pass: might not be a browser
|
||||
}
|
||||
|
||||
this.EXPORT_TAGS = {
|
||||
':common': this.EXPORT,
|
||||
':all': m.concat(this.EXPORT, this.EXPORT_OK)
|
||||
};
|
||||
|
||||
m.nameFunctions(this);
|
||||
};
|
||||
|
||||
MochiKit.Signal.__new__(this);
|
||||
|
||||
//
|
||||
// XXX: Internet Explorer blows
|
||||
//
|
||||
if (!MochiKit.__compat__) {
|
||||
connect = MochiKit.Signal.connect;
|
||||
disconnect = MochiKit.Signal.disconnect;
|
||||
disconnectAll = MochiKit.Signal.disconnectAll;
|
||||
signal = MochiKit.Signal.signal;
|
||||
}
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Signal);
|
||||
@@ -1,181 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.Test 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.Test');
|
||||
dojo.require('MochiKit.Base');
|
||||
}
|
||||
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use("MochiKit.Base", []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.Base) == 'undefined') {
|
||||
throw "";
|
||||
}
|
||||
} catch (e) {
|
||||
throw "MochiKit.Test depends on MochiKit.Base!";
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.Test) == 'undefined') {
|
||||
MochiKit.Test = {};
|
||||
}
|
||||
|
||||
MochiKit.Test.NAME = "MochiKit.Test";
|
||||
MochiKit.Test.VERSION = "1.3.1";
|
||||
MochiKit.Test.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
MochiKit.Test.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
|
||||
MochiKit.Test.EXPORT = ["runTests"];
|
||||
MochiKit.Test.EXPORT_OK = [];
|
||||
|
||||
MochiKit.Test.runTests = function (obj) {
|
||||
if (typeof(obj) == "string") {
|
||||
obj = JSAN.use(obj);
|
||||
}
|
||||
var suite = new MochiKit.Test.Suite();
|
||||
suite.run(obj);
|
||||
};
|
||||
|
||||
MochiKit.Test.Suite = function () {
|
||||
this.testIndex = 0;
|
||||
MochiKit.Base.bindMethods(this);
|
||||
};
|
||||
|
||||
MochiKit.Test.Suite.prototype = {
|
||||
run: function (obj) {
|
||||
try {
|
||||
obj(this);
|
||||
} catch (e) {
|
||||
this.traceback(e);
|
||||
}
|
||||
},
|
||||
traceback: function (e) {
|
||||
var items = MochiKit.Iter.sorted(MochiKit.Base.items(e));
|
||||
print("not ok " + this.testIndex + " - Error thrown");
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var kv = items[i];
|
||||
if (kv[0] == "stack") {
|
||||
kv[1] = kv[1].split(/\n/)[0];
|
||||
}
|
||||
this.print("# " + kv.join(": "));
|
||||
}
|
||||
},
|
||||
print: function (s) {
|
||||
print(s);
|
||||
},
|
||||
is: function (got, expected, /* optional */message) {
|
||||
var res = 1;
|
||||
var msg = null;
|
||||
try {
|
||||
res = MochiKit.Base.compare(got, expected);
|
||||
} catch (e) {
|
||||
msg = "Can not compare " + typeof(got) + ":" + typeof(expected);
|
||||
}
|
||||
if (res) {
|
||||
msg = "Expected value did not compare equal";
|
||||
}
|
||||
if (!res) {
|
||||
return this.testResult(true, message);
|
||||
}
|
||||
return this.testResult(false, message,
|
||||
[[msg], ["got:", got], ["expected:", expected]]);
|
||||
},
|
||||
|
||||
testResult: function (pass, msg, failures) {
|
||||
this.testIndex += 1;
|
||||
if (pass) {
|
||||
this.print("ok " + this.testIndex + " - " + msg);
|
||||
return;
|
||||
}
|
||||
this.print("not ok " + this.testIndex + " - " + msg);
|
||||
if (failures) {
|
||||
for (var i = 0; i < failures.length; i++) {
|
||||
this.print("# " + failures[i].join(" "));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
isDeeply: function (got, expected, /* optional */message) {
|
||||
var m = MochiKit.Base;
|
||||
var res = 1;
|
||||
try {
|
||||
res = m.compare(got, expected);
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
if (res === 0) {
|
||||
return this.ok(true, message);
|
||||
}
|
||||
var gk = m.keys(got);
|
||||
var ek = m.keys(expected);
|
||||
gk.sort();
|
||||
ek.sort();
|
||||
if (m.compare(gk, ek)) {
|
||||
// differing keys
|
||||
var cmp = {};
|
||||
var i;
|
||||
for (i = 0; i < gk.length; i++) {
|
||||
cmp[gk[i]] = "got";
|
||||
}
|
||||
for (i = 0; i < ek.length; i++) {
|
||||
if (ek[i] in cmp) {
|
||||
delete cmp[ek[i]];
|
||||
} else {
|
||||
cmp[ek[i]] = "expected";
|
||||
}
|
||||
}
|
||||
var diffkeys = m.keys(cmp);
|
||||
diffkeys.sort();
|
||||
var gotkeys = [];
|
||||
var expkeys = [];
|
||||
while (diffkeys.length) {
|
||||
var k = diffkeys.shift();
|
||||
if (k in Object.prototype) {
|
||||
continue;
|
||||
}
|
||||
(cmp[k] == "got" ? gotkeys : expkeys).push(k);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return this.testResult((!res), msg,
|
||||
(msg ? [["got:", got], ["expected:", expected]] : undefined)
|
||||
);
|
||||
},
|
||||
|
||||
ok: function (res, message) {
|
||||
return this.testResult(res, message);
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Test.__new__ = function () {
|
||||
var m = MochiKit.Base;
|
||||
|
||||
this.EXPORT_TAGS = {
|
||||
":common": this.EXPORT,
|
||||
":all": m.concat(this.EXPORT, this.EXPORT_OK)
|
||||
};
|
||||
|
||||
m.nameFunctions(this);
|
||||
|
||||
};
|
||||
|
||||
MochiKit.Test.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Test);
|
||||
@@ -1,402 +0,0 @@
|
||||
/***
|
||||
|
||||
MochiKit.Visual 1.3.1
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito and others. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('MochiKit.Visual');
|
||||
dojo.require('MochiKit.Base');
|
||||
dojo.require('MochiKit.DOM');
|
||||
dojo.require('MochiKit.Color');
|
||||
}
|
||||
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use("MochiKit.Base", []);
|
||||
JSAN.use("MochiKit.DOM", []);
|
||||
JSAN.use("MochiKit.Color", []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(MochiKit.Base) == 'undefined' ||
|
||||
typeof(MochiKit.DOM) == 'undefined' ||
|
||||
typeof(MochiKit.Color) == 'undefined') {
|
||||
throw "";
|
||||
}
|
||||
} catch (e) {
|
||||
throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM and MochiKit.Color!";
|
||||
}
|
||||
|
||||
if (typeof(MochiKit.Visual) == "undefined") {
|
||||
MochiKit.Visual = {};
|
||||
}
|
||||
|
||||
MochiKit.Visual.NAME = "MochiKit.Visual";
|
||||
MochiKit.Visual.VERSION = "1.3.1";
|
||||
|
||||
MochiKit.Visual.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
MochiKit.Visual.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
|
||||
MochiKit.Visual._RoundCorners = function (e, options) {
|
||||
e = MochiKit.DOM.getElement(e);
|
||||
this._setOptions(options);
|
||||
if (this.options.__unstable__wrapElement) {
|
||||
e = this._doWrap(e);
|
||||
}
|
||||
|
||||
var color = this.options.color;
|
||||
var C = MochiKit.Color.Color;
|
||||
if (this.options.color == "fromElement") {
|
||||
color = C.fromBackground(e);
|
||||
} else if (!(color instanceof C)) {
|
||||
color = C.fromString(color);
|
||||
}
|
||||
this.isTransparent = (color.asRGB().a <= 0);
|
||||
|
||||
var bgColor = this.options.bgColor;
|
||||
if (this.options.bgColor == "fromParent") {
|
||||
bgColor = C.fromBackground(e.offsetParent);
|
||||
} else if (!(bgColor instanceof C)) {
|
||||
bgColor = C.fromString(bgColor);
|
||||
}
|
||||
|
||||
this._roundCornersImpl(e, color, bgColor);
|
||||
};
|
||||
|
||||
MochiKit.Visual._RoundCorners.prototype = {
|
||||
_doWrap: function (e) {
|
||||
var parent = e.parentNode;
|
||||
var doc = MochiKit.DOM.currentDocument();
|
||||
if (typeof(doc.defaultView) == "undefined"
|
||||
|| doc.defaultView === null) {
|
||||
return e;
|
||||
}
|
||||
var style = doc.defaultView.getComputedStyle(e, null);
|
||||
if (typeof(style) == "undefined" || style === null) {
|
||||
return e;
|
||||
}
|
||||
var wrapper = MochiKit.DOM.DIV({"style": {
|
||||
display: "block",
|
||||
// convert padding to margin
|
||||
marginTop: style.getPropertyValue("padding-top"),
|
||||
marginRight: style.getPropertyValue("padding-right"),
|
||||
marginBottom: style.getPropertyValue("padding-bottom"),
|
||||
marginLeft: style.getPropertyValue("padding-left"),
|
||||
// remove padding so the rounding looks right
|
||||
padding: "0px"
|
||||
/*
|
||||
paddingRight: "0px",
|
||||
paddingLeft: "0px"
|
||||
*/
|
||||
}});
|
||||
wrapper.innerHTML = e.innerHTML;
|
||||
e.innerHTML = "";
|
||||
e.appendChild(wrapper);
|
||||
return e;
|
||||
},
|
||||
|
||||
_roundCornersImpl: function (e, color, bgColor) {
|
||||
if (this.options.border) {
|
||||
this._renderBorder(e, bgColor);
|
||||
}
|
||||
if (this._isTopRounded()) {
|
||||
this._roundTopCorners(e, color, bgColor);
|
||||
}
|
||||
if (this._isBottomRounded()) {
|
||||
this._roundBottomCorners(e, color, bgColor);
|
||||
}
|
||||
},
|
||||
|
||||
_renderBorder: function (el, bgColor) {
|
||||
var borderValue = "1px solid " + this._borderColor(bgColor);
|
||||
var borderL = "border-left: " + borderValue;
|
||||
var borderR = "border-right: " + borderValue;
|
||||
var style = "style='" + borderL + ";" + borderR + "'";
|
||||
el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
|
||||
},
|
||||
|
||||
_roundTopCorners: function (el, color, bgColor) {
|
||||
var corner = this._createCorner(bgColor);
|
||||
for (var i = 0; i < this.options.numSlices; i++) {
|
||||
corner.appendChild(
|
||||
this._createCornerSlice(color, bgColor, i, "top")
|
||||
);
|
||||
}
|
||||
el.style.paddingTop = 0;
|
||||
el.insertBefore(corner, el.firstChild);
|
||||
},
|
||||
|
||||
_roundBottomCorners: function (el, color, bgColor) {
|
||||
var corner = this._createCorner(bgColor);
|
||||
for (var i = (this.options.numSlices - 1); i >= 0; i--) {
|
||||
corner.appendChild(
|
||||
this._createCornerSlice(color, bgColor, i, "bottom")
|
||||
);
|
||||
}
|
||||
el.style.paddingBottom = 0;
|
||||
el.appendChild(corner);
|
||||
},
|
||||
|
||||
_createCorner: function (bgColor) {
|
||||
var dom = MochiKit.DOM;
|
||||
return dom.DIV({style: {backgroundColor: bgColor.toString()}});
|
||||
},
|
||||
|
||||
_createCornerSlice: function (color, bgColor, n, position) {
|
||||
var slice = MochiKit.DOM.SPAN();
|
||||
|
||||
var inStyle = slice.style;
|
||||
inStyle.backgroundColor = color.toString();
|
||||
inStyle.display = "block";
|
||||
inStyle.height = "1px";
|
||||
inStyle.overflow = "hidden";
|
||||
inStyle.fontSize = "1px";
|
||||
|
||||
var borderColor = this._borderColor(color, bgColor);
|
||||
if (this.options.border && n === 0) {
|
||||
inStyle.borderTopStyle = "solid";
|
||||
inStyle.borderTopWidth = "1px";
|
||||
inStyle.borderLeftWidth = "0px";
|
||||
inStyle.borderRightWidth = "0px";
|
||||
inStyle.borderBottomWidth = "0px";
|
||||
// assumes css compliant box model
|
||||
inStyle.height = "0px";
|
||||
inStyle.borderColor = borderColor.toString();
|
||||
} else if (borderColor) {
|
||||
inStyle.borderColor = borderColor.toString();
|
||||
inStyle.borderStyle = "solid";
|
||||
inStyle.borderWidth = "0px 1px";
|
||||
}
|
||||
|
||||
if (!this.options.compact && (n == (this.options.numSlices - 1))) {
|
||||
inStyle.height = "2px";
|
||||
}
|
||||
|
||||
this._setMargin(slice, n, position);
|
||||
this._setBorder(slice, n, position);
|
||||
|
||||
return slice;
|
||||
},
|
||||
|
||||
_setOptions: function (options) {
|
||||
this.options = {
|
||||
corners: "all",
|
||||
color: "fromElement",
|
||||
bgColor: "fromParent",
|
||||
blend: true,
|
||||
border: false,
|
||||
compact: false,
|
||||
__unstable__wrapElement: false
|
||||
};
|
||||
MochiKit.Base.update(this.options, options);
|
||||
|
||||
this.options.numSlices = (this.options.compact ? 2 : 4);
|
||||
},
|
||||
|
||||
_whichSideTop: function () {
|
||||
var corners = this.options.corners;
|
||||
if (this._hasString(corners, "all", "top")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var has_tl = (corners.indexOf("tl") != -1);
|
||||
var has_tr = (corners.indexOf("tr") != -1);
|
||||
if (has_tl && has_tr) {
|
||||
return "";
|
||||
}
|
||||
if (has_tl) {
|
||||
return "left";
|
||||
}
|
||||
if (has_tr) {
|
||||
return "right";
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
_whichSideBottom: function () {
|
||||
var corners = this.options.corners;
|
||||
if (this._hasString(corners, "all", "bottom")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var has_bl = (corners.indexOf('bl') != -1);
|
||||
var has_br = (corners.indexOf('br') != -1);
|
||||
if (has_bl && has_br) {
|
||||
return "";
|
||||
}
|
||||
if (has_bl) {
|
||||
return "left";
|
||||
}
|
||||
if (has_br) {
|
||||
return "right";
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
_borderColor: function (color, bgColor) {
|
||||
if (color == "transparent") {
|
||||
return bgColor;
|
||||
} else if (this.options.border) {
|
||||
return this.options.border;
|
||||
} else if (this.options.blend) {
|
||||
return bgColor.blendedColor(color);
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
|
||||
_setMargin: function (el, n, corners) {
|
||||
var marginSize = this._marginSize(n) + "px";
|
||||
var whichSide = (
|
||||
corners == "top" ? this._whichSideTop() : this._whichSideBottom()
|
||||
);
|
||||
var style = el.style;
|
||||
|
||||
if (whichSide == "left") {
|
||||
style.marginLeft = marginSize;
|
||||
style.marginRight = "0px";
|
||||
} else if (whichSide == "right") {
|
||||
style.marginRight = marginSize;
|
||||
style.marginLeft = "0px";
|
||||
} else {
|
||||
style.marginLeft = marginSize;
|
||||
style.marginRight = marginSize;
|
||||
}
|
||||
},
|
||||
|
||||
_setBorder: function (el, n, corners) {
|
||||
var borderSize = this._borderSize(n) + "px";
|
||||
var whichSide = (
|
||||
corners == "top" ? this._whichSideTop() : this._whichSideBottom()
|
||||
);
|
||||
|
||||
var style = el.style;
|
||||
if (whichSide == "left") {
|
||||
style.borderLeftWidth = borderSize;
|
||||
style.borderRightWidth = "0px";
|
||||
} else if (whichSide == "right") {
|
||||
style.borderRightWidth = borderSize;
|
||||
style.borderLeftWidth = "0px";
|
||||
} else {
|
||||
style.borderLeftWidth = borderSize;
|
||||
style.borderRightWidth = borderSize;
|
||||
}
|
||||
},
|
||||
|
||||
_marginSize: function (n) {
|
||||
if (this.isTransparent) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var o = this.options;
|
||||
if (o.compact && o.blend) {
|
||||
var smBlendedMarginSizes = [1, 0];
|
||||
return smBlendedMarginSizes[n];
|
||||
} else if (o.compact) {
|
||||
var compactMarginSizes = [2, 1];
|
||||
return compactMarginSizes[n];
|
||||
} else if (o.blend) {
|
||||
var blendedMarginSizes = [3, 2, 1, 0];
|
||||
return blendedMarginSizes[n];
|
||||
} else {
|
||||
var marginSizes = [5, 3, 2, 1];
|
||||
return marginSizes[n];
|
||||
}
|
||||
},
|
||||
|
||||
_borderSize: function (n) {
|
||||
var o = this.options;
|
||||
var borderSizes;
|
||||
if (o.compact && (o.blend || this.isTransparent)) {
|
||||
return 1;
|
||||
} else if (o.compact) {
|
||||
borderSizes = [1, 0];
|
||||
} else if (o.blend) {
|
||||
borderSizes = [2, 1, 1, 1];
|
||||
} else if (o.border) {
|
||||
borderSizes = [0, 2, 0, 0];
|
||||
} else if (this.isTransparent) {
|
||||
borderSizes = [5, 3, 2, 1];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return borderSizes[n];
|
||||
},
|
||||
|
||||
_hasString: function (str) {
|
||||
for (var i = 1; i< arguments.length; i++) {
|
||||
if (str.indexOf(arguments[i]) != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_isTopRounded: function () {
|
||||
return this._hasString(this.options.corners,
|
||||
"all", "top", "tl", "tr"
|
||||
);
|
||||
},
|
||||
|
||||
_isBottomRounded: function () {
|
||||
return this._hasString(this.options.corners,
|
||||
"all", "bottom", "bl", "br"
|
||||
);
|
||||
},
|
||||
|
||||
_hasSingleTextChild: function (el) {
|
||||
return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3);
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Visual.roundElement = function (e, options) {
|
||||
new MochiKit.Visual._RoundCorners(e, options);
|
||||
};
|
||||
|
||||
MochiKit.Visual.roundClass = function (tagName, className, options) {
|
||||
var elements = MochiKit.DOM.getElementsByTagAndClassName(
|
||||
tagName, className
|
||||
);
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
MochiKit.Visual.roundElement(elements[i], options);
|
||||
}
|
||||
};
|
||||
|
||||
// Compatibility with MochiKit 1.0
|
||||
MochiKit.Visual.Color = MochiKit.Color.Color;
|
||||
MochiKit.Visual.getElementsComputedStyle = MochiKit.DOM.computedStyle;
|
||||
|
||||
/* end of Rico adaptation */
|
||||
|
||||
MochiKit.Visual.__new__ = function () {
|
||||
var m = MochiKit.Base;
|
||||
|
||||
m.nameFunctions(this);
|
||||
|
||||
this.EXPORT_TAGS = {
|
||||
":common": this.EXPORT,
|
||||
":all": m.concat(this.EXPORT, this.EXPORT_OK)
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
MochiKit.Visual.EXPORT = [
|
||||
"roundElement",
|
||||
"roundClass"
|
||||
];
|
||||
|
||||
MochiKit.Visual.EXPORT_OK = [];
|
||||
|
||||
MochiKit.Visual.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Visual);
|
||||
@@ -1,17 +0,0 @@
|
||||
dojo.hostenv.conditionalLoadModule({
|
||||
"common": [
|
||||
"MochiKit.Base",
|
||||
"MochiKit.Iter",
|
||||
"MochiKit.Logging",
|
||||
"MochiKit.DateTime",
|
||||
"MochiKit.Format",
|
||||
"MochiKit.Async",
|
||||
"MochiKit.Color"
|
||||
],
|
||||
"browser": [
|
||||
"MochiKit.DOM",
|
||||
"MochiKit.LoggingPane",
|
||||
"MochiKit.Visual"
|
||||
]
|
||||
});
|
||||
dojo.hostenv.moduleLoaded("MochiKit.*");
|
||||
|
Before Width: | Height: | Size: 971 B |
|
Before Width: | Height: | Size: 591 B |
@@ -1,163 +0,0 @@
|
||||
/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
|
||||
/* Container Styles */
|
||||
|
||||
.calcontainer {*height:1%;} /* IE */
|
||||
.calcontainer:after {content:'.';clear:both;display:block;visibility:hidden;height:0;} /* others */
|
||||
|
||||
.calbordered {
|
||||
float:left;
|
||||
padding:5px;
|
||||
background-color:#F7F9FB;
|
||||
border:1px solid #7B9EBD;
|
||||
}
|
||||
|
||||
.calbordered .title {
|
||||
font:73% Arial,Helvetica,sans-serif;
|
||||
color:#000;
|
||||
font-weight:bold;
|
||||
margin-bottom:5px;
|
||||
height:auto;
|
||||
width:304px;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.title .close-icon {
|
||||
position:absolute;
|
||||
right:0;
|
||||
top:0;
|
||||
border:none;
|
||||
}
|
||||
|
||||
.cal2up {
|
||||
float:left;
|
||||
}
|
||||
|
||||
.calnavleft {
|
||||
position:absolute;
|
||||
top:0;
|
||||
bottom:0;
|
||||
height:12px;
|
||||
left:2px;
|
||||
}
|
||||
|
||||
.calnavright {
|
||||
position:absolute;
|
||||
top:0;
|
||||
bottom:0;
|
||||
height:12px;
|
||||
right:2px;
|
||||
}
|
||||
|
||||
/* Calendar element styles */
|
||||
|
||||
.calendar {
|
||||
font:73% Arial,Helvetica,sans-serif;
|
||||
text-align:center;
|
||||
border-spacing:0;
|
||||
}
|
||||
|
||||
td.calcell {
|
||||
width:1.5em;
|
||||
height:1em;
|
||||
border:1px solid #E0E0E0;
|
||||
background-color:#FFF;
|
||||
}
|
||||
|
||||
.calendar.wait td.calcell {
|
||||
color:#999;
|
||||
background-color:#CCC;
|
||||
}
|
||||
|
||||
.calendar.wait td.calcell a {
|
||||
color:#999;
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
td.calcell a {
|
||||
color:#003DB8;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
td.calcell.today {
|
||||
border:1px solid #000;
|
||||
}
|
||||
|
||||
td.calcell.oom {
|
||||
cursor:default;
|
||||
color:#999;
|
||||
background-color:#EEE;
|
||||
border:1px solid #E0E0E0;
|
||||
}
|
||||
|
||||
td.calcell.selected {
|
||||
color:#003DB8;
|
||||
background-color:#FFF19F;
|
||||
border:1px solid #FF9900;
|
||||
}
|
||||
|
||||
td.calcell.calcellhover {
|
||||
cursor:pointer;
|
||||
color:#FFF;
|
||||
background-color:#FF9900;
|
||||
border:1px solid #FF9900;
|
||||
}
|
||||
|
||||
/* Added to perform some correction for Opera 8.5
|
||||
hover redraw bug */
|
||||
table:hover {
|
||||
background-color:#FFF;
|
||||
}
|
||||
|
||||
td.calcell.calcellhover a {
|
||||
color:#FFF;
|
||||
}
|
||||
|
||||
td.calcell.restricted {
|
||||
text-decoration:line-through;
|
||||
}
|
||||
|
||||
td.calcell.previous {
|
||||
color:#CCC;
|
||||
}
|
||||
|
||||
td.calcell.highlight1 { background-color:#CCFF99; }
|
||||
td.calcell.highlight2 { background-color:#99CCFF; }
|
||||
td.calcell.highlight3 { background-color:#FFCCCC; }
|
||||
td.calcell.highlight4 { background-color:#CCFF99; }
|
||||
|
||||
|
||||
.calhead {
|
||||
border:1px solid #E0E0E0;
|
||||
vertical-align:middle;
|
||||
background-color:#FFF;
|
||||
}
|
||||
|
||||
.calheader {
|
||||
position:relative;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.calheader img {
|
||||
border:none;
|
||||
}
|
||||
|
||||
.calweekdaycell {
|
||||
color:#666;
|
||||
font-weight:normal;
|
||||
}
|
||||
|
||||
.calfoot {
|
||||
background-color:#EEE;
|
||||
}
|
||||
|
||||
.calrowhead, .calrowfoot {
|
||||
color:#666;
|
||||
font-size:9px;
|
||||
font-style:italic;
|
||||
font-weight:normal;
|
||||
width:15px;
|
||||
}
|
||||
|
||||
.calrowhead {
|
||||
border-right-width:2px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 93 B |
|
Before Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 88 B |
|
Before Width: | Height: | Size: 85 B |
@@ -1,206 +0,0 @@
|
||||
.overlay {
|
||||
position:absolute;
|
||||
display:block;
|
||||
}
|
||||
|
||||
.tt {
|
||||
visibility:hidden;
|
||||
position:absolute;
|
||||
color:#333;
|
||||
background-color:#FDFFB4;
|
||||
font-family:arial,helvetica,verdana,sans-serif;
|
||||
padding:2px;
|
||||
border:1px solid #FCC90D;
|
||||
font:100% sans-serif;
|
||||
width:auto;
|
||||
}
|
||||
|
||||
* html body.masked select {
|
||||
visibility:hidden;
|
||||
}
|
||||
|
||||
* html div.panel-container select {
|
||||
visibility:inherit;
|
||||
}
|
||||
|
||||
* html div.drag select {
|
||||
visibility:hidden;
|
||||
}
|
||||
|
||||
* html div.hide-select select {
|
||||
visibility:hidden;
|
||||
}
|
||||
|
||||
.mask {
|
||||
z-index:0;
|
||||
display:none;
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
background-color:#CCC;
|
||||
-moz-opacity: 0.5;
|
||||
opacity:.50;
|
||||
filter: alpha(opacity=50);
|
||||
}
|
||||
.mask[id]{ /* IE6 and below Can't See This */
|
||||
position:fixed;
|
||||
}
|
||||
|
||||
.hide-scrollbars * {
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.hide-scrollbars textarea, .hide-scrollbars select {
|
||||
overflow:hidden;
|
||||
display:none;
|
||||
}
|
||||
|
||||
.show-scrollbars textarea, .show-scrollbars select {
|
||||
overflow:visible;
|
||||
}
|
||||
|
||||
.panel-container {
|
||||
position:absolute;
|
||||
background-color:transparent;
|
||||
z-index:6;
|
||||
visibility:hidden;
|
||||
overflow:visible;
|
||||
width:auto;
|
||||
}
|
||||
|
||||
.panel-container.matte {
|
||||
padding:3px;
|
||||
background-color:#FFF;
|
||||
}
|
||||
|
||||
.panel-container.matte .underlay {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.panel-container.shadow {
|
||||
padding:0px;
|
||||
background-color:transparent;
|
||||
}
|
||||
|
||||
.panel-container.shadow .underlay {
|
||||
visibility:inherit;
|
||||
position:absolute;
|
||||
background-color:#CCC;
|
||||
top:3px;left:3px;
|
||||
z-index:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
-moz-opacity: 0.7;
|
||||
opacity:.70;
|
||||
filter:alpha(opacity=70);
|
||||
}
|
||||
|
||||
.panel {
|
||||
visibility:hidden;
|
||||
border-collapse:separate;
|
||||
position:relative;
|
||||
left:0px;top:0px;
|
||||
font:1em Arial;
|
||||
background-color:#FFF;
|
||||
border:1px solid #000;
|
||||
z-index:1;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
.panel .hd {
|
||||
background-color:#3d77cb;
|
||||
color:#FFF;
|
||||
font-size:1em;
|
||||
height:1em;
|
||||
border:1px solid #FFF;
|
||||
border-bottom:1px solid #000;
|
||||
font-weight:bold;
|
||||
overflow:hidden;
|
||||
padding:4px;
|
||||
}
|
||||
|
||||
.panel .bd {
|
||||
overflow:hidden;
|
||||
padding:4px;
|
||||
}
|
||||
|
||||
.panel .bd p {
|
||||
margin:0 0 1em;
|
||||
}
|
||||
|
||||
.panel .close {
|
||||
position:absolute;
|
||||
top:5px;
|
||||
right:4px;
|
||||
z-index:6;
|
||||
height:12px;
|
||||
width:12px;
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
background-repeat:no-repeat;
|
||||
cursor:pointer;
|
||||
visibility:inherit;
|
||||
}
|
||||
|
||||
.panel .close.nonsecure {
|
||||
background-image:url(http://us.i1.yimg.com/us.yimg.com/i/nt/ic/ut/alt3/close12_1.gif);
|
||||
}
|
||||
|
||||
.panel .close.secure {
|
||||
background-image:url(https://a248.e.akamai.net/sec.yimg.com/i/nt/ic/ut/alt3/close12_1.gif);
|
||||
}
|
||||
|
||||
.panel .ft {
|
||||
padding:4px;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.simple-dialog .bd .icon {
|
||||
background-repeat:no-repeat;
|
||||
width:16px;
|
||||
height:16px;
|
||||
margin-right:10px;
|
||||
float:left;
|
||||
}
|
||||
|
||||
.dialog .ft, .simple-dialog .ft {
|
||||
padding-bottom:5px;
|
||||
padding-right:5px;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
.dialog form, .simple-dialog form {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.button-group button {
|
||||
font:100 76% verdana;
|
||||
text-decoration:none;
|
||||
background-color: #E4E4E4;
|
||||
color: #333;
|
||||
cursor: hand;
|
||||
vertical-align: middle;
|
||||
border: 2px solid #797979;
|
||||
border-top-color:#FFF;
|
||||
border-left-color:#FFF;
|
||||
margin:2px;
|
||||
padding:2px;
|
||||
}
|
||||
|
||||
.button-group button.default {
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.button-group button:hover, .button-group button.hover {
|
||||
border:2px solid #90A029;
|
||||
background-color:#EBF09E;
|
||||
border-top-color:#FFF;
|
||||
border-left-color:#FFF;
|
||||
}
|
||||
|
||||
.button-group button:active {
|
||||
border:2px solid #E4E4E4;
|
||||
background-color:#BBB;
|
||||
border-top-color:#333;
|
||||
border-left-color:#333;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 928 B |
|
Before Width: | Height: | Size: 601 B |
|
Before Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 142 B |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 130 B |
|
Before Width: | Height: | Size: 111 B |
@@ -1,264 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
|
||||
Code licensed under the BSD License:
|
||||
http://developer.yahoo.net/yui/license.txt
|
||||
*/
|
||||
|
||||
|
||||
/* Menu styles */
|
||||
|
||||
div.yuimenu {
|
||||
|
||||
z-index:1;
|
||||
visibility:hidden;
|
||||
background-color:#f6f7ee;
|
||||
border:solid 1px #c4c4be;
|
||||
padding:1px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* MenuBar Styles */
|
||||
|
||||
div.yuimenubar {
|
||||
|
||||
background-color:#f6f7ee;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Application of "zoom:1" triggers "haslayout" in IE so that the module's
|
||||
body clears its floated elements
|
||||
*/
|
||||
div.yuimenubar div.bd {
|
||||
|
||||
zoom:1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Clear the module body for other browsers
|
||||
*/
|
||||
div.yuimenubar div.bd:after {
|
||||
|
||||
content:'.';
|
||||
display:block;
|
||||
clear:both;
|
||||
visibility:hidden;
|
||||
height:0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Matches the group title (H6) inside a Menu or MenuBar instance */
|
||||
|
||||
div.yuimenu h6,
|
||||
div.yuimenubar h6 {
|
||||
|
||||
font-size:100%;
|
||||
font-weight:normal;
|
||||
margin:0;
|
||||
border:solid 1px #c4c4be;
|
||||
color:#b9b9b9;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenubar h6 {
|
||||
|
||||
float:left;
|
||||
display:inline; /* Prevent margin doubling in IE */
|
||||
padding:4px 12px;
|
||||
border-width:0 1px 0 0;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu h6 {
|
||||
|
||||
float:none;
|
||||
display:block;
|
||||
border-width:1px 0 0 0;
|
||||
padding:5px 10px 0 10px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Matches the UL inside a Menu or MenuBar instance */
|
||||
|
||||
div.yuimenubar ul {
|
||||
|
||||
list-style-type:none;
|
||||
margin:0;
|
||||
padding:0;
|
||||
overflow:hidden;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu ul {
|
||||
|
||||
list-style-type:none;
|
||||
border:solid 1px #c4c4be;
|
||||
border-width:1px 0 0 0;
|
||||
margin:0;
|
||||
padding:10px 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
div.yuimenu ul.first,
|
||||
div.yuimenu ul.hastitle,
|
||||
div.yuimenu h6.first {
|
||||
|
||||
border-width:0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* MenuItem and MenuBarItem styles */
|
||||
|
||||
div.yuimenu li,
|
||||
div.yuimenubar li {
|
||||
|
||||
font-size:85%;
|
||||
cursor:pointer;
|
||||
cursor:hand;
|
||||
white-space:nowrap;
|
||||
text-align:left;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li.yuimenuitem {
|
||||
|
||||
padding:2px 24px;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li li,
|
||||
div.yuimenubar li li {
|
||||
|
||||
font-size:100%;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Matches the help text for a MenuItem instance */
|
||||
|
||||
div.yuimenu li em {
|
||||
|
||||
font-style:normal;
|
||||
margin:0 0 0 40px;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li a em {
|
||||
|
||||
margin:0;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li a,
|
||||
div.yuimenubar li a {
|
||||
|
||||
/*
|
||||
"zoom:1" triggers "haslayout" in IE to ensure that the mouseover and
|
||||
mouseout events bubble to the parent LI in IE.
|
||||
*/
|
||||
zoom:1;
|
||||
color:#000;
|
||||
text-decoration:none;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Matches the sub menu indicator for a MenuItem instance */
|
||||
|
||||
div.yuimenu li img {
|
||||
|
||||
margin:0 -16px 0 10px;
|
||||
border:0;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li.hassubmenu,
|
||||
div.yuimenu li.hashelptext {
|
||||
|
||||
text-align:right;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li.hassubmenu a.hassubmenu,
|
||||
div.yuimenu li.hashelptext a.hashelptext {
|
||||
|
||||
float:left;
|
||||
display:inline; /* Prevent margin doubling in IE */
|
||||
text-align:left;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Matches focused and selected MenuItem instances */
|
||||
|
||||
div.yuimenu li.selected,
|
||||
div.yuimenubar li.selected {
|
||||
|
||||
background-color:#8c8ad0;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li.selected a.selected,
|
||||
div.yuimenubar li.selected a.selected {
|
||||
|
||||
text-decoration:underline;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li.selected a.selected,
|
||||
div.yuimenu li.selected em.selected,
|
||||
div.yuimenubar li.selected a.selected {
|
||||
|
||||
color:#fff;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Matches disabled MenuItem instances */
|
||||
|
||||
div.yuimenu li.disabled,
|
||||
div.yuimenubar li.disabled {
|
||||
|
||||
cursor:default;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenu li.disabled a.disabled,
|
||||
div.yuimenu li.disabled em.disabled,
|
||||
div.yuimenubar li.disabled a.disabled {
|
||||
|
||||
color:#b9b9b9;
|
||||
cursor:default;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenubar li.yuimenubaritem {
|
||||
|
||||
float:left;
|
||||
display:inline; /* Prevent margin doubling in IE */
|
||||
border-width:0 0 0 1px;
|
||||
border-style:solid;
|
||||
border-color:#c4c4be;
|
||||
padding:4px 24px;
|
||||
margin:0;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenubar li.yuimenubaritem.first {
|
||||
|
||||
border-width:0;
|
||||
|
||||
}
|
||||
|
||||
div.yuimenubar li.yuimenubaritem img {
|
||||
|
||||
margin:0 0 0 10px;
|
||||
vertical-align:middle;
|
||||
|
||||
}
|
||||
|
Before Width: | Height: | Size: 63 B |
|
Before Width: | Height: | Size: 63 B |
|
Before Width: | Height: | Size: 63 B |
|
Before Width: | Height: | Size: 56 B |
|
Before Width: | Height: | Size: 56 B |
|
Before Width: | Height: | Size: 56 B |
|
Before Width: | Height: | Size: 552 B |
|
Before Width: | Height: | Size: 545 B |
|
Before Width: | Height: | Size: 563 B |
|
Before Width: | Height: | Size: 504 B |
|
Before Width: | Height: | Size: 539 B |
|
Before Width: | Height: | Size: 568 B |