diff --git a/site/Fit_Calculator/bar_bore_calc.php b/site/Fit_Calculator/bar_bore_calc.php new file mode 100644 index 0000000..87c510e --- /dev/null +++ b/site/Fit_Calculator/bar_bore_calc.php @@ -0,0 +1,157 @@ + + + + +<:: Welcome to Slowtwitch.com ::>: Bar to Head Tube Calculator + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

F.I.S.T. Bar to Head Tube Calculator

+
+

All values are in millimeters!

+
+
+
+
Bar-Bore Y
+
+
+ +
+
+
+
Bar-Bore X
+
+
+ +
+
+
+
Head Angle
+
+
+ +
+
+
+
Stem Length
+
+
+ +
+
+
+
Stem Angle
+
+
+
Plug in actual stem pitch. Write 0 [the number zero] for an extension perpendicular to the steerer; -6 for 6° down from perpendicular, 6 for 6° up; -17° for a "7-shaped" stem; and so forth. +
+
+
+
Stem Clamp Height
+
+
+ +
+
+
+
Spacer Height
+
+
+ +
+
+
+
Headset Topcap
+
+
+ +
+
+
+
+
+
+ Agree to Terms +
+
+
+
+
+
+ +
+
+
+
+

The calculator above is designed to help fitters trained in the F.I.S.T. tri + bike fit protocol to generate geometries for custom triathlon bikes. Note + that the inputs required to use this calculator include "stack" and "reach." + These values are described at length in our tri bike fit articles on Slowtwitch.com. +

+ +

+ Even if the fit is performed correctly, pitfalls loom. You must have the + tools to accurately find the stack and reach of the bike that fits under the + rider. The fitter is required to account for the stem length, stem pitch, + height of the stem clamp, headset upper stack, spacers under the stem if + any, and of course the choice of aerobar. He then must have an accurate way + of generating the stack and reach measures, using either a fit bike (best is + the bike made by Exit Cycling) that accurately generates these values + (taking into consideration negative reach if applicable), or he must use an external tool, such + as Serotta's X/Y tool. +

+

TERMS OF USE

+

+ + This calculator consists of a set of trigonometric and geometric equations. + It solves math equations. That's all it does. There are no warranties + expressed or implied that these geometries cause a bike to be safe, or + comfortable, or powerful, or aerodynamic, or even be ridden; or indeed can + even be built. Should you build or cause to build a bike based on + geometries calculated by this generator, you do so at your own risk. You + agree to hold harmless Slowtwitch.com, its owners, employees and contractors + against all claims arising out of your use of this calculator. You agree to + assume all risk and liability associated with using this calculator. You + agree that the final determination of an appropriate geometry rests with you + and/or any customer for whom you may be building this bike, or causing it to + be built, and with the company building the bike. +

+
+ +
+
+
+ +
+
+ + +
+ + + + + diff --git a/site/Fit_Calculator/bar_bore_calc_X.php b/site/Fit_Calculator/bar_bore_calc_X.php new file mode 100644 index 0000000..a5f0adc --- /dev/null +++ b/site/Fit_Calculator/bar_bore_calc_X.php @@ -0,0 +1,144 @@ + + + + +<:: Welcome to Slowtwitch.com ::>: Bar to Head Tube Calculator + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

F.I.S.T. Bar to Head Tube Calculator

+
+
+
+

Input

+
+
+
Bar-Bore Y
+
+
+
+
+
Bar-Bore X
+
+
+
+
+
Head Tube Angle
+
+
+
+
+
Stem Length
+
+
+
+
+
Stem Angle
+
+
+
+
+
Stem Clamp Height
+
+
+
+
+
Spacer Height
+
+
+
+
+
Headset Topcap
+
+
+
+
+
+
+

Output

+

Stack:

+

Reach:

+
+
+ +

+ Even if the fit is performed correctly, pitfalls loom. You must have the + tools to accurately find the stack and reach of the bike that fits under the + rider. The fitter is required to account for the stem length, stem pitch, + height of the stem clamp, headset upper stack, spacers under the stem if + any, and of course the choice of aerobar. He then must have an accurate way + of generating the stack and reach measures, using either a fit bike (best is + the bike made by Exit Cycling) that accurately generates these values + (taking into consideration negative reach if applicable), or he must use an external tool, such + as Serotta's X/Y tool. +

+
+ +
+
+
+ +
+
+ + +
+ + + + + diff --git a/site/Fit_Calculator/config.php b/site/Fit_Calculator/config.php new file mode 100644 index 0000000..b109762 --- /dev/null +++ b/site/Fit_Calculator/config.php @@ -0,0 +1,21 @@ + diff --git a/site/Fit_Calculator/do_calc.php b/site/Fit_Calculator/do_calc.php new file mode 100644 index 0000000..1d160cf --- /dev/null +++ b/site/Fit_Calculator/do_calc.php @@ -0,0 +1,214 @@ + + + + + +<:: Welcome to Slowtwitch.com ::>: Custom Tri Geometry Calculator + + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+

F.I.S.T Custom Bike Calculator

+
+
+

Input

+
+
+
Stack
+
+
+
+
+
Reach
+
+
+
+
+
Seat Angle
+
+
+
+
+
Head Tube Angle
+
+
+
+
+
Fork Offset
+
+
+
+
+
Fork Length
+
+
+
+
+
BB Drop
+
+
+
+
+
Chainstay
+
+
+
+
+
Rear Wheel
+
+
+
+
+
Headset Lower Stack
+
+
+
+
+
Wheel Size
+
+
+
+
+
+
+

Frame Measurements

+
+
+
BB Height
+
+
+
+
+
Trail
+
+
+
+
+
Eff. Top Tube Length
+
+
+
+
+
Head Tube Length
+
+
+
+
+
Wheelbase
+
+
+
+
+
Front Center
+
+
+
+
+
+
+ WARNING: Your front center is too short!

'; + } + + if( ($front_center < 525) && ($wheel_size == 650) ){ + echo '

WARNING: Your front center is too short!

'; + } + + ?> + + +
+
+
+ +
+
+ + +
+ + + + diff --git a/site/Fit_Calculator/fit_calculator.php b/site/Fit_Calculator/fit_calculator.php new file mode 100644 index 0000000..415881d --- /dev/null +++ b/site/Fit_Calculator/fit_calculator.php @@ -0,0 +1,323 @@ + + + + +<:: Welcome to Slowtwitch.com ::>: Custom Tri Geometry Calculator + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

F.I.S.T Custom Bike Calculator

+
+

All values are in millimeters!

+
+
+ +
+
Serotta X
+
+ +
+
+
Head Angle
+
+
+ +
+
+
+
Stem Length
+
+
+ +
+
+
+
Stem Angle
+
+
+
+ Plug in actual stem pitch. Write 0 [the number zero] for an extension perpendicular to the steerer; -6 for 6° down from perpendicular, 6 for 6° up; -17° for a "7-shaped" stem; and so forth. +
+
+
+
Stem Clamp Height
+
+
+ +
+
+
+
Spacer Height
+
+
+ +
+
+
+
Headset Topcap
+
+
+ + + + +
+
+ +
+
Stack
+
+ +
+
+
Reach
+
+
+ +
+
+ +
+
Chain Stay
+
+
+
+ (Note that some custom tri bike makers have a standard chain + stay length, because these builders fair the rear wheel with the trailing + edge of the seat tube. Find your chosen bike maker's chain + stay value before you send him calcs generated here.) +
+
+
+
Seat Angle
+
+
+ +
+
+ +
+
Head Angle
+
+
+ +
+
+ +
+
Fork Offset
+
+
+ +
+
+
+
Fork Length
+
+
+ +
+
+
+
+
+
+
+
+
+
HS Lower Stack
+
+
+
+ (1.5mm is a typical value for integrated headsets; you'll want to change this if your custom builder builds with external headsets, which is frequently the case. The oft-used Chris King headset has a lower stack of 13.7mm.) +
+
+
+
BB Drop
+
+
+ +
+
+
+
Rear Wheel
+
+
+ +
+
+
+
Wheel Size
+
+
+ 700C (Note: Changing this will reset certain values)
+ 650C +
+
+
+
Morphology
+
+
+ Standard (Note: Changing this will reset certain values)
+ Long Legged +
+
+
+
+
+
+ Agree to Terms +
+
+
+
+
+
+ + +
+
+
+
+ +

The calculator above is designed to help fitters trained in the F.I.S.T. tri + bike fit protocol to generate geometries for custom triathlon bikes. Note + that the inputs required to use this calculator include "stack" and "reach." + These values are described at length in our tri bike fit articles on Slowtwitch.com. +

+

+ The F.I.S.T. fitting protocol is a two-step process: First, the fitter + finds the rider's "fit coordinates," aka his "points in space." The second + part of the protocol focuses on finding the right production bike to match + those fit coordinates or, in this case, generating a custom geometry that + matches the fit coordinates. But, know this: It is remarkably easy to + calculate a "bad" custom geometry for a rider. The culprit is most often a + badly executed "Part I" of this protocol, that is, the fitter executed a + poor fit session. If this happens, the calculator below will faithfully + generate the geometry for a bad bike to perfectly match the bad fit. + Forewarned is forearmed. +

+ +

+ Even if the fit is performed correctly, pitfalls loom. You must have the + tools to accurately find the stack and reach of the bike that fits under the + rider. The fitter is required to account for the stem length, stem pitch, + height of the stem clamp, headset upper stack, spacers under the stem if + any, and of course the choice of aerobar. He then must have an accurate way + of generating the stack and reach measures, using either a fit bike (best is + the bike made by Exit Cycling) that accurately generates these values + (taking into consideration negative reach if applicable), or he must use an external tool, such + as Serotta's X/Y tool. +

+ Anyone who uses this calculator can change any of the defaults below. + Toggling from 700c to 650c, or from standard to long-legged morphology, will + change the defaults, but you can still override our defaults and insert your + own values. There are explanatory notes below, and you are encouraged to + heed them. +

+

OTHER NOTES

+ This calculator "refuses" to return geometry for bikes with + front/center values less than 560mm on a 700c bike and 525mm on a 650c bike. + This, because of shoe overlap. Some bike makers think these minimum values + should be even higher, by 5mm or 10mm. If the calculator displays this + error message, you'll need to add reach; or you'll need to shallow the head + angle and add fork offset; or both. +

+ All bike makers, custom makers included, feature a minimum head tube length + for the bikes they can build. Find this value out, from your chosen custom + builder(s), because this calculator doesn't know what those minimum values + are for each builder. Keep in mind that if your custom builder builds with + external headsets, you must change the default lower headset stack in the + calculator, and you must account for the potentially significant upper + stack. +

+ Morphologies: The calculator generates a geometry for long-legged, + short-torsoed riders by employing two tactical changes, designed to grant + the rider a lower center of mass, and a longer base of support for his + otherwise high center of mass. When you select "Long Legged" the calculator + drops the bottom bracket 10 extra millimeters below the bike's centerline; + and it also shallows the head angle one degree, and adds 6mm of fork offset + in order to keep the trail a constant value (our default settings generate a + trail of about 61mm, more or less). Of course, you can override these + defaults, and if your rider wishes (let us say) a higher bottom bracket + notwithstanding his high center of mass, so be it. Just change the default. +

+ Yes, lengthening the front/center of the bike while keeping the cockpit + distance and trail constant can be achieved through shallowing the head + angle while adding to the fork offset. The calculator will employ this + tactic when you choose the long legged morphology option. This may result + in a fork with an offset greater than 45mm. Not many fork manufacturers + make forks with offsets greater than 45mm, so you'll want to check + availability before you build or cause to have built a bike requiring this + fork offset. +

+

TERMS OF USE

+ + This calculator consists of a set of trigonometric and geometric equations. + It solves math equations. That's all it does. There are no warranties + expressed or implied that these geometries cause a bike to be safe, or + comfortable, or powerful, or aerodynamic, or even be ridden; or indeed can + even be built. Should you build or cause to build a bike based on + geometries calculated by this generator, you do so at your own risk. You + agree to hold harmless Slowtwitch.com, its owners, employees and contractors + against all claims arising out of your use of this calculator. You agree to + assume all risk and liability associated with using this calculator. You + agree that the final determination of an appropriate geometry rests with you + and/or any customer for whom you may be building this bike, or causing it to + be built, and with the company building the bike. +

+ +
+ +
+
+
+ +
+
+ + +
+ + + + diff --git a/site/Fit_Calculator/include_breadcrumb.php b/site/Fit_Calculator/include_breadcrumb.php new file mode 100644 index 0000000..7104a01 --- /dev/null +++ b/site/Fit_Calculator/include_breadcrumb.php @@ -0,0 +1,5 @@ + diff --git a/site/Fit_Calculator/include_sidebar.php b/site/Fit_Calculator/include_sidebar.php new file mode 100644 index 0000000..d02f6d2 --- /dev/null +++ b/site/Fit_Calculator/include_sidebar.php @@ -0,0 +1,5 @@ + +
+ diff --git a/site/Fit_Calculator/stem_calc.php b/site/Fit_Calculator/stem_calc.php new file mode 100644 index 0000000..35fd4d9 --- /dev/null +++ b/site/Fit_Calculator/stem_calc.php @@ -0,0 +1,151 @@ + + + + +<:: Welcome to Slowtwitch.com ::>: F.I.S.T STEM Calculator + + + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

F.I.S.T STEM Calculator

+
+

All values are in millimeters! Except for angles, which are in degrees.

+ +
+
+
+
Head Angle
+
+
+ +
+
+
+
Stem Length
+
+
+ +
+
+
+
Stem Angle
+
+
+
Plug in actual stem pitch. Write 0 [the number zero] for an extension perpendicular to the steerer; -6 for 6° down from perpendicular, 6 for 6° up; -17° for a "7-shaped" stem; and so forth. +
+
+
+
Stem Clamp Height
+
+
+ +
+
+
+
Spacer Height
+
+
+ +
+
+
+
Headset Topcap
+
+
+ +
+
+
+
+
+
+ Agree to Terms +
+
+
+
+
+
+ + + + + +
+
+
+
+ +

The calculator above is designed to help fitters trained in the F.I.S.T. tri + bike fit protocol to generate geometries for custom triathlon bikes. Note + that the inputs required to use this calculator include "stack" and "reach." + These values are described at length in our tri bike fit articles on Slowtwitch.com. +

+ +

+ Even if the fit is performed correctly, pitfalls loom. You must have the + tools to accurately find the stack and reach of the bike that fits under the + rider. The fitter is required to account for the stem length, stem pitch, + height of the stem clamp, headset upper stack, spacers under the stem if + any, and of course the choice of aerobar. He then must have an accurate way + of generating the stack and reach measures, using either a fit bike (best is + the bike made by Exit Cycling) that accurately generates these values + (taking into consideration negative reach if applicable), or he must use an external tool, such + as Serotta's X/Y tool. +

+

TERMS OF USE

+

+ + This calculator consists of a set of trigonometric and geometric equations. + It solves math equations. That's all it does. There are no warranties + expressed or implied that these geometries cause a bike to be safe, or + comfortable, or powerful, or aerodynamic, or even be ridden; or indeed can + even be built. Should you build or cause to build a bike based on + geometries calculated by this generator, you do so at your own risk. You + agree to hold harmless Slowtwitch.com, its owners, employees and contractors + against all claims arising out of your use of this calculator. You agree to + assume all risk and liability associated with using this calculator. You + agree that the final determination of an appropriate geometry rests with you + and/or any customer for whom you may be building this bike, or causing it to + be built, and with the company building the bike. +

+ +
+ +
+
+
+ +
+
+ + +
+ + + + diff --git a/site/Fit_Calculator/stem_calc_X.php b/site/Fit_Calculator/stem_calc_X.php new file mode 100644 index 0000000..ed89550 --- /dev/null +++ b/site/Fit_Calculator/stem_calc_X.php @@ -0,0 +1,146 @@ + + + + + +<:: Welcome to Slowtwitch.com ::>: Stem Rise & Stretch Calculator + + + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

F.I.S.T Stem Calculator

+
+
+
+

Input

+
+
+
Head Tube Angle
+
+
+ +
+
+
+
Stem Length
+
+
+ +
+
+
+
Stem Angle
+
+
+ +
+
+
+
Stem Clamp Height
+
+
+ +
+
+
+
Spacer Height
+
+
+ +
+
+
+
Headset Topcap
+
+
+ +
+
+
+
+
+

Output

+

Rise:

+

Stretch:

+
+
+

Return to the Stem Calculator

+

+ Even if the fit is performed correctly, pitfalls loom. You must have the + tools to accurately find the stack and reach of the bike that fits under the + rider. The fitter is required to account for the stem length, stem pitch, + height of the stem clamp, headset upper stack, spacers under the stem if + any, and of course the choice of aerobar. He then must have an accurate way + of generating the stack and reach measures, using either a fit bike (best is + the bike made by Exit Cycling) that accurately generates these values + (taking into consideration negative reach if applicable), or he must use an external tool, such + as Serotta's X/Y tool. +

+
+ +
+
+
+ +
+
+ + +
+ + + + diff --git a/site/ads.txt b/site/ads.txt new file mode 100644 index 0000000..029d642 --- /dev/null +++ b/site/ads.txt @@ -0,0 +1,220 @@ +Insticator.com,058fb58a-5aac-432c-bb56-a8e3e300437c, DIRECT #Insticator_Version_2.0 +33across.com, 0010b00001rrPUnAAM, DIRECT, bbea06d9c4d2853c +pubmatic.com, 158136, RESELLER, 5d62403b186f2ace +gumgum.com, 13318, RESELLER, ffdef49475d318a9 +adtech.com, 12094, RESELLER +adtech.com, 9993, RESELLER +advangelists.com, 8d3bba7425e7c98c50f52ca1b52d3735, RESELLER, 60d26397ec060f98 +rubiconproject.com, 21434, RESELLER, 0bfd66d529a55807 +pubmatic.com, 158569, RESELLER, 5d62403b186f2ace +springserve.com, 868, DIRECT, a24eb641fc82e93d +contextweb.com, 526740, RESELLER, 89ff185a4c4e857c +appnexus.com, 7096, DIRECT +rhythmone.com, 1755648630, RESELLER, a670c89d4a324e47 +rubiconproject.com, 18126, RESELLER, 0bfd66d529a55807 +pubmatic.com, 157607, RESELLER, 5d62403b186f2ace +video.unrulymedia.com, UNRX-PUB-b7b8af13-0a12-4d37-8b27-0dc8aa90e3e2, RESELLER +advertising.com, 8656, RESELLER +lkqd.net, 39, RESELLER, 59c49fa9598a0117 +spotxchange.com, 77201, RESELLER, 7842df1d2fe2db34 +contextweb.com, 558458, RESELLER, 89ff185a4c4e857c +loopme.com, 5641, RESELLER, 6c8d5f95897a5a3b +tremorhub.com, u6pqo-bygoc, RESELLER, 1a4e959a1b50034a +mobfox.com, 67448, RESELLER +springserve.com, 5, RESELLER, a24eb641fc82e93d +google.com, pub-7630961163643137, DIRECT, f08c47fec0942fa0 +aps.amazon.com, 70fb13d1-ab65-42ac-a7ca-0b4e680d5c92, DIRECT +openx.com, 540191398, RESELLER, 6a698e2ec38604c6 +pubmatic.com, 157150, RESELLER, 5d62403b186f2ace +districtm.io, 100962, RESELLER +rubiconproject.com, 18020, RESELLER, 0bfd66d529a55807 +rhythmone.com, 1654642120, RESELLER, a670c89d4a324e47 +adtech.com, 12068, RESELLER +google.com, pub-0796790890307838, RESELLER, f08c47fec0942fa0 +pubmatic.com, 157866, RESELLER, 5d62403b186f2ace +openx.com, 539624483, RESELLER, 6a698e2ec38604c6 +rubiconproject.com, 18304, RESELLER, 0bfd66d529a55807 +indexexchange.com, 186318, RESELLER +rhythmone.com, 1575167821, RESELLER +advertising.com, 10238, RESELLER +appnexus.com, 3695, RESELLER +beachfront.com, 13310, DIRECT, e2541279e8e2ca4d +EMXDGT.com, 22, DIRECT, 1e1d41537f7cad7f +Appnexus.com, 1356, RESELLER, f5ab79cb980f11d1 +brightcom.com, 15800, DIRECT +google.com, pub-5231479214411897, RESELLER, f08c47fec0942fa0 +google.com, pub-4207323757133151, RESELLER, f08c47fec0942fa0 +lkqd.net, 49, RESELLER, 59c49fa9598a0117 +advertising.com, 23302, RESELLER +freewheel.tv, 118529, RESELLER +freewheel.tv, 118537, RESELLER +beachfront.com, 1333, RESELLER, e2541279e8e2ca4d +advertising.com, 2270, RESELLER +advertising.com, 26347, RESELLER +advertising.com, 23889, RESELLER +conversantmedia.com, 40291, DIRECT, 03113cd04947736d +appnexus.com, 4052, RESELLER +openx.com, 540031703, RESELLER, 6a698e2ec38604c6 +contextweb.com, 561998, RESELLER, 89ff185a4c4e857c +pubmatic.com, 158100, RESELLER, 5d62403b186f2ace +districtm.io, 100683, DIRECT, 3fd707be9c4527c3 +appnexus.com, 1908, RESELLER, f5ab79cb980f11d1 +lkqd.net, 252, RESELLER, 59c49fa9598a0117 +lkqd.com, 252, RESELLER, 59c49fa9598a0117 +springserve.com, 105, RESELLER, a24eb641fc82e93d +advertising.com, 3531, RESELLER +rhythmone.com, 2968119028, RESELLER, a670c89d4a324e47 +pubmatic.com, 157903, RESELLER, 5d62403b186f2ace +openx.com, 540454059, RESELLER, 6a698e2ec38604c6 +e-planning.net, ca658eed27b34b00, DIRECT +rubiconproject.com, 12186, RESELLER, 0bfd66d529a55807 +pubmatic.com, 156631, RESELLER, 5d62403b186f2ace +rhythmone.com, 1767353092, RESELLER, a670c89d4a324e47 +indexexchange.com, 190243, DIRECT +valo.ai, e4dffdb0d6a5e665b9f98e11abf61fa7, Direct +improvedigital.com, 1066, RESELLER +contextweb.com, 561954, RESELLER, 89ff185a4c4e857c +advertising.com, 18632, RESELLER +lkqd.net, 286, RESELLER, 59c49fa9598a0117 +beachfront.com, 4469, RESELLER, e2541279e8e2ca4d +aniview.com, 57712eeef83f155c398b4567, reseller +cosmoshq.com, 1002, DIRECT +gumgum.com, 13344, DIRECT, ffdef49475d318a9 +appnexus.com, 1001, reseller, f5ab79cb980f11d1 +appnexus.com, 1942, reseller, f5ab79cb980f11d1 +appnexus.com, 2758, reseller, f5ab79cb980f11d1 +appnexus.com, 3135, reseller, f5ab79cb980f11d1 +bidtellect.com, 1407, reseller, 1c34aa2d85d45e93 +contextweb.com, 558355, reseller +openx.com, 537120563, reseller, 6a698e2ec38604c6 +openx.com, 537149485, reseller, 6a698e2ec38604c6 +spotx.tv, 147949, reseller, 7842df1d2fe2db34 +spotxchange.com, 147949, reseller, 7842df1d2fe2db34 +google.com, pub-9557089510405422, reseller, f08c47fec0942fa0 +google.com, pub-3848273848634341, reseller, f08c47fec0942fa0 +rhythmone.com, 78519861, reseller +appnexus.com, 7597, reseller, f5ab79cb980f11d1 +33across.com, 0013300001r0t9mAAA, reseller +appnexus.com, 10239, reseller, f5ab79cb980f11d1 +rubiconproject.com, 16414, reseller, 0bfd66d529a55807 +pubmatic.com, 156423, reseller, 5d62403b186f2ace +openx.com, 539392223, reseller, 6a698e2ec38604c6 +rhythmone.com, 2439829435, reseller, a670c89d4a324e47 +emxdgt.com, 326, reseller, 1e1d41537f7cad7f +pubmatic.com, 157897, reseller, 5d62403b186f2ace +synacor.com, 82151, RESELLER, e108f11b2cdf7d5b +coxmt.com, 2000067995202, RESELLER +appnexus.com, 9316, RESELLER, f5ab79cb980f11d1 +pubmatic.com, 156344, RESELLER, 5d62403b186f2ace +rubiconproject.com, 13344, RESELLER, 0bfd66d529a55807 +improvedigital.com, 1277, DIRECT +improvedigital.com, 1276, DIRECT +indexexchange.com, 187071, DIRECT, 50b1c356f2c5c8fc +indexexchange.com, 187482, DIRECT, 50b1c356f2c5c8fc +openx.com, 537117488, RESELLER, 6a698e2ec38604c6 +openx.com, 540105394, RESELLER, 6a698e2ec38604c6 +Pubmatic.com, 95054, DIRECT, 5d62403b186f2ace +Pubmatic.com, 95054, RESELLER, 5d62403b186f2ace +Pubmatic.com, 157119, DIRECT, 5d62403b186f2ace +Pubmatic.com, 157119, RESELLER, 5d62403b186f2ace +contextweb.com, 561664, RESELLER, 89ff185a4c4e857c +rhythmone.com, 136898039, DIRECT, a670c89d4a324e47 +Rhythmone.com, 527383184, DIRECT, a670c89d4a324e47 +RTBHOUSE.COM, eDr4TCudLLHttcPmswNj, DIRECT +rubiconproject.com, 17062, DIRECT, 0bfd66d529a55807 +rubiconproject.com, 17980, DIRECT, 0bfd66d529a55807 +smartadserver.com, 3262, DIRECT +smartadserver.com, 3262, RESELLER +contextweb.com, 560288, RESELLER, 89ff185a4c4e857c +pubmatic.com, 156439, RESELLER +pubmatic.com, 154037, RESELLER +pubmatic.com, 156030, RESELLER, 5d62403b186f2ace +rubiconproject.com, 16114, RESELLER, 0bfd66d529a55807 +rubiconproject.com, 13132, RESELLER, 0bfd66d529a55807 +openx.com, 537149888, RESELLER, 6a698e2ec38604c6 +appnexus.com, 3703, RESELLER, f5ab79cb980f11d1 +groundtruth.com, 107, RESELLER, 81cbf0a75a5e0e9a +districtm.io, 101760, RESELLER, 3fd707be9c4527c3 +loopme.com, s-2411, RESELLER, 6c8d5f95897a5a3b +loopme.com, 5679, RESELLER, 6c8d5f95897a5a3b +sonobi.com, e315a43aa9, DIRECT, d1a215d9eb5aee9e +rhythmone.com, 1059622079, RESELLER, a670c89d4a324e47 +contextweb.com, 560606, RESELLER, 89ff185a4c4e857c +sonobi.com, 70bc4d0919, DIRECT, d1a215d9eb5aee9e +sovrn.com, 257618, DIRECT, fafdf38b16bf6b2b +lijit.com, 257618, DIRECT, fafdf38b16bf6b2b +appnexus.com, 1360, RESELLER, f5ab79cb980f11d1 +gumgum.com, 11645, RESELLER, ffdef49475d318a9 +openx.com, 538959099, RESELLER, 6a698e2ec38604c6 +openx.com, 539924617, RESELLER, 6a698e2ec38604c6 +pubmatic.com, 137711, RESELLER, 5d62403b186f2ace +pubmatic.com, 156212, RESELLER, 5d62403b186f2ace +pubmatic.com, 156700, RESELLER, 5d62403b186f2ace +rubiconproject.com, 17960, RESELLER, 0bfd66d529a55807 +spotxchange.com, 110408, RESELLER, 7842df1d2fe2db34 +spotx.tv, 110408, RESELLER, 7842df1d2fe2db34 +springserve.com, 873, DIRECT, a24eb641fc82e93d +beachfront.com, 4969, RESELLER, e2541279e8e2ca4d +advertising.com, 26282, RESELLER +pubmatic.com, 157310, RESELLER, 5d62403b186f2ace +rhythmone.com, 2968119028, DIRECT, a670c89d4a324e47 +spotxchange.com, 239904, RESELLER, 7842df1d2fe2db34 +spotx.tv, 239904, RESELLER, 7842df1d2fe2db34 +contextweb.com, 561910, RESELLER, 89ff185a4c4e857c +adtech.com, 4937, RESELLER +adtech.com, 11605, RESELLER +pubmatic.com, 158135, RESELLER, 5d62403b186f2ace +contextweb.com, 562056, RESELLER, 89ff185a4c4e857c +pubmatic.com, 148800, RESELLER, 5d62403b186f2ace +pubmatic.com, 156957, RESELLER, 5d62403b186f2ace +openx.com, 537143737, RESELLER, 6a698e2ec38604c6 +openx.com, 540259865, RESELLER, 6a698e2ec38604c6 +openx.com, 540423120, RESELLER, 6a698e2ec38604c6 +google.com, pub-1772611089853771, RESELLER, f08c47fec0942fa0 +google.com, pub-8268618999035658, RESELLER, f08c47fec0942fa0 +google.com, pub-9328633604439863, RESELLER, f08c47fec0942fa0 +google.com, pub-6968738577620513, RESELLER, f08c47fec0942fa0 +google.com, pub-6254331789601537, RESELLER, f08c47fec0942fa0 +ucfunnel.com, par-488A3E6BD8D997D0ED8B3BD34D8BA4B, RESELLER +advertising.com, 19623, RESELLER +indexexchange.com, 183965, RESELLER, 50b1c356f2c5c8fc +pubmatic.com, 156084, RESELLER, 5d62403b186f2ace +pubmatic.com, 156325, RESELLER, 5d62403b186f2ace +pubmatic.com, 156458, RESELLER, 5d62403b186f2ace +rubiconproject.com, 18222, RESELLER, 0bfd66d529a55807 +districtm.io, 101769, RESELLER, 3fd707be9c4527c3 +synacor.com, 82129, DIRECT, e108f11b2cdf7d5b +rubiconproject.com, 13344, DIRECT, 0bfd66d529a55807 +beachfront.com, 5278, RESELLER, e2541279e8e2ca4d +openx.com, 539337395, RESELLER, 6a698e2ec38604c6 +openx.com, 540170114, RESELLER, 6a698e2ec38604c6 +pubmatic.com, 157568, RESELLER, 5d62403b186f2ace +advertising.com, 23218, RESELLER +adtech.com, 23218, RESELLER +beachfront.com, 10402, RESELLER, e2541279e8e2ca4d +freewheel.tv, 283074, RESELLER +freewheel.tv, 957521, RESELLER +freewheel.tv, 123433, RESELLER +districtm.io, 101633, DIRECT, 3fd707be9c4527c3 +ucfunnel.com, par-BE7E7ADB8D34EE2BF7BBD2899BB62A77, DIRECT +aralego.com, par-BE7E7ADB8D34EE2BF7BBD2899BB62A77, DIRECT +appnexus.com, 9393, DIRECT +ssp.ynxs.io, 185, DIRECT +appnexus.com, 10617, DIRECT +advertising.com, 25034, DIRECT +aps.amazon.com,e9ebbf2b-e30e-4f2f-826f-2b583b80ad97,DIRECT +pubmatic.com,157150,RESELLER,5d62403b186f2ace +openx.com,540191398,RESELLER,6a698e2ec38604c6 +rubiconproject.com,18020,RESELLER,0bfd66d529a55807 +appnexus.com,1908,RESELLER,f5ab79cb980f11d1 +smaato.com,1100044650,RESELLER,07bcf65f187117b4 +adtech.com,12068,RESELLER,e1a5b5b6e3255540 +ad-generation.jp,12474,RESELLER,7f4ea9029ac04e53 +districtm.io,100962,RESELLER,3fd707be9c4527c3 +appnexus.com,3663,RESELLER,f5ab79cb980f11d1 +rhythmone.com,1654642120,RESELLER,a670c89d4a324e47 +yahoo.com,55029,RESELLER,e1a5b5b6e3255540 +gumgum.com,14141,RESELLER,ffdef49475d318a9 +indexexchange.com,192410,RESELLER,50b1c356f2c5c8fc +pubmatic.com,160006,RESELLER,5d62403b186f2ace +pubmatic.com,160096,RESELLER,5d62403b186f2ace \ No newline at end of file diff --git a/site/articles/globals.txt b/site/articles/globals.txt new file mode 100644 index 0000000..669fa92 --- /dev/null +++ b/site/articles/globals.txt @@ -0,0 +1,336 @@ +{ + 'cat_match' => 'sub { + my $fullname = shift || return; + my $url = $DB->table(\'Category\')->as_url($fullname); + if (index($url, "Bike_Fit") != -1) { + return "true"; + } else { + return "false"; + } +}', + 'category_url' => 'sub { + my $fullname = shift || return; + my $url = $DB->table(\'Category\')->as_url($fullname); + return $url; +}', + 'comscore' => ' + + +', + 'convert_nl_br' => 'sub { + my $tags = GT::Template->tags; + foreach (keys %$tags) { + next if ($_ eq \'RelatedArticles\'); + $tags->{$_} =~ s/\r//g; + $tags->{$_} =~ s/\n/
/g; + } + return $tags; +}', + 'dans_series' => '- F.I.S.T. Workshops +
- Geometry Calculator +
- Retailers +
- Stack // Reach +
- Training Log +
- Triathlon Clubs', + 'forum_url' => 'sub { + return \'http://forumdev.slowtwitch.com\'; +}', + 'ga_link_tracker' => ' +', + 'get_detailed_url' => 'sub { + my $id = shift; + return $CFG->{build_detail_url} . \'/\' . $DB->table(\'Links\')->detailed_url($id); +}', + 'get_footer_categories' => 'sub { +# usage ($depth, $sb, $so); + my $category = $DB->table(\'Category\'); + my $depth = shift || 0; + my $sb = shift || "Name"; + my $so = shift ||"ASC"; + my $pos = shift || 1; + + $category->select_options("ORDER BY $sb $so"); + my $sth = $category->select( { CatDepth => $depth, Cat_Pos => $pos }); + my @loop; + while (my $link = $sth->fetchrow_hashref) { + $link->{URL} = "$CFG->{build_root_url}/" . $category->as_url($link->{Full_Name}) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : \'\'); + + push @loop, $link; + } + return { \'category_links_loop\' => \@loop }; +}', + 'get_header_categories' => 'sub { +# usage ($depth, $sb, $so); + my $category = $DB->table(\'Category\'); + my $depth = shift || 0; + my $sb = shift || "Name"; + my $so = shift ||"ASC"; + my $pos = shift || 0; + + $category->select_options("ORDER BY $sb $so"); + my $sth = $category->select( { CatDepth => $depth, Cat_Pos => $pos }); + my @loop; + while (my $link = $sth->fetchrow_hashref) { + $link->{URL} = "$CFG->{build_root_url}/" . $category->as_url($link->{Full_Name}) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : \'\'); + + push @loop, $link; + } + return { \'category_links_loop\' => \@loop }; +}', + 'get_links' => 'sub { +# usage ($type, $sb, $so); + my $db = $DB->table(\'Links\'); + my $type = shift || "editorial"; + my $sb = shift || "Add_Date"; + my $so = shift ||"DESC"; + my $mh = shift || 10; + + $db->select_options("ORDER BY $sb $so", "LIMIT $mh"); + my $sth = $db->select({ Type => $type }, VIEWABLE); + my @loop; + while (my $link = $sth->fetchrow_hashref) { + $link = Links::SiteHTML::tags(\'link\',$link); + push @loop, $link; + } + return { $type . \'_links_loop\' => \@loop }; +}', + 'get_links_categories' => 'sub { + my $links = shift; + my @ids = map { $_->{ID} } @$links; + my $catlink = $DB->table(\'CatLinks\',\'Category\'); + my %names = $catlink->select(\'LinkID\', \'Full_Name\', { LinkID => \@ids })->fetchall_list; + + return \%names; +}', + 'glam_widget' => ' +', + 'google_analytics' => ' +', + 'main_site_url' => 'sub { + return \'https://www.slowtwitch.com\'; +}', + 'old_related_articles' => 'sub { + my $related = shift || return; + my @ids = split ("\n",$related); + my @loop; + my $db = $DB->table(\'Links\'); + require Links::SiteHTML; + foreach my $id (@ids) { + my $link = $db->get($id); + $link = Links::SiteHTML::tags(\'link\',$link); + push @loop, $link; + } + return { related_articles_loop => \@loop }; +}', + 'poll' => '', + 'quantcast' => ' + + + +', + 'related_articles' => 'sub { + my $related = shift || return; + my @ids = split ("\n",$related); + my @loop; + my $db = $DB->table(\'Links\'); + + my $linkid = shift; + my $cond = GT::SQL::Condition->new(); + $cond->add(\'RelatedArticles\',\'like\', \'%\' . $linkid . \'%\'); + my $sth = $db->select($cond); + my $seen = {}; + while (my $link = $sth->fetchrow_hashref()) { + $link = Links::SiteHTML::tags(\'link\',$link); + my @rids = split("\n", $link->{RelatedArticles}); + my $found = 0; + for (@rids) { + my $tid = $_; + $tid =~ s/\s+//g; + $found = 1 if ($tid == $linkid); + } + push @loop, $link if ($found); + $seen->{$link->{ID}} = 1 if ($found); + } + + require Links::SiteHTML; + foreach my $id (@ids) { + next if ($seen->{$id}); + my $rlink = $db->get($id); + if ($rlink) { + $rlink = Links::SiteHTML::tags(\'link\',$rlink); + push @loop, { %$rlink }; + } + } + return { related_articles_loop => \@loop }; +} +', + 'related_photos' => 'sub { + my $related = shift || return; + my @ids = split ("\n",$related); + my @loop; + use lib \'/home/slowtwitch/slowtwitch.com/cgi-bin/photos/admin\'; + Links::init(\'/home/slowtwitch/slowtwitch.com/cgi-bin/photos/admin\'); + require Plugins::SlideShow; + my $DBH = new GT::SQL \'/home/slowtwitch/slowtwitch.com/cgi-bin/photos/admin/defs\'; + my $db = $DBH->table(\'Links\'); + require Links::SiteHTML; + foreach my $id (@ids) { + my $link = $db->get($id); + my $fh = $db->file_info("Image1_thumbnail", $link->{ID}); + my $fdir = $fh->File_Directory(); + my $full_path = "$fh"; + my $rel_path = $full_path; + $rel_path =~ s,$fdir,,; + $rel_path =~ s,%,%25,g; + + $link->{Image1_thumbnail_path} = $rel_path; + $link = Links::SiteHTML::tags(\'link\',$link); + push @loop, $link; + } + return { related_photos_loop => \@loop }; +}', + 'replace_line_break' => 'sub { + my $text = shift; + $text =~ s// /g; + return $text; +}', + 'rewrite_detail_url' => 'sub { + my $tags = GT::Template->tags; + if ($tags->{detailed_url} and !$IN->param(\'d\')) { + $tags->{detailed_url} =~ s/(\d+)\.html$/j$1.html/; + } + return $tags; +}', + 'round' => 'sub { + my $num = shift; + return sprintf("%.1f", $num - 0.05); +} +', + 'shorten_it' => 'sub { + my $str = shift; + my $length = shift || 160; + if ($length > 0 and length $str > $length) { + $str = substr($str,0,$length); + $str =~ s/\s+\w+$//g; + $str .= " ..."; + } + return $str; +}', + 'sidenav' => '', + 'sidenav_fitter' => '', + 'site_title' => '<:: Welcome to Slowtwitch.com ::>', + 'site_title_short' => 'Slowtwitch.com', + 'slowdrive' => '
+ + +
+ + + +
+
', + 'thumbnail' => 'sub { + my $link = shift; + my $image1_thumbnail_path = shift; + if ($image1_thumbnail_path) { + return $image1_thumbnail_path; + } elsif ($link->{Link_Type} ne \'video\') { + return; + } + + if ($link->{Thumbnail_URL} and $link->{Thumbnail_URL} ne \'http://\') { + return $link->{Thumbnail_URL}; + } else { + require Plugins::ConvertVideo; + + my $field = Plugins::ConvertVideo::get_file_path($link->{ID}, "thumbnail_file_field"); + if ($field->{thumbnail_file_field_path}) { + return $field->{thumbnail_file_field_path}; + } + } + + return; +}', + 'ticker_loop' => 'sub { + my @coupon_links_loop; + my $db = $DB->table(\'Ticker\'); + my $sth = $db->do(\'SELECT ticker_text, ticker_link FROM glinks_Ticker ORDER BY ticker_text ASC\'); + while (my $result = $sth->fetchrow_hashref) { + push @coupon_links_loop, { + coupon => $result->{ticker_text}, + url => $result->{ticker_link} + }; + } + + return { \'coupon_links_loop\' => \@coupon_links_loop }; +}' +}; + +# vim:syn=perl:ts=4:noet diff --git a/site/articles/language.txt b/site/articles/language.txt new file mode 100644 index 0000000..287ab91 --- /dev/null +++ b/site/articles/language.txt @@ -0,0 +1,183 @@ +{ + 'ADD_BADREFER' => 'Sorry, this site does not accept submissions from \'%s\'.', + 'ADD_BADSTATUS' => 'Your link could not be added because it is not accessible: %s.', + 'ADD_ILLEGALVAL' => '%s cannot contain the value \'%s\'', + 'ADD_INVALIDCAT' => 'Unable to find category with ID \'%s\'.', + 'ADD_NOCATEGORIES' => 'There are no categories to add a link to.', + 'ADD_NOCATEGORY' => 'You did not specify a category for this link.', + 'ADD_NOTNULL' => 'Column %s cannot be left blank.', + 'ADD_SELCAT' => 'Please first visit the category you wish to add or move your link to, then click on Add/Modify a Link.', + 'ADD_UNIQUE' => 'The column \'%s\' must be unique, and already has an entry \'%s\'.', + 'BOOKMARK_BAD_FOLDER' => 'Please enter a valid folder name.', + 'BOOKMARK_BAD_FOLDER_ID' => 'There is no folder with the id \'%s\'.', + 'BOOKMARK_COMMENTS_EDITED' => 'The comment has been updated.', + 'BOOKMARK_DISABLED' => 'Bookmarks have been disabled.', + 'BOOKMARK_FOLDER_DEFAULT' => 'You can\'t remove a default folder.', + 'BOOKMARK_FOLDER_DUPLICATE' => 'A folder with name \'%s\' already exists.', + 'BOOKMARK_FOLDER_INVALID' => 'The folder is invalid.', + 'BOOKMARK_FOLDER_LIMIT' => 'You have reached your folder limit and cannot create any more.', + 'BOOKMARK_FOLDER_MODIFIED' => 'The folder has been updated.', + 'BOOKMARK_FOLDER_NOTEMPTY' => 'You cannot delete a folder that is not empty.', + 'BOOKMARK_FOLDER_NOTEXISTS' => 'The folder does not exist.', + 'BOOKMARK_FOLDER_NOTPUBLIC' => 'The folder you tried to access is not open to the public.', + 'BOOKMARK_FOLDER_NO_MOVE' => 'You cannot move links to the folder with id \'%s\'.', + 'BOOKMARK_FOLDER_REMOVED' => 'The folder %s has been removed.', + 'BOOKMARK_LINK_ADDED' => 'The link has been bookmarked.', + 'BOOKMARK_LINK_EXISTS' => 'This link has already been bookmarked in the selected folder.', + 'BOOKMARK_LINK_LIMIT' => 'You may not add any more links as you have reached your limit.', + 'BOOKMARK_LINK_MOVED' => '%s link(s) have been moved to folder %s.', + 'BOOKMARK_LINK_NOTEXISTS' => 'The link with id \'%s\' doesn\'t exist in your bookmarks.', + 'BOOKMARK_LINK_REMOVED' => '%s link(s) have been removed from your bookmarks.', + 'BOOKMARK_NO_ACTION' => 'No action passed.', + 'BOOKMARK_PREFERENCES' => 'The bookmark preferences have been updated.', + 'BOOKMARK_PREF_INVALIDPERPAGE' => 'Links per page must be greater than 0.', + 'BOOKMARK_PUBLIC_USER' => 'You do not have permission to access %s\'s folders.', + 'BOOKMARK_USER_NOTEXISTS' => 'The user %s does not exist.', + 'BUILD_DETAILED_ARGS' => 'Invalid argument passed to build_detailed: %s', + 'BUILD_DETAILED_DISABLED' => 'Detailed pages are not enabled.', + 'BUILD_DETAILED_EXPIRED' => 'The link has not been paid for or has expired.', + 'BUILD_DETAILED_INVALIDID' => 'Invalid link id passed to build_detailed: %s', + 'BUILD_DETAILED_UNVAL' => 'The link has not yet been validated.', + 'DATE_UNIT_DAY' => 'Day', + 'DATE_UNIT_DAYS' => 'Days', + 'DATE_UNIT_MONTH' => 'Month', + 'DATE_UNIT_MONTHS' => 'Months', + 'DATE_UNIT_WEEK' => 'Week', + 'DATE_UNIT_WEEKS' => 'Weeks', + 'DATE_UNIT_YEAR' => 'Year', + 'DATE_UNIT_YEARS' => 'Years', + 'FILE_TABLE' => 'Table "%s" could not be loaded because "%s".', + 'FILE_TABLEFORMAT' => 'Table name for request improperly formed or possibly insecure.', + 'FILE_UNKNOWN' => 'Unknown File requested.', + 'GENERAL_BANNED' => 'Your host has been banned; please contact the site owner for details.', + 'GENERAL_DISABLED' => 'The site is down for maintenance, please try again shortly.', + 'GENERAL_ERROR' => 'An error has occurred.', + 'JUMP_INVALIDID' => 'Unable to find link with id: \'%s\'.', + 'LINKS_ADD' => 'Add a Link', + 'LINKS_ADD_SUCCESS' => 'Link Added', + 'LINKS_BOOKMARK' => 'Bookmarks', + 'LINKS_COOL' => 'Cool', + 'LINKS_EMAILPASS' => 'Forgotten Password', + 'LINKS_ERROR' => 'Error', + 'LINKS_LOGIN' => 'User Login', + 'LINKS_MODIFY' => 'Modify a Link', + 'LINKS_MODIFY_SUCCESS' => 'Link Modified', + 'LINKS_NEW' => 'New', + 'LINKS_NEWSLETTER' => 'Newsletter', + 'LINKS_PAGE' => 'Page %s', + 'LINKS_PAYMENT' => 'Payment', + 'LINKS_PAYMENT_SUCCESS' => 'Payment Confirmation', + 'LINKS_RATE' => 'Rate a Link', + 'LINKS_REVIEW' => 'Reviews', + 'LINKS_REVIEW_ADD' => 'Add a Review', + 'LINKS_REVIEW_EDIT' => 'Edit Review', + 'LINKS_SEARCH' => 'Search', + 'LINKS_SEARCH_RESULTS' => 'Search Results', + 'LINKS_SIGNUP' => 'User Sign Up', + 'LINKS_TOP' => 'Home', + 'LINKS_TOPRATED' => 'Top Rated Links', + 'LINKS_VALIDATE' => 'Validation', + 'MODIFY_BADSTATUS' => 'Your link could not be modified because it is not accessible: %s.', + 'MODIFY_BADURL' => 'We were unable to find the URL \'%s\' in the database. Please make sure you typed it in exactly as it appears in the directory.', + 'MODIFY_INVALIDLINKID' => 'Invalid link ID.', + 'MODIFY_NOCATEGORY' => 'You did not specify a category for this link.', + 'MODIFY_NOLINKS' => 'You do not have any links to modify.', + 'MODIFY_NOTOWNER' => 'You are not authorized to modify this link.', + 'MODIFY_NOURL' => 'You did not specify a link to modify.', + 'MODIFY_REJECTSUB' => 'Your change has been rejected.', + 'MODIFY_SELCAT' => 'Before you can modify your link, please go to the category your link is in, or the category you want to put it in and click modify.', + 'NEWSLETTERERR_ALREADYSUB' => 'You are already subscribed to the Newsletter.', + 'NEWSLETTERERR_NOACTION' => 'You did not specify what you want to do with the list.', + 'NEWSLETTERERR_NOCATSUB' => 'You didn\'t specify which category to subscribe to.', + 'NEWSLETTERERR_NOCATUNSUB' => 'You didn\'t specify which category to unsubscribe from.', + 'NEWSLETTERERR_NOTSUB' => 'You aren\'t subscribed to the Newsletter.', + 'NEWSLETTER_CATSUB' => 'You have subscribed to the selected categories.', + 'NEWSLETTER_CATUNSUB' => 'You have unsubscribed from the selected categories.', + 'NEWSLETTER_CATUPDATED' => 'Your subscriptions have been updated.', + 'NEWSLETTER_ROOTCAT' => 'Home', + 'NEWSLETTER_SUBSCRIBED' => 'You have successfully subscribed to the Newsletter.', + 'NEWSLETTER_UNSUBSCRIBED' => 'You have successfully unsubscribed from the Newsletter.', + 'PAGE_INVALIDCAT' => 'Category \'%s\' does not exist.', + 'PAGE_INVALIDDETAIL' => 'Unable to find detailed page: \'%s\'.', + 'PAYLOG_DEL_SUCCESS' => 'Payment log entry deleted.', + 'PAYLOG_INVALID_ID' => 'Invalid log ID.', + 'PAYMENTERR_DECLINED' => 'Your payment was declined.', + 'PAYMENTERR_DIRECT' => 'Your payment could not be processed. Please check the fields below and resubmit your payment.', + 'PAYMENTERR_INVALIDCATID' => 'Invalid category ID.', + 'PAYMENTERR_INVALIDLEVEL' => 'You have selected an invalid payment level.', + 'PAYMENTERR_INVALIDLINKID' => 'Invalid link ID.', + 'PAYMENTERR_INVALIDMETHOD' => 'You have selected an invalid payment method.', + 'PAYMENTERR_INVALIDTERM' => 'You have selected an invalid payment term.', + 'PAYMENTERR_NOLEVEL' => 'You must select a payment level.', + 'PAYMENTERR_NOMETHOD' => 'You must select a payment method.', + 'PAYMENTERR_NOTACCEPTED' => 'Payments are not accepted for the category the link is in.', + 'PAYMENTERR_NOTOWNER' => 'You can only make payments to your own links.', + 'PAYMENT_CURRENCY_FORMAT' => '$%s ', + 'PAYMENT_DIRECT_AuthorizeDotNet' => 'Authorize.Net', + 'PAYMENT_DIRECT_Moneris' => 'Moneris', + 'PAYMENT_REMOTE_2CheckOut' => '2CheckOut', + 'PAYMENT_REMOTE_APPROVED' => 'Approved remote payment received from %s', + 'PAYMENT_REMOTE_CANCELLED' => 'Cancelled payment notification received from %s', + 'PAYMENT_REMOTE_INVALIDIP' => 'A payment notification was received from %s with an unauthorized IP address.', + 'PAYMENT_REMOTE_INVALIDPW' => 'A payment notification was received from %s with an invalid password.', + 'PAYMENT_REMOTE_Manual' => 'Manual', + 'PAYMENT_REMOTE_PayPal' => 'PayPal', + 'PAYMENT_REMOTE_RECURRING_ACCEPTED' => 'Recurring payment notification received from %s', + 'PAYMENT_REMOTE_RECURRING_DECLINED' => 'Declined payment notification received from %s', + 'PAYMENT_REMOTE_REFUND' => 'Notification of payment refund received from %s', + 'PAYMENT_REMOTE_WorldPay' => 'WorldPay', + 'PAYMENT_TYPE_AMEX' => 'American Express', + 'PAYMENT_TYPE_DELTA' => 'Delta', + 'PAYMENT_TYPE_DINERS' => 'Diners Club', + 'PAYMENT_TYPE_DISC' => 'Discover', + 'PAYMENT_TYPE_EURO' => 'Eurocard', + 'PAYMENT_TYPE_JCB' => 'JCB', + 'PAYMENT_TYPE_MANUAL' => 'Manual', + 'PAYMENT_TYPE_MC' => 'MasterCard', + 'PAYMENT_TYPE_NOVA' => 'Nova', + 'PAYMENT_TYPE_PAYPAL' => 'PayPal', + 'PAYMENT_TYPE_SOLO' => 'Solo', + 'PAYMENT_TYPE_SWITCH' => 'Switch', + 'PAYMENT_TYPE_VISA' => 'VISA', + 'PAYMENT_TYPE_VISA_DEBIT' => 'VISA Debit', + 'RANDOM_NOLINKS' => 'No available links.', + 'RATE_INVALIDID' => 'Unable to find link with ID: \'%s\'.', + 'RATE_INVALIDRATE' => 'Please enter a number from 1 to 10.', + 'RATE_VOTED' => 'You have already voted for this link.', + 'REVIEW_ADD_WAIT' => 'You have already submitted a review for this link. Please wait for it to be validated.', + 'REVIEW_GUEST_EMAIL_REQUIRED' => 'Please enter your e-mail address to add a review!', + 'REVIEW_GUEST_NAME_REQUIRED' => 'Please fill out your name to add a review!', + 'REVIEW_INVALIDID' => 'Invalid Link ID : %s.', + 'REVIEW_INVALID_ACTION' => 'Invalid action!', + 'REVIEW_INVALID_UPDATE' => 'Unable to update review database. User is invalid for this review or the review is not validated.', + 'REVIEW_MAX_REVIEWS' => 'You can only add %s review(s) to a link.', + 'REVIEW_MODIFY_DENIED' => 'You do not have permission to modify your review.', + 'REVIEW_MODIFY_TIMEOUT' => 'The edit time for the review has expired.', + 'REVIEW_NORESULTS' => 'No reviews are available.', + 'REVIEW_NOT_EXISTS' => 'Review doesn\'t exist!', + 'REVIEW_RATING' => 'Please select a rating from 1 to 5 only.', + 'REVIEW_VOTED' => 'You have already voted for this review.', + 'SEARCH_NOLINKS' => 'No results found for your search', + 'SUBSCRIBE_ALREADYSUB' => 'You are already subscribed to this mailing list.', + 'SUBSCRIBE_ERROR' => 'No action and/or e-mail specified.', + 'SUBSCRIBE_INVALIDLIST' => 'Unable to find mailing list: \'%s\'.', + 'SUBSCRIBE_NOTSUB' => 'You are not subscribed to this mailing list.', + 'SUBSCRIBE_SUCCESS' => 'You have successfully subscribed to the mailing list.', + 'SUBSCRIBE_UNSUBSUCCESS' => 'You have successfully unsubscribed from the mailing list.', + 'USER_AUTHERROR' => 'Authentication error: %s', + 'USER_BADLOGIN' => 'Invalid username/password.', + 'USER_EMAILTAKEN' => 'The e-mail address you entered is already taken.', + 'USER_INVALIDEMAIL' => 'Invalid e-mail address: \'%s\'', + 'USER_INVALIDNAME' => 'Invalid name: \'%s\'', + 'USER_INVALIDSIGNUP' => 'Please fill out all fields completely.', + 'USER_INVALIDUSERNAME' => 'Invalid format for username: %s', + 'USER_INVALIDVAL' => 'Invalid validation code.', + 'USER_LOGOUT' => 'You have been successfully logged out.', + 'USER_NAMETAKEN' => 'The username you requested is already taken.', + 'USER_NOEMAIL' => 'No user with that e-mail address.', + 'USER_NOTVAL' => 'This account has not yet been validated.', + 'USER_PASSSENT' => 'Your password has been successfully e-mailed to you.', + 'USER_VALSENT' => 'Your validation code has been sent!' +}; + +# vim:syn=perl:ts=4:noet diff --git a/site/articles/local/globals.txt b/site/articles/local/globals.txt new file mode 100644 index 0000000..2fdf0ff --- /dev/null +++ b/site/articles/local/globals.txt @@ -0,0 +1,198 @@ +{ + 'ad_300x250' => ' + +
+ +
+', + 'ad_300x250_1' => ' + +
+ +
+', + 'ad_300x250_noroadblocks' => ' + +
+ +
+', + 'ad_300x250_roadblocks' => ' + +
+ +
+', + 'ad_300x600' => ' + +
+ +
+', + 'ad_728x90' => ' + +
+ +
+', + 'ad_728x90_roadblocks' => ' + +
+ +
+', + 'ad_970x250' => ' + +
+ +
+', + 'ad_wallpaper' => ' + + +', + 'advertserve_ajax' => ' + +', + 'calendar_url' => 'https://www.slowtwitch.com/calendar', + 'comscore' => '', + 'current_year' => 'sub { + use POSIX qw(strftime); + my $now_string = strftime "%Y", localtime; + return $now_string; +}', + 'exclusive_ad_test' => 'sub { + my $regex_match = $ID =~ /7629/; + return $regex_match; +}', + 'forum_url' => 'sub { + return \'https://forum.slowtwitch.com\'; +}', + 'get_image_context' => 'sub { + my $index = shift || return; + my $tags = GT::Template->tags; + return { description => $tags->{"Image$index" . "_description"} || \'\', paragraph => $tags->{"Paragraph$index"} || \'\' }; +}', + 'google_tag_manager' => ' + + + + +', + 'is_old_article' => 'sub { +my $date = shift; +require GT::Date; + +return GT::Date::date_is_greater($date, \'2016-08-03\') ? 0 : 1; +}', + 'old_detailed_url' => 'sub { + my $url = shift || return; + + $url =~ s,^https://,http://,; + return { http_detailed_url => $url }; +}', + 'quantcast' => '', + 'shorten_it' => 'sub { + my $str = shift || return; + my $length = shift || 160; + $str =~ s/<(?:[^>\'"]*|([\'"]).*?\1)*>//gs; + if ($length > 0 and length $str > $length) { + $str = substr($str,0,$length); + $str =~ s/\s+\w+$//g; + $str .= " ..."; + } + return $str; +}', + 'site_description' => 'Online triathlon magazine with product reviews, a bike fit guide, training tips, and several regular columnists. The editor is Dan Empfield, the founder of Quintana Roo.', + 'site_keywords' => 'triathlon, swim, bike, run, ironman, 70.3, ITU, Olympic, USAT, slowtwitch', + 'static_url' => 'sub { + return $CFG->{build_static_url}; +}' +}; + +# vim:syn=perl:ts=4:noet diff --git a/site/coaches/_notes.txt b/site/coaches/_notes.txt new file mode 100644 index 0000000..072ec82 --- /dev/null +++ b/site/coaches/_notes.txt @@ -0,0 +1,54 @@ +Advanced search options will be: + +******************* EDUCATION ****************** + +Undergrad degree [ ] Undergrad sci degree or ex sci [ ] + +Graduate degree [ ] Graduate science or ex sci degree [ ] + +***************** CERTIFICATIONS **************** + +F.I.S.T certified [ ] Serrotta certified [ ] + +USAT level 1 [ ] USAT level 2 [ ] USAT level 3 [ ] + +USA Cycling level 1 [ ] USA Cycling level 2 [ ] + +USA Swimming level 1 [ ] USA Swimming level 2 [ ] + + +**************** SERVICES OFFERED *************** + +Regular group swim workouts on pool deck [ ] + +One-on-one swim instruction on pool deck [ ] + +Local fitting [ ] + +Regular track workouts in person [ ] + +Online coaching [ ] + +***************** LOCATION **************** + +What we have before, plus: + +Outside the United states [ ] + +--<<< OTHER FIELDS FOR COACHES AND COACHES TO FILL OUT WOULD BE >>>-- + +Street address +Street address two +City +State +Zip +Phone +Fax/alt phone +Email +Website + +--<< TEXT AREA >>-- + +More Info +Rates & Fees +Camps \ No newline at end of file diff --git a/site/coaches/add.php b/site/coaches/add.php new file mode 100644 index 0000000..2cd116f --- /dev/null +++ b/site/coaches/add.php @@ -0,0 +1,568 @@ + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+ + +

Thank you

+

Thank you. Your coach information should be added within 24 hours. You will now be redirected back to the add page.

+ + + +

Add a Coach: Step 2 of 2

+ +

Add a Coach: Step 1 of 2

+ +

If you would like to add a coach to our website, simply fill out the form below. Be sure to fill out every field. After filling out each field, click submit. You will then be prompted to confirm your information before the information is sent to us.

+ +

+ + + +
+
+
+
Name
+
+
+ +
+
+
+
Street Address
+
+
+ +
+
+
+
Street Address Two (optional)
+
+
+ +
+
+
+
City
+
+
+ +
+
+
+
State
+
+
+ +
+
+
+
Zip/Postal Code
+
+
+ +
+
+
+
Phone
+
+
+ +
+
+
+
Fax / Alternate Phone
+
+
+ +
+
+
+
E-mail
+
+
+ +
+
+
+
Website
+
+
+ +
+
+
+
+
+
+

Info

+
+
+
+
Certifications
+
+
+ "); + echo(""); + while ($list = mysql_fetch_array($fetch)) { + if(($grouping != $list[coach_certification_group]) OR !($i%3)) { + if (!($i%3)) echo (""); + echo ""; + $grouping = $list[coach_certification_group]; + $i = 0; + } + echo("\n"); + $i++; + } + while ($i<3) { + echo ("\n"); + $i++; + } + echo(""); + + ?> +
 
$list[coach_certification_name] 
+
+
+
+
Services
+
+
+ "); + echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%1)) echo ""; + echo("\n"); + $i++; + } + echo(""); + + ?> +
$row[coach_service_name]
+
+
+
+
Education
+
+
+ "); + echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%2)) echo ""; + echo("\n"); + $i++; + } + echo(""); + + ?> +
$row[coach_degree_name]
+
+
+
+
General Info
+
+
+ +
+
+
+
Rates & Fees
+
+
+ +
+
+
+
Camps
+
+
+ +
+
+
+
+
+
+ + +
+
+
+ +
+ + + Please confirm your information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your information before submitting.
+
+ +
+
+
Name
+
+
+ +
+
+ = 50) { + if ($i == false) { + echo ("Duplicate Alert:"); + } + if ($i == true) {echo ("
");} + echo ("".$match_row['coach_name']." (".$match_row['coach_city'].", ".$match_row['coach_state'].") (Similarity: ".(round($percent, 0))."%)"); + $i = true; + } + } + if ($i == true) { echo(""); } + ?> +
+
Street Address
+
+
+ +
+
+
+
Street Address Two
+
+
+ +
+
+
+
City
+
+
+ +
+
+
+
State
+
+
+ +
+
+
+
Zip/Postal Code
+
+
+ +
+
+
+
Phone
+
+
+ +
+
+
+
Fax
+
+
+ +
+
+
+
E-mail
+
+
+ +
+
+
+
Website
+
+
+ +
+
+
+
+
+
+

Info

+
+
+
+
Certifications
+
+
+ +
+
+
+
Services
+
+
+ +
+
+
+
Education
+
+
+ +
+
+
+
General Info
+
+
+ +
+
+
+
Rates & Fees
+
+
+ +
+
+
+
Camps
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + +
+
+
+
+ + +
+ +
+
+ + + +
+
+ + + + + + diff --git a/site/coaches/add_X.php b/site/coaches/add_X.php new file mode 100644 index 0000000..841286b --- /dev/null +++ b/site/coaches/add_X.php @@ -0,0 +1,115 @@ +"; + $errmsg = rtrim($errmsg, ", "); +} + +$start_url = "(http(s)?\:\/\/)?"; // start url +$dots = "([\w_-]{2,}\.)+"; // one or more parts containing a '.' at the end +$last_part = "([\w_-]{2,})"; // last part doesn't contain a dot +$user = "((\/)(\~)[\w_=-]+)?((\/)[\w_=-]+)*"; // maybe subdirectories - possibly with user ~ +$end = "((\/)|(\/)[\w_-]+\.[\w]{2,})?"; // maybe a slash at the end or slash+file+extension +$qstring1 = "((\?[\w_-]+\=([^\#]+)){0,1}"; // querystring - first argument (?a=b) +$qstring2 = "(\&[\w_-]+\=([^\#]+))*)?"; // querystring - following arguments (&c=d) +$bkmrk = "(#[\w_-]+)?"; // bookmark + +$exp = "/^".$start_url.$dots.$last_part.$user.$end.$qstring1.$qstring2.$bkmrk."$/i"; +if( !preg_match($exp, $_POST[website]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
"; +} +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[name]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Please use only letters and numbers in the name
"; +} + +// begin error message check +if(!$errmsg){ + + $name = trim($_POST[name]); + $name_tag = strtolower(str_replace(" ","", $name)); + //if(strlen($name_tag) > 12){ //Shorten it + $name_tag = substr($name_tag, 0, 12); + //} // need to update a typo here in other dbs + $address = mysql_escape_string(trim($_POST[address])); + if (isset($_POST['address_two'])) { $address_two = mysql_escape_string(trim($_POST[address_two])); } else { $address_two = NULL; } + $city = mysql_escape_string(trim($_POST[city])); + $state = $_POST[state]; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = mysql_escape_string(trim($_POST[zip])); + $phone = trim($_POST[phone]); + $fax = trim($_POST[fax]); + $email = mysql_escape_string(trim($_POST[email])); + $website = mysql_escape_string(trim($_POST[website])); + $certifications = $_POST[certifications]; + $services = $_POST[services]; + $degrees = $_POST[degrees]; + $cost = mysql_escape_string(nl2br(substr(trim($_POST[cost]), 0, 4096))); + $info = mysql_escape_string(nl2br(substr(trim($_POST[info]), 0, 4096))); + $camps = mysql_escape_string(nl2br(substr(trim($_POST[camps]), 0, 4096))); + $submitted_by = $_POST[submitted_by]; + + // begin boolean check to see if we should insert the coach into the dbase + if($_POST[insert_coach] == true){ + $sql = "INSERT INTO ".$prefix."Coaches (coach_name, coach_name_tag, coach_address, coach_address_two, coach_city, coach_state, coach_state_tag, coach_zip, coach_phone, coach_fax, coach_email, coach_website, coach_certifications, coach_services, coach_degrees, coach_cost, coach_info, coach_camps, coach_submitted_by, coach_valid) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', ',$certifications,', ',$services,', ',$degrees,', '$cost', '$info', '$camps', $submitted_by, 0)"; + //echo("shop entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + //exit(); + $insert_success = true; + }else{ + //echo("shop NOT entered."); + $confirm_coach = true; + } + // end insert check +} +// end error message check +?> diff --git a/site/coaches/ajax.rate.item.php b/site/coaches/ajax.rate.item.php new file mode 100644 index 0000000..694db67 --- /dev/null +++ b/site/coaches/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/coaches/comments_add.php b/site/coaches/comments_add.php new file mode 100644 index 0000000..55d154b --- /dev/null +++ b/site/coaches/comments_add.php @@ -0,0 +1,35 @@ + + +
+ + + + +
+ +Add A Comment +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+ + +
diff --git a/site/coaches/comments_add_X.php b/site/coaches/comments_add_X.php new file mode 100644 index 0000000..a864624 --- /dev/null +++ b/site/coaches/comments_add_X.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/site/coaches/comments_show.php b/site/coaches/comments_show.php new file mode 100644 index 0000000..997f0d4 --- /dev/null +++ b/site/coaches/comments_show.php @@ -0,0 +1,19 @@ + + + + +" data-num-posts="5" data-width="500">*/ ?> +" num_posts="5" width="500">**/ ?> + diff --git a/site/coaches/comments_validate.php b/site/coaches/comments_validate.php new file mode 100644 index 0000000..abb6b81 --- /dev/null +++ b/site/coaches/comments_validate.php @@ -0,0 +1,88 @@ + + + + + + +
+ + +
+ + + + + +

Unvalidated Comments

+
+
+ + + + "> + + + +
Reviewed by: ".$commenter_user_username.""; echo " on ".date("F j, Y g:i A", $arrComments[comment_time]); echo " about ".$coach_name."";?>
+ +
Validate this comment. Delete this comment.
+
+ +
+
+ + +
+ +
+ + + \ No newline at end of file diff --git a/site/coaches/comments_validate_X.php b/site/coaches/comments_validate_X.php new file mode 100644 index 0000000..315e650 --- /dev/null +++ b/site/coaches/comments_validate_X.php @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/site/coaches/config.php b/site/coaches/config.php new file mode 100644 index 0000000..bdbc599 --- /dev/null +++ b/site/coaches/config.php @@ -0,0 +1,148 @@ += '4.0.4pl1' && strstr($_SERVER["HTTP_USER_AGENT"],'compatible')) { + if (extension_loaded('zlib')) { + ob_end_clean(); + ob_start('ob_gzhandler'); + } +} else if ($phpver > '4.0') { + if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) { + if (extension_loaded('zlib')) { + $do_gzip_compress = TRUE; + ob_start(array('ob_gzhandler',5)); + ob_implicit_flush(0); + header('Content-Encoding: gzip'); + } + } +} +$phpver = explode(".", $phpver); +$phpver = "$phpver[0]$phpver[1]"; +if ($phpver >= 41) { + $PHP_SELF = $_SERVER['PHP_SELF']; +} + +if (!ini_get("register_globals")) { + #import_request_variables('GPC'); +} + +function curPageURL() { + $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); + $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); + $port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : ''; + $url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.$_SERVER["REQUEST_URI"]; + return $url; +} + +$statecount = mysql_num_rows(mysql_query("SELECT * FROM gforum_Coaches WHERE coach_valid = 1")); + +//Array of states for use in the form +$state_list = array('AL'=>"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming", + // New Foreign "States", + 'OA'=>"Outside N. America"); + +?> diff --git a/site/coaches/delete_X.php b/site/coaches/delete_X.php new file mode 100644 index 0000000..c336b3a --- /dev/null +++ b/site/coaches/delete_X.php @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/site/coaches/include_breadcrumb.php b/site/coaches/include_breadcrumb.php new file mode 100644 index 0000000..5f435cc --- /dev/null +++ b/site/coaches/include_breadcrumb.php @@ -0,0 +1,12 @@ + diff --git a/site/coaches/include_buttons.php b/site/coaches/include_buttons.php new file mode 100644 index 0000000..fead2a8 --- /dev/null +++ b/site/coaches/include_buttons.php @@ -0,0 +1,107 @@ + + +
+
+ +
+
" style="display: inline;"> + + + + + + +
+ +
" style="display: inline;"> + +
+ +
" style="display: inline;"> + +
+ + +
+ + +
+ +
Entered By: $username"); + } +} +?> +
diff --git a/site/coaches/include_common_content.php b/site/coaches/include_common_content.php new file mode 100644 index 0000000..a23eeaf --- /dev/null +++ b/site/coaches/include_common_content.php @@ -0,0 +1,40 @@ + + +> + +
Skip to Content
+
+
+ + + + +
+
+
+ + + +
+
+
+
+
diff --git a/site/coaches/include_common_footer.php b/site/coaches/include_common_footer.php new file mode 100644 index 0000000..091f170 --- /dev/null +++ b/site/coaches/include_common_footer.php @@ -0,0 +1 @@ + diff --git a/site/coaches/include_common_head.php b/site/coaches/include_common_head.php new file mode 100644 index 0000000..4a1425d --- /dev/null +++ b/site/coaches/include_common_head.php @@ -0,0 +1,19 @@ + + + + + +Slowtwitch.com Coach Database: <? echo $pagetitle; ?> + + + + + diff --git a/site/coaches/include_navigation.php b/site/coaches/include_navigation.php new file mode 100644 index 0000000..e295847 --- /dev/null +++ b/site/coaches/include_navigation.php @@ -0,0 +1,71 @@ + + +
+

Browse Coaches

+
+Outside N. America
"); } + $region_dropdown .= "$state_string"; + echo ("
" . $currentregion . " (" . $regioncount . ")+
"); + echo $tempstring; + echo ('
'); + } + $currentregion = $rowregionlist[regionlong]; + $currentrid = $rowregionlist[regionid]; + $currenttag = $rowregionlist[regionname]; + $regioncount = 0; + $tempstring = ''; + $state_string = ''; + } + if ($selected_item == $rowregionlist[statetag]) { + $selected_state = ' selected="selected"'; + } + $state_string .= ""; + $tempstring = $tempstring. "$rowregionlist[statelong] ($rowregionlist[numclubs])\n"; + $regioncount += $rowregionlist[numclubs]; +} + +echo ("
".$currentregion." (".$regioncount.")+
"); +echo $tempstring; +echo ('
'); +if ( $selected_item == 'top') { $selected_region = ' selected="selected"'; } +$region_dropdown .= ""; + +?> + +
+
diff --git a/site/coaches/include_sidebar.php b/site/coaches/include_sidebar.php new file mode 100644 index 0000000..5a4f90b --- /dev/null +++ b/site/coaches/include_sidebar.php @@ -0,0 +1,14 @@ + + +
+ + + +
+ + diff --git a/site/coaches/include_status.php b/site/coaches/include_status.php new file mode 100644 index 0000000..e3150fd --- /dev/null +++ b/site/coaches/include_status.php @@ -0,0 +1,12 @@ + +
Admin:"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table." WHERE ".$field_lead."valid = 0")); + echo("
Validate Entries (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Edits")); + echo("
Validate Edits (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Comment WHERE comment_valid = 0")); + echo("
Validate Comments (".$unvalid_count.")"); +} +?> diff --git a/site/coaches/include_store.php b/site/coaches/include_store.php new file mode 100644 index 0000000..3daff8f --- /dev/null +++ b/site/coaches/include_store.php @@ -0,0 +1,27 @@ +
+
+

">

"; } else { echo "";} + } + ?> +
+ +

(Avg. rating based on )

+ +
+ $row[coach_address_two]"); } + echo("
$row[coach_city], $row[coach_state] $row[coach_zip]"); + ?> +
Phone: +
Fax: +
+
+ Email: $row[coach_email]"; ?>
+ Website: $row[coach_website]"; ?>
+ "); } ?> + ">More info > +
+
diff --git a/site/coaches/index.php b/site/coaches/index.php new file mode 100644 index 0000000..b0b1433 --- /dev/null +++ b/site/coaches/index.php @@ -0,0 +1,120 @@ + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Triathlon Coaches

+ + Add Coach + +
+ + +
+
+
+ + +

Welcome to Slowtwitch.com's North American Triathlon Coach Database

+

coaches and counting. This collection of coaches is the most complete and comprehensive + selection of triathlon coaches in North America.

+ +

Searching the database

+

+ Our Advanced Search is very potent, and will help you drill down to that set + of coaches conforming to a specific purpose you have in mind. +

+

Browsing the database

+

+ You do not need to log in to do this. You'll find a list of coaches in + your region by clicking the regional links on the left. Click the (+) sign + and the region will expand to expose the individual states. Click on the + state to show that list of coaches in it. If you want to see coaches in + multiple states, but not those states we've aggregated into the regions you + see at left, you may do this via our Advanced Search. +

+ +

Showing solidarity with your coach

+

+ When you see your personal coach listed here, you may click the "I AM COACHED" button. Your User Name will be added to the coaches's list of clients, + just like your User Name appends to those races you choose when you build + your Slowtwitch Personal Race Calendar. Likewise, your Forum User Profile + will show that this is your coach of choice. +

+ +

How to enter a coach

+

+ You must be a registered user to add a coach to the database. There is + one common type of registration on Slowtwitch, and if you are registered to + post on our Reader Forum you are one of + + who have made a registration, + and this means you're able to add coaches to our database. +

+ If you're not registered, the login prompt is to the left of the page, near + the top. The registration process is straightforward, easy, and free. It + will require you to receive an email and click on a link to complete your + registration. All this should take you only a minute or two. Then... +

+ 1. Click the ADD A COACH button to begin adding to the database. +

+ 2. Once you SUBMIT your coach, you'll also need to CONFIRM your submission + via a link at the bottom of the page. +

+ 3. Once you successfully add your coach, it will not immediately be visible + to you. We must validate the addition on our end before anyone can see it. + We do this so that spammers won't use the coach registration as a way to spam + our database. +

+

How to edit published information about a coach

+

Any registered user may edit information for a listing. We will review the full contents of each update before confirming any changes that are made. A list of all editors who have made changes is visible at the bottom of each listing. If an entry has been updated, but those changes have not yet been confirmed, this is evident via a note on the individual page for that particular entry. This is to prevent conflicting updates from occuring simultaneously. If you wish to update an entry with pending changes, please wait until we have had a chance to review those changes first. Someone may have already changed the information you were going to change yourself.

+

How to comment on a coach

+

Any registered user may make a comment on a coach listing. These comments are subject to validation by an administrator before being published.

+

Global coach map

+

The map below shows the location of all registered Slowtwitch coaches around the globe. You can drag the map, zoom-in, zoom-out, and use any other of the standard Google Maps features. Anywhere you see a red icon, you can click to see the name of that coach and a street address.

+ +
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/coaches/individual.php b/site/coaches/individual.php new file mode 100644 index 0000000..aea4874 --- /dev/null +++ b/site/coaches/individual.php @@ -0,0 +1,245 @@ + + + + + + +
+ +
+
+ + +
+ + +
+
+
+

Triathlon Coaches

+ +
+ +
+ + Back +
+ + +

Commenter: your comments have been submitted and will be validated within 24 hours.

+ + + +

Editor: your changes have been submitted and will be validated within 24 hours.

+ + +

Group Edits: there are group edits waiting to be validated.

+ + +
+
+

+

Slowtwitch Certified Coach"; } else { echo "";} + } + ?> +
+
+ Comment +
+
+
+
+ "); } ?> + ,
+ Phone:
+ Fax: +
+
+ Email:
+ Website: +
+
+
+
+ +
+
+

Info

+
+ Education: +
+ Certifications: +
+ Services: + +
+
+
+

General Info

+
+ General Info:
+ Rates & Fees:
+ Training Camps Offered: +
+
+
+
+
+ +
+ + Map location is based off of a geocode of the addressed entered using Google's Google Maps API. If your address does not geocode properly, you can either update the address (we will attempt to re-geocode after any updates to your entry) or you can use Google's geocoding tool found here: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html to obtain a lat/long for your location and enter that. To use the utility, type in an address that is close to your location and then drag-and-drop the marker to obtain the desired lat/long. If you choose to enter a lat/long, you must check the box on the edit page that says, "override geocode with entered lat/long." + +
+
+
+

Who's coached?

+
+ + + 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i > 1){ echo ", "; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username]"; + // TODO: SLOWTWITCH EDIT END + } + $i++; + } + ?> +
+
+
+
+ "; + ?> +

+
+ = 0) { + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if ($i >= 1) { echo "
"; } + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + } + $i++; + } + if($numcount <= 0) { echo "No users"; } + ?> +
+
+
+
+ + +
+
+
+ + +
+
+ + +
+ + + diff --git a/site/coaches/logout.php b/site/coaches/logout.php new file mode 100644 index 0000000..6cf5ddd --- /dev/null +++ b/site/coaches/logout.php @@ -0,0 +1,7 @@ + diff --git a/site/coaches/mysql.class.php b/site/coaches/mysql.class.php new file mode 100644 index 0000000..6d82189 --- /dev/null +++ b/site/coaches/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/coaches/rating/classes/database.class.php b/site/coaches/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/coaches/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/coaches/rating/classes/error.class.php b/site/coaches/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/coaches/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
\r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
\r\n" . + "
" . self::$description[$i] . "

\r\n"; + } + } + + // Write Error Template Output + $output = "
\r\n" . + "
{$error}:
\r\n" . + "
\r\n" . $output . "\r\n
\r\n" . + "
\r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
\r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
\r\n" . + "
" . self::$description[$i] . "

\r\n"; + } + } + + // Write Warning Template Output + $output = "
\r\n" . + "
{$warning}:
\r\n" . + "
\r\n" . $output . "\r\n
\r\n" . + "
\r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/coaches/rating/classes/include.all.php b/site/coaches/rating/classes/include.all.php new file mode 100644 index 0000000..2c1fa21 --- /dev/null +++ b/site/coaches/rating/classes/include.all.php @@ -0,0 +1,7 @@ + diff --git a/site/coaches/rating/classes/rating.class.php b/site/coaches/rating/classes/rating.class.php new file mode 100644 index 0000000..d15c167 --- /dev/null +++ b/site/coaches/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +
{$cat_info['rating_cat_name']}
\r\n"; + $output .= "
{$cat_info['rating_cat_min']}
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
{$cat_info['rating_cat_max']}
\r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
{$cat_info['rating_cat_name']}
\r\n"; + $output .= "
{$cat_info['rating_cat_min']}
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
{$cat_info['rating_cat_max']}
\r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
Overall Rating
"; + $output .= "
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
\r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_CoachesRating` (`coach_id_fk`, `category_id_fk`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_CoachesRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_CoachesRating` WHERE `category_id_fk`='{$varItem}' AND `coach_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_CoachesRating` WHERE `coach_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_CoachesRating` WHERE `category_id_fk`='{$varItem}' AND `coach_id_fk`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> diff --git a/site/coaches/rating/int.to.words.php b/site/coaches/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/coaches/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/coaches/rating/rating-example.php b/site/coaches/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/coaches/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

Race Rating System:

+ + + + + + + \ No newline at end of file diff --git a/site/coaches/regionlist.php b/site/coaches/regionlist.php new file mode 100644 index 0000000..50a4e84 --- /dev/null +++ b/site/coaches/regionlist.php @@ -0,0 +1,85 @@ + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+

Triathlon Coaches

+ Back + + " class="btn btn-white float-right">Add Coach + +
+ + +

Region

+
+ No triathlon coaches have been entered yet for $regionname.

"; + } + ?> + + + +
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/coaches/search.php b/site/coaches/search.php new file mode 100644 index 0000000..fc601fb --- /dev/null +++ b/site/coaches/search.php @@ -0,0 +1,229 @@ + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Search For A Coach

+

If you would like to search for a coach, please use the form below. None of the fields are mandatory. Checking no box in a field indicates you don't care if a coach has or does not have certifications, a fit bike, or motion capture system. Checking regions selects all states in that region. Checking any state's box selects or deselects that state.

+ +
+

+
+
+
Name Search
+
+
+ +
+
+
+
+
+
+

Info

+
+
+
+
Certifications
+
+
+ + "); + while ($row = mysql_fetch_array($results)) { + if(($grouping != $row[coach_certification_group]) OR !($i%3)) { + if (!($i%3)) echo (""); + echo ""; + $grouping = $row[coach_certification_group]; + $i = 0; + } + echo("\n"); + $i++; + } + while($i<3) { + echo(""); + $i++; + } + if(!($i%3)) echo ""; + echo("\n"); + $i++; + while($i<3) { + echo(""); + $i++; + } + if(!($i%3)) echo ""; + echo(""); + ?> +
 
$row[coach_certification_name] 
ANY 
+
+
+
+
Services Offered
+
+
+ "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%1)) echo ""; + echo("\n"); + $i++; + } + if(!($i%1)) echo ""; + echo("\n"); + echo(""); + + ?> +
$row[coach_service_name]
ANY
+
+
+
+
Education
+
+
+ "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%2)) echo ""; + echo("\n"); + $i++; + } + if(!($i%2)) echo ""; + echo("\n"); + echo(""); + + ?> +
$row[coach_degree_name]
ANY 
+
+
+
+
+
+
+

Location

+
+
+
+
Region
+
+
+ + "; + foreach($regions AS $region => $statetag) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + + } + + ?> + +
$region
+

*Selecting a region will select all states in that region. You can then deselect or select any additional states. Only the selected states will be included in your search. Leaving all boxes blank will select races in all states.

+
+
+
+
State
+
+
+ + "; + while($row = mysql_fetch_array($state_list)){ + if(!($i%4)) echo ""; + echo "\n"; + $i++; + } + ?> + +
$row[statelong]
+

*Leave blank to select all.

+
+
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/coaches/search_X.php b/site/coaches/search_X.php new file mode 100644 index 0000000..41e51b6 --- /dev/null +++ b/site/coaches/search_X.php @@ -0,0 +1,200 @@ + ',0,'"; + } else { + foreach ($_POST[certifications] AS $value) { + $sql = $sql." AND coach_certifications LIKE '%,$value,%'"; + } + } +} + +if (isset($_POST[services])) { + if (in_array("999", $_POST[services])) { + $sql = $sql." AND coach_services <> ',0,'"; + } else { + foreach ($_POST[services] AS $value) { + $sql = $sql." AND coach_services LIKE '%,$value,%'"; + } + } +} + +if (isset($_POST[degree])) { + if (in_array("999", $_POST[degree])) { + $sql = $sql." AND coach_degrees <> ',0,'"; + } else { + foreach ($_POST[degree] AS $value) { + $sql = $sql." AND coach_degrees LIKE '%,$value,%'"; + } + } +} + +// regions are checkboxes that then check off all states within that region +// add states +if (isset($_POST[states])) { + $glue = "','"; + $statelist = "('".implode($glue, $_POST[states])."')"; + $sql = $sql." AND coach_state_tag IN $statelist"; +} + + +$sql = $sql." ORDER BY coach_name ASC"; + +//echo $sql; + +$results = mysql_query($sql) OR die(mysql_error()); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} +$coach_count = mysql_num_rows($results); + +//keyword search +// trim redundant keywords: triathlon, duathlon +$trim_words = array(" the ", " a ", " an ", "and ", " half ", "triathlon", "duathlon"); +foreach ($trim_words AS $word) { + $_POST['keyword'] = str_ireplace($word, " ", $_POST['keyword']); +} +$bool_Keywords = false; +if (isset($_POST['keyword']) && $_POST['keyword'] != "") { + $bool_Keywords = true; + while($row_coaches = mysql_fetch_array($results)) { + // build an array that we can loop through. + $arr_coaches[$i] = $row_coaches; + $i++; + } + + $arr_Matches = array(); + foreach ($arr_coaches AS $coach) { + if (stripos($coach['coach_name'], $_POST['keyword']) !== false) { + // push this onto the array of matches + $coach['percent'] = 100; + array_push($arr_Matches, $coach); + } else { + $name_nospace = str_replace(" ", "", $coach['coach_name']); + $keyword_nospace = str_replace(" ", "", $_POST['keyword']); + if (stripos($name_nospace, $keyword_nospace) !== false) { + // push this onto the array of matches + $coach['percent'] = 90; + array_push($arr_Matches, $coach); + } else { + // trim redundant keywords + $coach_name = $coach['coach_name']; + foreach ($trim_words AS $word) { + $coach_name = str_ireplace($word, " ", $coach_name); + } + //$coach_name = str_ireplace(" ", "", $coach_name); + $coach_name = strtolower($coach_name); + $arr_coach_name = explode(" ", $coach_name); + $_POST['keyword'] = strtolower($_POST['keyword']); + $_POST['keyword'] = str_replace(" ", "", $_POST['keyword']); + foreach ($arr_coach_name AS $test_word) { + similar_text($test_word, $_POST['keyword'], $percent); + if ($percent >= 70) { + // push this onto the array of matches + $coach['percent'] = round($percent, 0); + //$coach['trimmed'] = $coach_name; + array_push($arr_Matches, $coach); + break; + } + } + } + } + } + + if (count($arr_Matches) == 0) { + $none = TRUE; + } + $coach_count = count($arr_Matches); + + //sort the array by keyword match success instead of by date + function cmp($a, $b) + { + if ($a['percent'] == $b['percent']) { + return 0; + } + return ($a['percent'] > $b['percent']) ? -1 : 1; + } + + usort($arr_Matches, "cmp"); +} +//end keyword search + +// set the page title +$pagetitle = "Search Results"; + +// set meta tags +$meta_keywords = "search, coaches, triathlon, results"; +$meta_description = "Triathlon coaches matching a user's search query. A list of matching coaches."; +?> + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Search Results

+

Coaches Match Your Search

+ + + + +
+ +
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/coaches/st_certified.php b/site/coaches/st_certified.php new file mode 100644 index 0000000..df532ba --- /dev/null +++ b/site/coaches/st_certified.php @@ -0,0 +1,70 @@ + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Slowtwitch Certified Coaches

+
+ + +

+ + +

+ +
+
+
+ +
+
+ + +
+ + + + + diff --git a/site/coaches/statelist.php b/site/coaches/statelist.php new file mode 100644 index 0000000..6e91965 --- /dev/null +++ b/site/coaches/statelist.php @@ -0,0 +1,131 @@ + + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+

Triathlon Coaches

+ Back + + " class="btn btn-white float-right">Add Coach + +
+ + +

State

+
+ + + + +
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/coaches/top.php b/site/coaches/top.php new file mode 100644 index 0000000..b87517a --- /dev/null +++ b/site/coaches/top.php @@ -0,0 +1,70 @@ + 10 ORDER BY score DESC, votes DESC LIMIT 10") OR die(mysql_error()); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} + +// set the page title +$pagetitle = "Top Triathlon Coaches"; + +// set meta tags +$meta_keywords = "top ranked triathlon coaches"; +$meta_description = "Top ranked triathlon coaches based on rankings submitted by the user."; +?> + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Top Ranked Triathlon Coaches

+
+ + +

+ + +

+ +
+
+
+ +
+
+ + +
+ + + + + diff --git a/site/coaches/validate.php b/site/coaches/validate.php new file mode 100644 index 0000000..b821abc --- /dev/null +++ b/site/coaches/validate.php @@ -0,0 +1,88 @@ + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Unvalidated Coaches

+
+ +
+ + +
Address: $row[coach_address_two]"); } echo("
$row[coach_city], $row[coach_state] $row[coach_zip]"); ?>
+
+
+ $row[coach_phone]
Fax/Alt Phone: $row[coach_fax]"; + ?> +
+
+
+
+ Website: $row[coach_website]"; ?> +
+ ">More information +
Validate this coach. Delete this coach. +
+
+ +
+ +
+ +
+ +
+
+
+ + +
+
+ + +
+ + + diff --git a/site/coaches/validate_X.php b/site/coaches/validate_X.php new file mode 100644 index 0000000..7d68f3b --- /dev/null +++ b/site/coaches/validate_X.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/site/coaches/wiki_buttons.php b/site/coaches/wiki_buttons.php new file mode 100644 index 0000000..35b8900 --- /dev/null +++ b/site/coaches/wiki_buttons.php @@ -0,0 +1,21 @@ + + +
+ +
+ + +
+ +
+ + +
+ +
diff --git a/site/coaches/wiki_edit.php b/site/coaches/wiki_edit.php new file mode 100644 index 0000000..4856027 --- /dev/null +++ b/site/coaches/wiki_edit.php @@ -0,0 +1,587 @@ + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+ + +

Edit a Coach: Step 2 of 2

+ +

Edit a Coach: Step 1 of 2

+ +

To edit a coach, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes as a NEW coach (for instance, if you have multiple chapters), hit the "SAVE AS A NEW COACH" button. To save changes to the existing coach entry, hit the "SAVE CHANGES TO YOUR COACH" button. You will have a chance to review the data before confirming. You will then be prompted to confirm your information before the information is sent to us.

+ +

+ + +
+
+
+
Name
+
+
+ +
+
+
+
Street Address
+
+
+ +
+
+
+
Street Address Two (Optional)
+
+
+ +
+
+
+
City
+
+
+ +
+
+
+
State
+
+
+ +
+
+
+
Zip/Postal Code
+
+
+ +
+
+
+
Phone
+
+
+ +
+
+
+
Fax/Alternate Phone
+
+
+ +
+
+
+
E-mail
+
+
+ +
+
+
+
Website
+
+
+ +
+
+
+
+
+
+

Info

+
+
+
+
Certifiations
+
+
+ "); + echo(""); + while ($list = mysql_fetch_array($fetch)) { + if(($grouping != $list[coach_certification_group]) OR !($i%3)) { + if (!($i%3)) echo (""); + echo ""; + $grouping = $list[coach_certification_group]; + $i = 0; + } + echo("\n"); + $i++; + } + while ($i<3) { + echo ("\n"); + $i++; + } + echo(""); + + ?> +
 
$list[coach_certification_name] 
+
+
+
+
Service
+
+
+ "); + echo(""); + while ($list = mysql_fetch_array($fetch)) { + if(!($i%1)) echo ""; + echo("\n"); + $i++; + } + echo(""); + + ?> +
$list[coach_service_name]
+
+
+
+
Education
+
+
+ "); + echo(""); + while ($list = mysql_fetch_array($fetch)) { + if(!($i%2)) echo ""; + echo("\n"); + $i++; + } + echo(""); + + ?> +
$list[coach_degree_name]
+ +
+
+
+
General Info
+
+
+ +
+
+
+
Rates & Fees
+
+
+ +
+
+
+
Camps
+
+
+ +
+
+
+
+
+
+ + + + + + + + + +
+
+
+
+ + +
+ Please confirm your information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your information before submitting.
+
+ +
+
+
Name
+
+
+ +
+
+
+
Street Address
+
+
+ +
+
+
+
Street Address Two
+
+
+ +
+
+
+
City
+
+
+ +
+
+
+
State
+
+
+ +
+
+
+
Zip/Postal Code
+
+
+ +
+
+
+
Phone
+
+
+ +
+
+
+
Fax/Alternate Phone
+
+
+ +
+
+
+
E-mail
+
+
+ +
+
+
+
Website
+
+
+ +
+
+
+
+
+
+

Info

+
+
+
+
Certifications
+
+
+ +
+
+
+
Services
+
+
+ +
+
+
+
Education
+
+
+ +
+
+
+
General Info
+
+
+ +
+
+
+
Rates & Fees
+
+
+ +
+
+
+
Camps
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + This data will be saved as a NEW COACH. + + + + This data will be saved as a modification to the EXISTING COACH. + + + + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+ + +
+ + + diff --git a/site/coaches/wiki_edit_X.php b/site/coaches/wiki_edit_X.php new file mode 100644 index 0000000..34e0a75 --- /dev/null +++ b/site/coaches/wiki_edit_X.php @@ -0,0 +1,124 @@ +"; + $errmsg = rtrim($errmsg, ", "); +} + +$start_url = "(http(s)?\:\/\/)?"; // start url +$dots = "([\w_-]{2,}\.)+"; // one or more parts containing a '.' at the end +$last_part = "([\w_-]{2,})"; // last part doesn't contain a dot +$user = "((\/)(\~)[\w_=-]+)?((\/)[\w_=-]+)*"; // maybe subdirectories - possibly with user ~ +$end = "((\/)|(\/)[\w_-]+\.[\w]{2,})?"; // maybe a slash at the end or slash+file+extension +$qstring1 = "((\?[\w_-]+\=([^\#]+)){0,1}"; // querystring - first argument (?a=b) +$qstring2 = "(\&[\w_-]+\=([^\#]+))*)?"; // querystring - following arguments (&c=d) +$bkmrk = "(#[\w_-]+)?"; // bookmark + +$exp = "/^".$start_url.$dots.$last_part.$user.$end.$qstring1.$qstring2.$bkmrk."$/i"; +if( !preg_match($exp, $_POST[coach_website]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
"; +} +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[coach_name]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Please use only letters and numbers in the name
"; +} + +if(!$errmsg){ + + $name = trim($_POST[coach_name]); + $name_tag = strtolower(str_replace(" ","", $name)); + if(strlen($nametag) > 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = mysql_escape_string(trim($_POST[coach_address])); + if (isset($_POST['coach_address_two'])) { $address_two = mysql_escape_string(trim($_POST[coach_address_two])); } else { $address_two = NULL; } + $city = mysql_escape_string(trim($_POST[coach_city])); + $state = $_POST[coach_state]; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = mysql_escape_string(trim($_POST[coach_zip])); + $phone = trim($_POST[coach_phone]); + $fax = trim($_POST[coach_fax]); + $email = mysql_escape_string(trim($_POST[coach_email])); + $website = mysql_escape_string(trim($_POST[coach_website])); + $certifications = $_POST[coach_certifications]; + $services = $_POST[coach_services]; + $degrees = $_POST[coach_degrees]; + $cost = mysql_escape_string(nl2br(substr(trim($_POST[coach_cost]), 0, 4096))); + $info = mysql_escape_string(nl2br(substr(trim($_POST[coach_info]), 0, 4096))); + $camps = mysql_escape_string(nl2br(substr(trim($_POST[coach_camps]), 0, 4096))); + $submitted_by = $_POST[coach_submitted_by]; + $id = $_POST[coach_id]; + $edited_by = $_POST[edited_by]; + $edit_timestamp = time(); + + // BEGIN CONFIRM ENTRY CHECK + if($_POST[insert_coach] == true){ + if(isset($_POST[new_coach])){ + $sql = "INSERT INTO ".$prefix."Coaches (coach_name, coach_name_tag, coach_address, coach_address_two, coach_city, coach_state, coach_state_tag, coach_zip, coach_phone, coach_fax, coach_email, coach_website, coach_certifications, coach_services, coach_degrees, coach_cost, coach_info, coach_camps, coach_submitted_by, coach_valid) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', ',$certifications,', ',$services,', ',$degrees,', '$cost', '$info', '$camps', $submitted_by, 0)"; + //echo("coach entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/add.php?confirmed=yes'); + } elseif(isset($_POST[save_changes])) { + $sql = "INSERT INTO ".$prefix."CoachesEdits (coach_id_fk, editor_user_id_fk, edit_timestamp, coach_name, coach_name_tag, coach_address, coach_address_two, coach_city, coach_state, coach_state_tag, coach_zip, coach_phone, coach_fax, coach_email, coach_website, coach_certifications, coach_services, coach_degrees, coach_cost, coach_info, coach_camps, coach_submitted_by, coach_valid) VALUES ('$id', '$edited_by', '$edit_timestamp', '$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', ',$certifications,', ',$services,', ',$degrees,', '$cost', '$info', '$camps', $submitted_by, 0)"; + //echo $sql; + //exit; + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/individual.php?coach_id='.$id.'&wiki_change=success'); + } else { + header('Location: '.$site_url.'/individual.php?coach_id='.$id.'&changes=failure'); + } + } else { + //echo("coach NOT entered."); + $confirm_coach = true; + } + // END CONFIRM ENTRY CHECK +} +// END ERROR MESSAGE CHECK +?> diff --git a/site/coaches/wiki_validate.php b/site/coaches/wiki_validate.php new file mode 100644 index 0000000..5c0e3c5 --- /dev/null +++ b/site/coaches/wiki_validate.php @@ -0,0 +1,92 @@ + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Unvalidated Public Edits

+
+ +
+ + +
Edited on: by ".$editor_user_username.""; if ($boolEditorIsOwner) { echo " (original coach submitter)"; } else { echo ""; } ?>
+
Info: + 400){ + $phrase = "…"; }else{ + $phrase = ""; } + + echo substr(htmlspecialchars(strip_tags(stripslashes($row[coach_info]))), 0, 160); + echo $phrase; + ?> +
+
+ Location:
+ ">More information +
Validate this edit. Delete this edit.
+
+ +
+ +
+ +
+ +
+
+
+ + +
+
+ + +
+ + + diff --git a/site/coaches/wiki_validate_X.php b/site/coaches/wiki_validate_X.php new file mode 100644 index 0000000..c3371e9 --- /dev/null +++ b/site/coaches/wiki_validate_X.php @@ -0,0 +1,97 @@ + \ No newline at end of file diff --git a/site/coaches/wiki_view.php b/site/coaches/wiki_view.php new file mode 100644 index 0000000..5e52661 --- /dev/null +++ b/site/coaches/wiki_view.php @@ -0,0 +1,198 @@ + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+ +

+ + +
+ + +Editor: ".$strEditor.""; ?> +
+ +Edit Date: +
+ +Street Address: +
+Street Address Two: +
+City: +
+State: +
+Zip/Postal Code: +
+Phone: +
+Fax/Alt Phone: +
+E-mail: +
+Website: + +
+
+ +
+ +
+ +
+Education: + +
+Certifications: + +
+Services: + +

+
+ +
+ +
+General Info: +

+Rates & Fees: +

+Training Camps Offered: + +
+ +
+ +
+
+
+
+ + +
+
+ + +
+ + + diff --git a/site/common/templates/include_footer.php b/site/common/templates/include_footer.php new file mode 100644 index 0000000..251c58e --- /dev/null +++ b/site/common/templates/include_footer.php @@ -0,0 +1,69 @@ + diff --git a/site/common/templates/include_global_head.php b/site/common/templates/include_global_head.php new file mode 100644 index 0000000..eba891f --- /dev/null +++ b/site/common/templates/include_global_head.php @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/site/common/templates/include_global_js.php b/site/common/templates/include_global_js.php new file mode 100644 index 0000000..2321894 --- /dev/null +++ b/site/common/templates/include_global_js.php @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/site/common/templates/include_header.php b/site/common/templates/include_header.php new file mode 100644 index 0000000..266862f --- /dev/null +++ b/site/common/templates/include_header.php @@ -0,0 +1,233 @@ + + + + + + +
+
+
+ Swim + Bike + Run +
+
+ + + +
+ + + +
+ +
+ +
+
+ +
+
+ +
+ + +
diff --git a/site/common/templates/include_local_listing.php b/site/common/templates/include_local_listing.php new file mode 100644 index 0000000..fa34536 --- /dev/null +++ b/site/common/templates/include_local_listing.php @@ -0,0 +1,12 @@ +
+ +
diff --git a/site/common/templates/local/include_footer.php b/site/common/templates/local/include_footer.php new file mode 100644 index 0000000..afe261d --- /dev/null +++ b/site/common/templates/local/include_footer.php @@ -0,0 +1,56 @@ + \ No newline at end of file diff --git a/site/common/templates/local/include_global_head.php b/site/common/templates/local/include_global_head.php new file mode 100644 index 0000000..05a88ff --- /dev/null +++ b/site/common/templates/local/include_global_head.php @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/site/common/templates/local/include_header.php b/site/common/templates/local/include_header.php new file mode 100644 index 0000000..aa1f39a --- /dev/null +++ b/site/common/templates/local/include_header.php @@ -0,0 +1,230 @@ + + + + +
+
+
+ Swim + Bike + Run +
+
+ + + +
+ + + +
+ +
+ +
+
+ +
+
+ +
+ + +
diff --git a/site/fitters/add.php b/site/fitters/add.php new file mode 100644 index 0000000..bf6ad61 --- /dev/null +++ b/site/fitters/add.php @@ -0,0 +1,337 @@ + + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+
+ +

Thank you

+

Thank you. Your fitter information should be added within 24 hours. You will now be redirected back to the add page.

+ + + +

Add a Fitter: Step 2 of 2

+ +

Add a Fitter: Step 1 of 2

+
+ + +

If you would like to add a fitter to our website, simply fill out the form below. Be sure to fill out every field. After filling out each field, click submit. You will then be prompted to confirm your information before the information is sent to us.

+ +

+ + +
+
+
+
Fitter Name
+
+
+ +
+
+
+
Address
+
+
+ +
+
+
+
Address 2
+
+
+ +
+
+
+
City
+
+
+ +
+
+
+
State
+
+
+ +
+
+
+
Zip/Postal Code
+
+
+ +
+
+
+
Override Address With Lat/Lng
+
+
+ > Check this if you know your physical address doesn't geocode properly using Google's API.
Then enter the desired lat/lng in the boxes below. +
+
+
+
Latitude
+
+
+ +
+
+
+
Longitude
+
+
+ +
+
+
+
Phone
+
+
+ +
+
+
+
Fax
+
+
+ +
+
+
+
E-mail
+
+
+ +
+
+
+
Website
+
+
+ +
+
+
+
Portfolio
+
+
+ +
+
+
+
+
+
+ +
+
+
+
Default Tri-Fit Methodology
+
+
+ "); + while ($list = mysql_fetch_array($fetch)) { + echo("$list[fitter_method_name]\n"); + } + ?> +
+
+
+
Certifications
+
+
+ "); + while ($list = mysql_fetch_array($fetch)) { + echo("$list[fitter_certification_name]\n"); + } + ?> +
+
+
+
Fit Bikes
+
+
+ "); + while ($row = mysql_fetch_array($results)) { + echo("$row[fitter_fitbike_name]\n"); + } + ?> +
+
+
+
Motion-Capture Systems
+
+
+ "); + while ($row = mysql_fetch_array($results)) { + echo("$row[fitter_motioncapture_name]\n"); + } + ?> +
+
+
+
Brand Friendly
+
+
+ Brands where the fitter has a specific *verified* expertise in this brand.
+ "); + while ($row = mysql_fetch_array($results)) { + echo("$row[fitter_brand_name]\n"); + } + ?> +
+
+
+
Cost of Fit
+
+
+ +
+
+
+
General Info
+
+
+ +
+
+
+
Directions
+
+
+ +
+
+
+
+
+
+ + +
+
+
+
+ + + +
+ +
+
+
+ + +
+
+ + +
+ + + diff --git a/site/fitters/add_X.php b/site/fitters/add_X.php new file mode 100644 index 0000000..e5e0c0d --- /dev/null +++ b/site/fitters/add_X.php @@ -0,0 +1,152 @@ +"; + $errmsg = rtrim($errmsg, ", "); +} + +$start_url = "(http(s)?\:\/\/)?"; // start url +$dots = "([\w_-]{2,}\.)+"; // one or more parts containing a '.' at the end +$last_part = "([\w_-]{2,})"; // last part doesn't contain a dot +$user = "((\/)(\~)[\w_=-]+)?((\/)[\w_=-]+)*"; // maybe subdirectories - possibly with user ~ +$end = "((\/)|(\/)[\w_-]+\.[\w]{2,})?"; // maybe a slash at the end or slash+file+extension +$qstring1 = "((\?[\w_-]+\=([^\#]+)){0,1}"; // querystring - first argument (?a=b) +$qstring2 = "(\&[\w_-]+\=([^\#]+))*)?"; // querystring - following arguments (&c=d) +$bkmrk = "(#[\w_-]+)?"; // bookmark + +$exp = "/^".$start_url.$dots.$last_part.$user.$end.$qstring1.$qstring2.$bkmrk."$/i"; +if( !preg_match($exp, $_POST[website]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
"; +} +if($_POST[portfolio] != "" && !preg_match($exp, $_POST[portfolio]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Portfolio Address
"; +} +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[name]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Please use only letters and numbers in the name
"; +} + +// begin error message check +if(!$errmsg){ + + $name = trim($_POST[name]); + $name_tag = strtolower(str_replace(" ","", $name)); + //if(strlen($name_tag) > 12){ //Shorten it + $name_tag = substr($name_tag, 0, 12); + //} // need to update a typo here in other dbs + $address = mysql_escape_string(trim($_POST[address])); + $full_address = $address; + if (isset($_POST['address_two'])) { $address_two = mysql_escape_string(trim($_POST[address_two])); } else { $address_two = NULL; $full_address = $full_address.", ".$address_two; } + $city = mysql_escape_string(trim($_POST[city])); + $full_address = $full_address.", ".$city; + $state = $_POST[state]; + $full_address = $full_address.", ".$state; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = mysql_escape_string(trim($_POST[zip])); + $full_address = $full_address." ".$zip; + $latlng_override = $_POST[latlng_override]; + if ($latlng_override == true) { + $lat = $_POST[lat]; + $lng = $_POST[lng]; + } else { + //geocode + //echo ($full_address); + $geocode_status = geocode($full_address); + //echo (is_array($geocode_status)); + if (is_array($geocode_status)) { + $geocode_error = false; + $lat = $geocode_status[0]; + $_POST[lat] = $lat; + $lng = $geocode_status[1]; + $_POST[lng] = $lng; + //echo ($lat.", ".$lng); + } else { + $geocode_error = true; + $lat = 0; + $_POST[lat] = $lat; + $lng = 0; + $_POST[lng] = $lng; + $geocode_message = $geocode_status; + } + } + $phone = trim($_POST[phone]); + $fax = trim($_POST[fax]); + $email = mysql_escape_string(trim($_POST[email])); + $website = mysql_escape_string(trim($_POST[website])); + $portfolio = mysql_escape_string(trim($_POST[portfolio])); + $methods = mysql_escape_string(trim($_POST[methods])); + $certifications = mysql_escape_string($_POST[certifications]); + $fitbikes = mysql_escape_string($_POST[fitbikes]); + $motioncapture = mysql_escape_string($_POST[motioncapture]); + $brandfriendly = mysql_escape_string($_POST[brandfriendly]); + $cost = mysql_escape_string(trim($_POST[cost])); + $info = mysql_escape_string(nl2br(substr(trim($_POST[info]), 0, 4096))); + $directions = mysql_escape_string(nl2br(substr(trim($_POST[directions]), 0, 4096))); + $submitted_by = $_POST[submitted_by]; + + // begin boolean check to see if we should insert the fitter into the dbase + if($_POST[insert_fitter] == true){ + $sql = "INSERT INTO ".$prefix."Fitters (fitter_name, fitter_name_tag, fitter_address, fitter_address_two, fitter_city, fitter_state, fitter_state_tag, fitter_zip, fitter_lat, fitter_lng, fitter_phone, fitter_fax, fitter_email, fitter_website, fitter_method, fitter_certifications, fitter_fitbikes, fitter_motioncapture, fitter_brandfriendly, fitter_cost, fitter_info, fitter_directions, fitter_submitted_by, fitter_valid, fitter_portfolio) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$lat', '$lng', '$phone', '$fax', '$email', '$website', '$methods', ',$certifications,', ',$fitbikes,', ',$motioncapture,', ',$brandfriendly,', '$cost', '$info', '$directions', $submitted_by, 0, '$portfolio')"; + //echo("shop entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + //exit(); + $insert_success = true; + }else{ + //echo("shop NOT entered."); + $confirm_fitter = true; + } + // end insert check +} +// end error message check +?> diff --git a/site/fitters/ajax.rate.item.php b/site/fitters/ajax.rate.item.php new file mode 100644 index 0000000..2b62953 --- /dev/null +++ b/site/fitters/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/fitters/class/mysql.class.php b/site/fitters/class/mysql.class.php new file mode 100644 index 0000000..6d82189 --- /dev/null +++ b/site/fitters/class/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/fitters/class/rating/classes/database.class.php b/site/fitters/class/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/fitters/class/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/fitters/class/rating/classes/error.class.php b/site/fitters/class/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/fitters/class/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
\r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
\r\n" . + "
" . self::$description[$i] . "

\r\n"; + } + } + + // Write Error Template Output + $output = "
\r\n" . + "
{$error}:
\r\n" . + "
\r\n" . $output . "\r\n
\r\n" . + "
\r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
\r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
\r\n" . + "
" . self::$description[$i] . "

\r\n"; + } + } + + // Write Warning Template Output + $output = "
\r\n" . + "
{$warning}:
\r\n" . + "
\r\n" . $output . "\r\n
\r\n" . + "
\r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/fitters/class/rating/classes/include.all.php b/site/fitters/class/rating/classes/include.all.php new file mode 100644 index 0000000..2c1fa21 --- /dev/null +++ b/site/fitters/class/rating/classes/include.all.php @@ -0,0 +1,7 @@ + diff --git a/site/fitters/class/rating/classes/rating.class.php b/site/fitters/class/rating/classes/rating.class.php new file mode 100644 index 0000000..c1b12f2 --- /dev/null +++ b/site/fitters/class/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +
{$cat_info['rating_cat_name']}
\r\n"; + $output .= "
{$cat_info['rating_cat_min']}
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
{$cat_info['rating_cat_max']}
\r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
{$cat_info['rating_cat_name']}
\r\n"; + $output .= "
{$cat_info['rating_cat_min']}
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
{$cat_info['rating_cat_max']}
\r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
Overall Rating
"; + $output .= "
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
\r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_FittersRating` (`fitter_id_fk`, `category_id_fk`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_FittersRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_FittersRating` WHERE `category_id_fk`='{$varItem}' AND `fitter_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_FittersRating` WHERE `fitter_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_FittersRating` WHERE `category_id_fk`='{$varItem}' AND `fitter_id_fk`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> diff --git a/site/fitters/class/rating/int.to.words.php b/site/fitters/class/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/fitters/class/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/fitters/class/rating/rating-example.php b/site/fitters/class/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/fitters/class/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

Race Rating System:

+ + + + + + + \ No newline at end of file diff --git a/site/fitters/comments_add.php b/site/fitters/comments_add.php new file mode 100644 index 0000000..52af2da --- /dev/null +++ b/site/fitters/comments_add.php @@ -0,0 +1,35 @@ + + +
+ + + + +
+ +Add A Comment +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+ + +
diff --git a/site/fitters/comments_add_X.php b/site/fitters/comments_add_X.php new file mode 100644 index 0000000..412107f --- /dev/null +++ b/site/fitters/comments_add_X.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/site/fitters/comments_show.php b/site/fitters/comments_show.php new file mode 100644 index 0000000..997f0d4 --- /dev/null +++ b/site/fitters/comments_show.php @@ -0,0 +1,19 @@ + + + + +" data-num-posts="5" data-width="500">
*/ ?> +" num_posts="5" width="500">**/ ?> + diff --git a/site/fitters/comments_validate.php b/site/fitters/comments_validate.php new file mode 100644 index 0000000..5e99c91 --- /dev/null +++ b/site/fitters/comments_validate.php @@ -0,0 +1,88 @@ + + + + + + +
+ + +
+ + + + + +

Unvalidated Comments

+
+
+ + + + "> + + + +
Reviewed by: ".$commenter_user_username.""; echo " on ".date("F j, Y g:i A", $arrComments[comment_time]); echo " about ".$fitter_name."";?>
+ +
Validate this comment. Delete this comment.
+
+ +
+
+ + +
+ +
+ + + \ No newline at end of file diff --git a/site/fitters/comments_validate_X.php b/site/fitters/comments_validate_X.php new file mode 100644 index 0000000..0245dbc --- /dev/null +++ b/site/fitters/comments_validate_X.php @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/site/fitters/config.php b/site/fitters/config.php new file mode 100644 index 0000000..f2fe093 --- /dev/null +++ b/site/fitters/config.php @@ -0,0 +1,226 @@ += '4.0.4pl1' && strstr($_SERVER["HTTP_USER_AGENT"],'compatible')) { + if (extension_loaded('zlib')) { + ob_end_clean(); + ob_start('ob_gzhandler'); + } +} else if ($phpver > '4.0') { + if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) { + if (extension_loaded('zlib')) { + $do_gzip_compress = TRUE; + ob_start(array('ob_gzhandler',5)); + ob_implicit_flush(0); + header('Content-Encoding: gzip'); + } + } +} +$phpver = explode(".", $phpver); +$phpver = "$phpver[0]$phpver[1]"; +if ($phpver >= 41) { + $PHP_SELF = $_SERVER['PHP_SELF']; +} + +if (!ini_get("register_globals")) { + #import_request_variables('GPC'); +} + +$statecount = mysql_num_rows(mysql_query("SELECT * FROM gforum_Fitters WHERE fitter_valid = 1")); + +$sql = "SELECT * FROM ".$prefix."FittersStates ORDER BY stateid"; +$result = mysql_query($sql) OR die(mysql_error()); +$state_list = array(); +$state_tag_list = array(); +while ($row = mysql_fetch_array($result)) { + $state_list[$row['stateid']] = $row['statelong']; + $state_tag_list[] = $row['statetag']; +} + +function fist_equipped($fitter_id) { + global $db,$prefix; + + $fist_equipped_bikes = array(10 => "guru", 13 => "retul", 12 => "purely", 2 => "exitcycling", 9 => "probikes"); + + $sql = "SELECT * FROM ".$prefix."Fitters WHERE fitter_id=$fitter_id LIMIT 1"; + + $sql_match = mysql_query($sql) or die(mysql_error()); + $match_row = mysql_fetch_array($sql_match); + + $match_row[fitter_certifications] = ltrim(rtrim($match_row[fitter_certifications], ", "), ", "); + + $sql = ("SELECT * FROM gforum_FittersCertifications WHERE fitter_certification_id IN ($match_row[fitter_certifications]) ORDER BY fitter_certification_name ASC"); + + //echo $sql; + + $fetch = mysql_query($sql) or die(mysql_error()); + + $fist_certified = false; + $fist_equipped = false; + $super_fist = false; + while ($list = mysql_fetch_array($fetch)) { + //echo ($list[fitter_certification_tag]); + $pos = strpos($list[fitter_certification_tag], "fist"); + $sup = strpos($list[fitter_certification_tag], "super"); + if ($pos !== false) { + //echo ("TRUE"); + $fist_certified = true; + if ($sup !== false) { + //echo ("TRUE"); + $fist_super_cert = true; + } + } + } + + if ($fist_certified === true) { + $match_row[fitter_fitbikes] = ltrim(rtrim($match_row[fitter_fitbikes], ", "), ", "); + + $sql = ("SELECT * FROM gforum_FittersFitbikes WHERE fitter_fitbike_id IN ($match_row[fitter_fitbikes]) ORDER BY fitter_fitbike_name ASC"); + + //echo $sql; + + $fetch = mysql_query($sql) or die(mysql_error()); + + $fitbike_list = ""; + while ($list = mysql_fetch_array($fetch)) { + //echo ($list[fitter_fitbike_tag]); + $key = array_search($list[fitter_fitbike_tag], $fist_equipped_bikes); + if ($key !== false){ $fist_equipped = true;} + } + } + + if ($fist_equipped == true && $fist_super_cert == true) { $super_fist = true; } + + if ($fist_equipped) { return("fist_equipped"); } + elseif ($super_fist) { return("super_fist"); } + else { return("none"); } + +} + +function curPageURL() { + $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); + $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); + $port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : ''; + $url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.$_SERVER["REQUEST_URI"]; + return $url; +} + +//Array of states for use in the form +/** $state_list = array('AL'=>"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming", + // New Foreign "States", + 'UK'=>"United Kingdom", + 'FR'=>"France", + 'DE'=>"Germany", + 'IT'=>"Italy", + 'CH'=>"Switzerland", + 'JP'=>"Japan", + 'AU'=>"Australia", + 'NZ'=>"New Zealand", + 'PI'=>"Pacific Islands", + 'HK'=>"Hong Kong"); +*/ +?> diff --git a/site/fitters/csv_list.php b/site/fitters/csv_list.php new file mode 100644 index 0000000..094d95f --- /dev/null +++ b/site/fitters/csv_list.php @@ -0,0 +1,116 @@ +
"); + +$results = mysql_query("SELECT * FROM ".$prefix."Fitters ORDER BY fitter_id ASC"); +while ($row = mysql_fetch_array($results)){ + echo stripslashes(stripslashes($row[fitter_name])) . ", "; + + echo stripslashes(htmlspecialchars($row[fitter_address])) . ", "; + + echo stripslashes(htmlspecialchars($row[fitter_address_two])) . ", "; + + echo stripslashes(htmlspecialchars($row[fitter_city])) . ", "; + + echo stripslashes(htmlspecialchars($row[fitter_state])) . ", "; + + echo stripslashes(htmlspecialchars($row[fitter_zip])) . ", "; + + echo stripslashes(htmlspecialchars($row[fitter_phone])) . ", "; + + echo stripslashes(htmlspecialchars($row[fitter_email])) . ", "; + + $substring = "http"; + if (!is_int(strpos($row[fitter_website], $substring))) { + $row[fitter_website] = "http://".$row[fitter_website]; + } + echo $row[fitter_website] . ", "; + + $row[fitter_fitbikes] = ltrim(rtrim($row[fitter_fitbikes], ", "), ", "); + + //methodology + $sql = ("SELECT * FROM ".$prefix."FittersMethods WHERE fitter_method_id = ".$row[fitter_method]." LIMIT 1"); + + //echo $sql; + + $fetch = mysql_query($sql) or die(mysql_error()); + + if (mysql_num_rows($fetch) > 0) { + while ($method_list = mysql_fetch_array($fetch)) { + echo ("$method_list[fitter_method_name], "); + } + } else { + echo ("Unanswered on fit methodology, "); + } + + + //certifications + $row[fitter_certifications] = ltrim(rtrim($row[fitter_certifications], ", "), ", "); + + $sql = ("SELECT * FROM gforum_FittersCertifications WHERE fitter_certification_id IN ($row[fitter_certifications]) ORDER BY fitter_certification_name ASC"); + + //echo $sql; + + $fetch = mysql_query($sql) or die(mysql_error()); + + $certification_list = ""; + while ($list = mysql_fetch_array($fetch)) { + $certification_list = $certification_list."$list[fitter_certification_name] / "; + } + $certification_list = rtrim($certification_list, '/ '); + + if ($certification_list) {echo $certification_list . ", ";} else {echo "No certification(s), ";} + + //fitbikes + $sql = ("SELECT * FROM gforum_FittersFitbikes WHERE fitter_fitbike_id IN ($row[fitter_fitbikes]) ORDER BY fitter_fitbike_name ASC"); + + //echo $sql; + + $fetch = mysql_query($sql) or die(mysql_error()); + + $fitbike_list = ""; + while ($list = mysql_fetch_array($fetch)) { + $fitbike_list = $fitbike_list."$list[fitter_fitbike_name] / "; + } + $fitbike_list = rtrim($fitbike_list, '/ '); + + if ($fitbike_list) {echo $fitbike_list . ", ";} else {echo "No fitbike(s), ";} + + //motion captures + $row[fitter_motioncapture] = ltrim(rtrim($row[fitter_motioncapture], ", "), ", "); + + $sql = ("SELECT * FROM gforum_FittersMotioncapture WHERE fitter_motioncapture_id IN ($row[fitter_motioncapture]) ORDER BY fitter_motioncapture_name ASC"); + + //echo $sql; + + $fetch = mysql_query($sql) or die(mysql_error()); + + $motioncapture_list = ""; + while ($list = mysql_fetch_array($fetch)) { + $motioncapture_list = $motioncapture_list."$list[fitter_motioncapture_name] / "; + } + $motioncapture_list = rtrim($motioncapture_list, '/ '); + + if ($motioncapture_list) {echo $motioncapture_list;} else {echo "No motion capture system(s)";} + + echo "
"; + +} +?> \ No newline at end of file diff --git a/site/fitters/delete_X.php b/site/fitters/delete_X.php new file mode 100644 index 0000000..b4a8f25 --- /dev/null +++ b/site/fitters/delete_X.php @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/site/fitters/include_add_confirm.php b/site/fitters/include_add_confirm.php new file mode 100644 index 0000000..f644e8c --- /dev/null +++ b/site/fitters/include_add_confirm.php @@ -0,0 +1,296 @@ +

Please confirm your information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your information before submitting.

+ +
+
+
Store Name
+
+
+ + = 50) { + if ($i == false) { + echo ("Duplicate Alert:"); + } + echo ("".$match_row['fitter_name']." (".$match_row['fitter_city'].", ".$match_row['fitter_state'].") (Similarity: ".(round($percent, 0))."%)"); + $i = true; + } + } + ?> +
+
+
+
Address
+
+
+
+
+
Address 2
+
+
+
+
+
City
+
+
+
+
+
State
+
+
+
+
+
Zip
+
+
+
+
+
Lat/Lng
+
+
+ +
+
+
+
Phone
+
+
+
+
+
Fax
+
+
+
+
+
E-mail
+
+
+
+
+
Website
+
+
+
+
+
Portfolio
+
+
+
+
+
+
+
+ +
+
+
+
Default Tri-Fit Methodology
+
+
+ 0) { + while ($row = mysql_fetch_array($results)) { + echo ("$row[fitter_method_name]"); + } + } else { + echo ("Unanswered"); + } + + ?> +
+
+
+
Certifications
+
+
+ +
+
+
+
Fit Bikes
+
+
+ +
+
+
+
Motion-Capture Systems
+
+
+ +
+
+
+
Brand Friendly
+
+
+ +
+
+
+
Cost of Fit
+
+
+ +
+
+
+
General Info
+
+
+ +
+
+
+
Directions
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ diff --git a/site/fitters/include_breadcrumb.php b/site/fitters/include_breadcrumb.php new file mode 100644 index 0000000..09e3dc5 --- /dev/null +++ b/site/fitters/include_breadcrumb.php @@ -0,0 +1,12 @@ + diff --git a/site/fitters/include_buttons.php b/site/fitters/include_buttons.php new file mode 100644 index 0000000..863d9d6 --- /dev/null +++ b/site/fitters/include_buttons.php @@ -0,0 +1,107 @@ + + +
+ + + + + + +
+ +
" style="display: inline;"> + +
+ +
" style="display: inline;"> + +
+ +
" style="display: inline;"> + +
+ + + +
+ + +
+ +
Entered By: $username"); + } +} +?> diff --git a/site/fitters/include_common_content.php b/site/fitters/include_common_content.php new file mode 100644 index 0000000..5fbb11e --- /dev/null +++ b/site/fitters/include_common_content.php @@ -0,0 +1,40 @@ + + +> + + +
+
+ + + + +
+
+
+ + + +
+
+
+
+
diff --git a/site/fitters/include_common_footer.php b/site/fitters/include_common_footer.php new file mode 100644 index 0000000..f11e4aa --- /dev/null +++ b/site/fitters/include_common_footer.php @@ -0,0 +1 @@ + diff --git a/site/fitters/include_common_head.php b/site/fitters/include_common_head.php new file mode 100644 index 0000000..31611e0 --- /dev/null +++ b/site/fitters/include_common_head.php @@ -0,0 +1,24 @@ + + + + + +Slowtwitch.com Fitter Database: <? echo $pagetitle; ?> + + + + + + + + diff --git a/site/fitters/include_edit_confirm.php b/site/fitters/include_edit_confirm.php new file mode 100644 index 0000000..85898ef --- /dev/null +++ b/site/fitters/include_edit_confirm.php @@ -0,0 +1,306 @@ +

Please confirm your information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your information before submitting.

+ +
+
+
Store Name
+
+
+ +
+
+
+
Address
+
+
+
+
+
Address 2
+
+
+
+
+
City
+
+
+
+
+
State
+
+
+
+
+
Zip
+
+
+
+
+
Lat/Lng
+
+
+ +
+
+
+
Phone
+
+
+
+
+
Fax
+
+
+
+
+
E-mail
+
+
+
+
+
Website
+
+
+
+
+
Portfolio
+
+
+
+
+
+
+
+ +
+
+
+
Default Tri-Fit Methodology
+
+
+ 0) { + while ($method_list = mysql_fetch_array($fetch)) { + echo ("$method_list[fitter_method_name]"); + } + } else { + echo ("Unanswered"); + } + ?> +
+
+
+
Certifications
+
+
+ +
+
+
+
Fit Bikes
+
+
+ +
+
+
+
Motion-Capture Systems
+
+
+ +
+
+
+
Brand Friendly
+
+
+ +
+
+
+
Cost of Fit
+
+
+ +
+
+
+
General Info
+
+
+ +
+
+
+
Directions
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This data will be saved as a NEW FITTER. + + + + This data will be saved as a modification to the EXISTING FITTER. + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
diff --git a/site/fitters/include_navigation.php b/site/fitters/include_navigation.php new file mode 100644 index 0000000..2286067 --- /dev/null +++ b/site/fitters/include_navigation.php @@ -0,0 +1,73 @@ + + +
+

Browse Fitters

+
+ +Outside N. America
"); } + $region_dropdown .= "$state_string"; + echo ("
" . $currentregion . " (" . $regioncount . ")+
"); + echo $tempstring; + echo ("
\n"); + } + $currentregion = $rowregionlist[regionlong]; + $currentrid = $rowregionlist[regionid]; + $currenttag = $rowregionlist[regionname]; + $regioncount = 0; + $tempstring = ''; + $state_string = ''; + } + if ($selected_item == $rowregionlist[statetag]) { + $selected_state = ' selected="selected"'; + } + $state_string .= ""; + $tempstring = $tempstring. "$rowregionlist[statelong] ($rowregionlist[numclubs])\n"; + $regioncount += $rowregionlist[numclubs]; +} + +echo ("
".$currentregion." (".$regioncount.")+
"); +echo $tempstring; +echo ('
'); + +if ( $selected_item == 'top') { $selected_region = ' selected="selected"'; } +$region_dropdown .= ""; + +?> + +
+
diff --git a/site/fitters/include_share.php b/site/fitters/include_share.php new file mode 100644 index 0000000..26d9b89 --- /dev/null +++ b/site/fitters/include_share.php @@ -0,0 +1,17 @@ + diff --git a/site/fitters/include_sidebar.php b/site/fitters/include_sidebar.php new file mode 100644 index 0000000..2565e57 --- /dev/null +++ b/site/fitters/include_sidebar.php @@ -0,0 +1,14 @@ + + +
+ + + +
+ + diff --git a/site/fitters/include_status.php b/site/fitters/include_status.php new file mode 100644 index 0000000..f783e93 --- /dev/null +++ b/site/fitters/include_status.php @@ -0,0 +1,13 @@ + + +
Admin:"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table." WHERE ".$field_lead."valid = 0")); + echo("
Validate Entries (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Edits")); + echo("
Validate Edits (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Comment WHERE comment_valid = 0")); + echo("
Validate Comments (".$unvalid_count.")"); +} +?> diff --git a/site/fitters/include_store.php b/site/fitters/include_store.php new file mode 100644 index 0000000..8b9242d --- /dev/null +++ b/site/fitters/include_store.php @@ -0,0 +1,23 @@ +
+
+

">

+
+ +

(Avg. rating based on )

+ +
+ $row[fitter_address_two]"); } + echo("
$row[fitter_city], $row[fitter_state] $row[fitter_zip]"); + ?> +
Phone: +
Fax: +
+
+ Email: $row[fitter_email]"; ?>
+ Website: $row[fitter_website]"; ?>
+ "); } ?> + ">More info > +
+
diff --git a/site/fitters/index.php b/site/fitters/index.php new file mode 100644 index 0000000..c73ae81 --- /dev/null +++ b/site/fitters/index.php @@ -0,0 +1,136 @@ + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Fitters

+ + + Add Fitter + +
+ + +
+
+
+ + +

Welcome to Slowtwitch.com's North American Bike Fitter Database

+

fitters and counting. This collection of fitters is the most complete and comprehensive + selection of bike fitters in North America.

+ +

F.I.S.T. equipped fitters

+ +

+ Fitters who have attended a F.I.S.T. tribike fit workshop *AND* who have what we consider to be a F.I.S.T.-compatible fitbike (Purely Custom, EXIT Cycling, Retul, Rob King, or Guru DFU) have a special icon to designate what we consider to be a particularly important confluence of skills and tools. You will see this icon prominently displayed on the regional, state, and top fitter lists, on your advanced search results, and also on the fitter's individual page. Look for this icon if you want someone who has both the equipment and the training to execute a textbook F.I.S.T. fit. +

+ +

Searching the database

+

+ Our Advanced Search is very potent, and will help you drill down to that set + of fitters conforming to a specific purpose you have in mind. +

+ +

Browsing the database

+

+ You do not need to log in to do this. You'll find a list of fitters in + your region by clicking the regional links on the left. Click the (+) sign + and the region will expand to expose the individual states. Click on the + state to show that list of fitters in it. If you want to see fitters in + multiple states, but not those states we've aggregated into the regions you + see at left, you may do this via our Advanced Search. +

+ +

Showing solidarity with your fitter

+

+ When you see your local fitter listed here, you may click the "I WAS FIT HERE" button. Your User Name will be added to the fitters's list of clients, + just like your User Name appends to those races you choose when you build + your Slowtwitch Personal Race Calendar. Likewise, your Forum User Profile + will show that this is your fitter of choice. +

+ +

How to enter a fitter

+

+ You must be a registered user to add a fitter to the database. There is + one common type of registration on Slowtwitch, and if you are registered to + post on our Reader Forum you are one of + + who have made a registration, + and this means you're able to add fitters to our database. +

+ If you're not registered, the login prompt is to the left of the page, near + the top. The registration process is straightforward, easy, and free. It + will require you to receive an email and click on a link to complete your + registration. All this should take you only a minute or two. Then... +

+ 1. Click the ADD A FITTER button to begin adding to the database. +

+ 2. Once you SUBMIT your fitter, you'll also need to CONFIRM your submission + via a link at the bottom of the page. +

+ 3. Once you successfully add your fitter, it will not immediately be visible + to you. We must validate the addition on our end before anyone can see it. + We do this so that spammers won't use the fitter registration as a way to spam + our database. +

+

How to edit published information about a fitter

+

+ Any registered user may edit information for a listing. We will review the full contents of each update before confirming any changes that are made. A list of all editors who have made changes is visible at the bottom of each listing. If an entry has been updated, but those changes have not yet been confirmed, this is evident via a note on the individual page for that particular entry. This is to prevent conflicting updates from occuring simultaneously. If you wish to update an entry with pending changes, please wait until we have had a chance to review those changes first. Someone may have already changed the information you were going to change yourself. +

+

How to comment on a fitter

+

+ Any registered user may make a comment on a fitter listing. These comments are subject to validation by an administrator before being published. +

+

Global fitter map

+

+ The map below shows the location of all registered Slowtwitch fitters around the globe. You can drag the map, zoom-in, zoom-out, and use any other of the standard Google Maps features. Anywhere you see a red icon, you can click to see the name of that fitter and a street address. +

+ +
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/fitters/individual.php b/site/fitters/individual.php new file mode 100644 index 0000000..aeb2785 --- /dev/null +++ b/site/fitters/individual.php @@ -0,0 +1,288 @@ + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Fitters

+ +
+ +
+ + Back +
+ +
+
+

+
+
+ Comment +
+
+
+
+ "); } ?> + ,
+ Phone:
+ Fax: +
+
+ Email:
+ Website:
+ Portfolio: +
+
+ + +

Commenter: your comments have been submitted and will be validated within 24 hours.

+ + +

Editor: your changes have been submitted and will be validated within 24 hours.

+ + + +

Group Edits: there are group edits waiting to be validated.

+ + +
+ + +
+ +
+

Fit Information

+
+ Default Tri-Fit Methodology: + 0) { + while ($method_list = mysql_fetch_array($fetch)) { + echo ("$method_list[fitter_method_name]"); + } + } else { + echo ("Unanswered"); + } + ?>
+ Certifications: +
+ Fit Bikes: +
+ Motion-Capture Systems: +
+ Brand-Friendly: +
+ Cost of Fit: +
+
+
+

General Information

+
+ General Information:
+ Directions: +
+
+
+
+
+ +
+ + Map location is based off of a geocode of the addressed entered using Google's Google Maps API. If your address does not geocode properly, you can either update the address (we will attempt to re-geocode after any updates to your entry) or you can use Google's geocoding tool found here: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html to obtain a lat/long for your location and enter that. To use the utility, type in an address that is close to your location and then drag-and-drop the marker to obtain the desired lat/long. If you choose to enter a lat/long, you must check the box on the edit page that says, "override geocode with entered lat/long." + +
+
+
+

Who was fit?

+
+ + + + 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i > 1){ echo ", "; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username]"; + // TODO: SLOWTWITCH EDIT END + } + $i++; + } + ?> +
+
+
+ + + +

+
+ = 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i >= 1){ echo "
"; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + // TODO: SLOWTWITCH EDIT END + } + $i++; + } + if($numcount <= 0){ echo "No users"; } + ?> +
+
+
+
+ + +
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/fitters/logout.php b/site/fitters/logout.php new file mode 100644 index 0000000..f7b445b --- /dev/null +++ b/site/fitters/logout.php @@ -0,0 +1,7 @@ + diff --git a/site/fitters/phpsqlgeocode_csv.php b/site/fitters/phpsqlgeocode_csv.php new file mode 100644 index 0000000..4ef6e6b --- /dev/null +++ b/site/fitters/phpsqlgeocode_csv.php @@ -0,0 +1,86 @@ += 5) { + // successful geocode + $geocode_pending = false; + $lat = $csvSplit[2]; + $lng = $csvSplit[3]; + + $query = sprintf("UPDATE gforum_Fitters " . + " SET fitter_lat = '%s', fitter_lng = '%s' " . + " WHERE fitter_id = %s LIMIT 1;", + mysql_real_escape_string($lat), + mysql_real_escape_string($lng), + mysql_real_escape_string($id)); + $update_result = mysql_query($query); + if (!$update_result) { + die("Invalid query: " . mysql_error()); + } + } else if (strcmp($status, "620") == 0) { + // sent geocodes too fast + $delay += 100000; + } else if ($accuracy < 5) { + // failure to geocode + $geocode_pending = false; + echo $request_url . "\n"; + echo "Address " . $address . " did not geocode to great enough accuracy to be useful. "; + echo "Accuracy match: " . $accuracy . " +\n"; + } else { + // failure to geocode + $geocode_pending = false; + echo "Address " . $address . " failed to geocode. "; + echo "Received status " . $status . " +\n"; + } + usleep($delay); + } +} +?> diff --git a/site/fitters/rating/ajax.rate.item.php b/site/fitters/rating/ajax.rate.item.php new file mode 100644 index 0000000..38c90de --- /dev/null +++ b/site/fitters/rating/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/fitters/rating/classes/database.class.php b/site/fitters/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/fitters/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/fitters/rating/classes/error.class.php b/site/fitters/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/fitters/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
\r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
\r\n" . + "
" . self::$description[$i] . "

\r\n"; + } + } + + // Write Error Template Output + $output = "
\r\n" . + "
{$error}:
\r\n" . + "
\r\n" . $output . "\r\n
\r\n" . + "
\r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
\r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
\r\n" . + "
" . self::$description[$i] . "

\r\n"; + } + } + + // Write Warning Template Output + $output = "
\r\n" . + "
{$warning}:
\r\n" . + "
\r\n" . $output . "\r\n
\r\n" . + "
\r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/fitters/rating/classes/include.all.php b/site/fitters/rating/classes/include.all.php new file mode 100644 index 0000000..76004b9 --- /dev/null +++ b/site/fitters/rating/classes/include.all.php @@ -0,0 +1,8 @@ + diff --git a/site/fitters/rating/classes/rating.class.php b/site/fitters/rating/classes/rating.class.php new file mode 100644 index 0000000..f12afa7 --- /dev/null +++ b/site/fitters/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +
{$cat_info['rating_cat_name']}
\r\n"; + $output .= "
{$cat_info['rating_cat_min']}
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
{$cat_info['rating_cat_max']}
\r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
{$cat_info['rating_cat_name']}
"; + $output .= "
{$cat_info['rating_cat_min']}
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
{$cat_info['rating_cat_max']}
\r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
Overall Rating
"; + $output .= "
    \r\n"; + $output .= "
  • 1
  • \r\n"; + $output .= "
  • 2
  • \r\n"; + $output .= "
  • 3
  • \r\n"; + $output .= "
  • 4
  • \r\n"; + $output .= "
  • 5
  • \r\n"; + $output .= "
\r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_FittersRating` (`fitter_id_fk`, `rating_category_id`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_FittersRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_FittersRating` WHERE `rating_category_id`='{$varItem}' AND `fitter_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_FittersRating` WHERE `fitter_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_FittersRating` WHERE `rating_category_id`='{$varItem}' AND `fitter_id_fk`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> diff --git a/site/fitters/rating/int.to.words.php b/site/fitters/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/fitters/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/fitters/rating/rating-example.php b/site/fitters/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/fitters/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

Race Rating System:

+ + + + + + + \ No newline at end of file diff --git a/site/fitters/regionlist.php b/site/fitters/regionlist.php new file mode 100644 index 0000000..3fa23e5 --- /dev/null +++ b/site/fitters/regionlist.php @@ -0,0 +1,87 @@ + + + + + + +
+ +
+
+ + + +
+ + +
+
+ +
+

Bike Fitters

+ Back + + " class="btn btn-white float-right">Add Fitter + +
+ + +

Region

+
+ + + + + +
+
+
+
+ +
+
+ + +
+ + + diff --git a/site/fitters/search.php b/site/fitters/search.php new file mode 100644 index 0000000..f41933d --- /dev/null +++ b/site/fitters/search.php @@ -0,0 +1,282 @@ + + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Search For A Fitter

+ +

If you would like to search for a fitter, please use the form below. None of the fields are mandatory. Checking no box in a field indicates you don't care if a fitter has or does not have certifications, a fit bike, or motion capture system. Checking regions selects all states in that region. Checking any state's box selects or deselects that state. All searches are "OR" based, so checking two boxes will find fitters that, for example, use either an EXIT fit bike OR a Serotta size-cycle. The one exception is for certifications, where checking both boxes will find fitters who have ALL of the checked certifications; you can use the "ANY" box to search for fitters who have any certification.

+ +
+

+ +
+
+
Name Search
+
+
+ +
+
+
+
+
+
+

Bike Fit

+
+
+
+
Has Portfolio Link
+
+
+ Portfolio Link in Profile +
+
+
+
Default Tri-Fit Methodology
+
+
+"); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +echo("\n"); +$i++; +while($i<4) { + echo(""); + $i++; +} +if(!($i%4)) echo ""; + +echo(""); + +?> +
$row[fitter_method_name]ANY 
+
+
+
+
Fit Certifications:
+
+
+"); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +if(!($i%4)) echo ""; +echo("\n"); +echo(""); + +?> +
$row[fitter_certification_name]
ANY
+
+
+
+
Fit-Bike Model(s) Used
+
+
+"); +//echo(""); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +if(!($i%4)) echo ""; +echo("\n"); +echo(""); + +?> +
$row[fitter_fitbike_name]
ANY
+
+
+
+
Motion-Capture Systems
+
+
+"); +//echo(""); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +if(!($i%4)) echo ""; +echo("\n"); +echo(""); + +?> +
$row[fitter_motioncapture_name]
ANY
+ +
+
+
+
Brand Friendly
+
+
+"); +//echo(""); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +if(!($i%4)) echo ""; +echo("\n"); +echo(""); + +?> +
$row[fitter_brand_name]
ANY
+ +
+
+
+
+
+
+

Location

+
+
+
+
Region
+
+
+ +"; +foreach($regions AS $region => $statetag) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + +} + +?> + +
$region
+

Selecting a region will select all states in that region. You can then deselect or select any additional states. Only the selected states will be included in your search. Leaving all boxes blank will select races in all states.

+
+
+
+
State
+
+
+ +"; +while($row = mysql_fetch_array($state_list)){ + if(!($i%4)) echo ""; + echo "\n"; + $i++; +} +?> + +
$row[statelong]
+

Leave blank to select all.

+
+
+
+
+
+
+ + +
+
+
+ +
+ +
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/fitters/search_X.php b/site/fitters/search_X.php new file mode 100644 index 0000000..67555fc --- /dev/null +++ b/site/fitters/search_X.php @@ -0,0 +1,269 @@ + ''"; +} + +if (isset($_POST[methods])) { + if (in_array("999", $_POST[methods])) { + $sql = $sql." AND fitter_method <> '0'"; + } else { + $sql = $sql." AND ("; + $flag = 0; + foreach ($_POST[methods] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql."fitter_method = '$value'"; + $flag = 1; + } + $sql = $sql.")"; + } +} + +if (isset($_POST[certifications])) { + if (in_array("999", $_POST[certifications])) { + $sql = $sql." AND fitter_certifications <> ',0,'"; + } else { + /**$sql = $sql."AND ("; + $flag = 0; + foreach ($_POST[certifications] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql."fitter_certifications LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")";**/ + foreach ($_POST[certifications] AS $value) { + $sql = $sql." AND fitter_certifications LIKE '%,$value,%'"; + } + } +} + +if (isset($_POST[fitbikes])) { + if (in_array("999", $_POST[fitbikes])) { + $sql = $sql." AND fitter_fitbikes <> ',0,'"; + } else { + $sql = $sql."AND ("; + $flag = 0; + foreach ($_POST[fitbikes] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql."fitter_fitbikes LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + //foreach ($_POST[fitbikes] AS $value) { + //$sql = $sql." OR fitter_fitbikes LIKE '%,$value,%'"; + //} + } +} + +if (isset($_POST[motioncapture])) { + if (in_array("999", $_POST[motioncapture])) { + $sql = $sql." AND fitter_motioncapture <> ',0,'"; + } else { + $sql = $sql."AND ("; + $flag = 0; + foreach ($_POST[motioncapture] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql."fitter_motioncapture LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + //foreach ($_POST[motioncapture] AS $value) { + //$sql = $sql." AND fitter_motioncapture LIKE '%,$value,%'"; + //} + } +} + +if (isset($_POST[brandfriendly])) { + if (in_array("999", $_POST[brandfriendly])) { + $sql = $sql." AND fitter_brandfriendly <> ',0,'"; + } else { + $sql = $sql."AND ("; + $flag = 0; + foreach ($_POST[brandfriendly] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql."fitter_brandfriendly LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + //foreach ($_POST[motioncapture] AS $value) { + //$sql = $sql." AND fitter_motioncapture LIKE '%,$value,%'"; + //} + } + } + +// regions are checkboxes that then check off all states within that region +// add states +if (isset($_POST[states])) { + $glue = "','"; + $statelist = "('".implode($glue, $_POST[states])."')"; + $sql = $sql." AND fitter_state_tag IN $statelist"; +} + + +$sql = $sql." ORDER BY fitter_name ASC"; + +//echo $sql; + +$results = mysql_query($sql) OR die(mysql_error()); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} +$match_count = mysql_num_rows($results); + +//keyword search +// trim redundant keywords: triathlon, duathlon +$trim_words = array(" the ", " a ", " an ", "and ", " half ", "triathlon", "duathlon"); +foreach ($trim_words AS $word) { + $_POST['keyword'] = str_ireplace($word, " ", $_POST['keyword']); +} +$bool_Keywords = false; +if (isset($_POST['keyword']) && $_POST['keyword'] != "") { + $bool_Keywords = true; + while($row_fitteres = mysql_fetch_array($results)) { + // build an array that we can loop through. + $arr_fitteres[$i] = $row_fitteres; + $i++; + } + + $arr_Matches = array(); + foreach ($arr_fitteres AS $fitter) { + if (stripos($fitter['fitter_name'], $_POST['keyword']) !== false) { + // push this onto the array of matches + $fitter['percent'] = 100; + array_push($arr_Matches, $fitter); + } else { + $name_nospace = str_replace(" ", "", $fitter['fitter_name']); + $keyword_nospace = str_replace(" ", "", $_POST['keyword']); + if (stripos($name_nospace, $keyword_nospace) !== false) { + // push this onto the array of matches + $fitter['percent'] = 90; + array_push($arr_Matches, $fitter); + } else { + // trim redundant keywords + $fitter_name = $fitter['fitter_name']; + foreach ($trim_words AS $word) { + $fitter_name = str_ireplace($word, " ", $fitter_name); + } + //$fitter_name = str_ireplace(" ", "", $fitter_name); + $fitter_name = strtolower($fitter_name); + $arr_fitter_name = explode(" ", $fitter_name); + $_POST['keyword'] = strtolower($_POST['keyword']); + $_POST['keyword'] = str_replace(" ", "", $_POST['keyword']); + foreach ($arr_fitter_name AS $test_word) { + similar_text($test_word, $_POST['keyword'], $percent); + if ($percent >= $comp_pct) { + // push this onto the array of matches + $fitter['percent'] = round($percent, 0); + //$fitter['trimmed'] = $fitter_name; + array_push($arr_Matches, $fitter); + break; + } + } + } + } + } + + if (count($arr_Matches) == 0) { + $none = TRUE; + } + $match_count = count($arr_Matches); + + //sort the array by keyword match success instead of by date + function cmp($a, $b) + { + if ($a['percent'] == $b['percent']) { + return 0; + } + return ($a['percent'] > $b['percent']) ? -1 : 1; + } + + usort($arr_Matches, "cmp"); +} +//end keyword search + +// set the page title +$pagetitle = "Search Results"; + +// set meta tags +$meta_keywords = "search, fitters, triathlon, results"; +$meta_description = "Bike fitters matching a user's search query. A list of matching fitters."; +?> + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Search Results

+

Fitters Match Your Search Criteria

+ + +
+ +
+
+
+ +
+
+ + +
+ + + diff --git a/site/fitters/statelist.php b/site/fitters/statelist.php new file mode 100644 index 0000000..a09ff6a --- /dev/null +++ b/site/fitters/statelist.php @@ -0,0 +1,85 @@ + + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+

Fitters

+ Back + + Add Fitter + +
+ + +

State

+ No bike fitters have been entered yet for $statename.

"; + } + ?> + + + +
+
+
+
+ +
+
+ + +
+ + + diff --git a/site/fitters/top.php b/site/fitters/top.php new file mode 100644 index 0000000..c0b9cf8 --- /dev/null +++ b/site/fitters/top.php @@ -0,0 +1,72 @@ + 10 ORDER BY score DESC, votes DESC LIMIT 10") OR die(mysql_error()); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} + +// set the page title +$pagetitle = "Top Bike Fitters"; + +// set meta tags +$meta_keywords = "top ranked bike fitters"; +$meta_description = "Top ranked bike fitters based on rankings submitted by the user."; +?> + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Top Ranked Bike Fitters

+
+ + + +

+ + +

+ +
+
+
+ +
+
+ + +
+ + + + diff --git a/site/fitters/validate.php b/site/fitters/validate.php new file mode 100644 index 0000000..bc6b43a --- /dev/null +++ b/site/fitters/validate.php @@ -0,0 +1,90 @@ + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Unvalidated Fitters

+
+ +
+ + +
Address: $row[fitter_address_two]"); } echo("
$row[fitter_city], $row[fitter_state] $row[fitter_zip]"); ?>
+
+ Fax/Alt Phone: $row[fitter_fax]"; + + ?> +
+
+ Email: $row[fitter_email]"; ?>
+ Website: $row[fitter_website]"; ?> +
+ ">More information +
Validate this fitter. Delete this fitter.
+
+ +
+ +
+ +
+ +
+
+
+ + +
+
+ + +
+ + + diff --git a/site/fitters/validate_X.php b/site/fitters/validate_X.php new file mode 100644 index 0000000..c238f40 --- /dev/null +++ b/site/fitters/validate_X.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/site/fitters/wiki_buttons.php b/site/fitters/wiki_buttons.php new file mode 100644 index 0000000..3c5e174 --- /dev/null +++ b/site/fitters/wiki_buttons.php @@ -0,0 +1,21 @@ + + +
+ +
+ + +
+ +
+ + +
+ +
diff --git a/site/fitters/wiki_edit.php b/site/fitters/wiki_edit.php new file mode 100644 index 0000000..8050d34 --- /dev/null +++ b/site/fitters/wiki_edit.php @@ -0,0 +1,362 @@ + + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+ + +

Edit a Fitter: Step 2 of 2

+ +

Edit a Fitter: Step 1 of 2

+
+ + +

To edit a fitter, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes as a NEW fitter (for instance, if you have multiple chapters), hit the "SAVE AS A NEW FITTER" button. To save changes to the existing fitter entry, hit the "SAVE CHANGES TO YOUR FITTER" button. You will have a chance to review the data before confirming. You will then be prompted to confirm your information before the information is sent to us.

+ +

+ + +
+
+
+
Store Name
+
+
+ +
+
+
+
Address
+
+
+ +
+
+
+
Address 2
+
+
+ +
+
+
+
City
+
+
+ +
+
+
+
State
+
+
+ +
+
+
+
Zip/Postal Code
+
+
+ +
+
+
+
Override Address With Lat/Lng
+
+
+ > Check this if you know your physical address doesn't geocode properly using Google's API.
Then enter the desired lat/lng in the boxes below. +
+
+
+
Latitude
+
+
+ +
+
+
+
Longitude
+
+
+ +
+
+
+
Phone
+
+
+ +
+
+
+
Fax
+
+
+ +
+
+
+
E-mail
+
+
+ +
+
+
+
Website
+
+
+ +
+
+
+
Portfolio
+
+
+ +
+
+
+
+
+
+ +
+
+
+
Default Tri-Fit Methodology
+
+
+ "); + while ($list = mysql_fetch_array($fetch)) { + echo("$list[fitter_method_name]\n"); + } + ?> +
+
+
+
Certifications
+
+
+ "); + while ($list = mysql_fetch_array($fetch)) { + echo("$list[fitter_certification_name]\n"); + } + ?> +
+
+
+
Fit Bikes
+
+
+ "); + while ($fetch = mysql_fetch_array($results)) { + echo("$fetch[fitter_fitbike_name]\n"); + } + ?> +
+
+
+
Motion-Capture Systems
+
+
+ "); + while ($fetch = mysql_fetch_array($results)) { + echo("$fetch[fitter_motioncapture_name]\n"); + } + ?> +
+
+
+
Brand Friendly
+
+
+ Brands where the fitter has a specific *verified* expertise in this brand.
+ "); + while ($fetch = mysql_fetch_array($results)) { + echo("$fetch[fitter_brand_name]\n"); + } + ?> +
+
+
+
Cost of Fit
+
+
+ +
+
+
+
General Info
+
+
+ +
+
+
+
Directions
+
+
+ +
+
+
+
+
+
+ + + + + + + + + +
+
+
+
+ + + +
+ +
+
+
+ + +
+
+ + +
+ + + diff --git a/site/fitters/wiki_edit_X.php b/site/fitters/wiki_edit_X.php new file mode 100644 index 0000000..cb46c1c --- /dev/null +++ b/site/fitters/wiki_edit_X.php @@ -0,0 +1,189 @@ +"; + $errmsg = rtrim($errmsg, ", "); +} + +$start_url = "(http(s)?\:\/\/)?"; // start url +$dots = "([\w_-]{2,}\.)+"; // one or more parts containing a '.' at the end +$last_part = "([\w_-]{2,})"; // last part doesn't contain a dot +$user = "((\/)(\~)[\w_=-]+)?((\/)[\w_=-]+)*"; // maybe subdirectories - possibly with user ~ +$end = "((\/)|(\/)[\w_-]+\.[\w]{2,})?"; // maybe a slash at the end or slash+file+extension +$qstring1 = "((\?[\w_-]+\=([^\#]+)){0,1}"; // querystring - first argument (?a=b) +$qstring2 = "(\&[\w_-]+\=([^\#]+))*)?"; // querystring - following arguments (&c=d) +$bkmrk = "(#[\w_-]+)?"; // bookmark + +$exp = "/^".$start_url.$dots.$last_part.$user.$end.$qstring1.$qstring2.$bkmrk."$/i"; +if( !preg_match($exp, $_POST[fitter_website]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
"; +} +if($_POST[fitter_portfolio] != "" && !preg_match($exp, $_POST[fitter_portfolio]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Portfolio Address
"; +} +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[fitter_name]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Please use only letters and numbers in the name
"; +} + +if(!$errmsg){ + + $name = trim($_POST[fitter_name]); + $name_tag = strtolower(str_replace(" ","", $name)); + if(strlen($nametag) > 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = mysql_escape_string(trim($_POST[fitter_address])); + $full_address = $address; + if (isset($_POST['fitter_address_two'])) { $address_two = mysql_escape_string(trim($_POST[fitter_address_two])); } else { $address_two = NULL; $full_address = $full_address.", ".$address_two; } + $city = mysql_escape_string(trim($_POST[fitter_city])); + $full_address = $full_address.", ".$city; + $state = $_POST[fitter_state]; + $full_address = $full_address.", ".$state; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = mysql_escape_string(trim($_POST[fitter_zip])); + $full_address = $full_address." ".$zip; + $latlng_override = $_POST[latlng_override]; + if ($latlng_override == true) { + $lat = $_POST[fitter_lat]; + $lng = $_POST[fitter_lng]; + } else { + //geocode + //echo ($full_address); + $geocode_status = geocode($full_address); + //echo (is_array($geocode_status)); + if (is_array($geocode_status)) { + $geocode_error = false; + $lat = $geocode_status[0]; + $_POST[fitter_lat] = $lat; + $lng = $geocode_status[1]; + $_POST[fitter_lng] = $lng; + //echo ($lat.", ".$lng); + } else { + $geocode_error = true; + $lat = 0; + $_POST[fitter_lat] = $lat; + $lng = 0; + $_POST[fitter_lng] = $lng; + $geocode_message = $geocode_status; + } + } + $phone = trim($_POST[fitter_phone]); + $fax = trim($_POST[fitter_fax]); + $email = mysql_escape_string(trim($_POST[fitter_email])); + $website = mysql_escape_string(trim($_POST[fitter_website])); + $portfolio = mysql_escape_string(trim($_POST[fitter_portfolio])); + $method = mysql_escape_string(trim($_POST[fitter_method])); + $certifications = mysql_escape_string(trim($_POST[fitter_certifications])); + $fitbikes = mysql_escape_string(trim($_POST[fitter_fitbikes])); + $motioncapture = mysql_escape_string(trim($_POST[fitter_motioncapture])); + $brandfriendly = mysql_escape_string(trim($_POST[fitter_brandfriendly])); + $cost = mysql_escape_string(trim($_POST[fitter_cost])); + $info = mysql_escape_string(nl2br(substr(trim($_POST[fitter_info]), 0, 4096))); + $directions = mysql_escape_string(nl2br(substr(trim($_POST[fitter_directions]), 0, 4096))); + $submitted_by = mysql_escape_string(trim($_POST[fitter_submitted_by])); + $id = mysql_escape_string(trim($_POST[fitter_id])); + $edited_by = mysql_escape_string(trim($_POST[edited_by])); + $edit_timestamp = time(); + + // BEGIN CONFIRM ENTRY CHECK + if($_POST[insert_fitter] == true){ + if(isset($_POST[new_fitter])){ + $sql = "INSERT INTO ".$prefix."Fitters (fitter_name, fitter_name_tag, fitter_address, fitter_address_two, fitter_city, fitter_state, fitter_state_tag, fitter_zip, fitter_lat, fitter_lng, fitter_phone, fitter_fax, fitter_email, fitter_website, fitter_method, fitter_certifications, fitter_fitbikes, fitter_motioncapture, fitter_brandfriendly, fitter_cost, fitter_info, fitter_directions, fitter_submitted_by, fitter_valid, fitter_portfolio) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$lat', '$lng', '$phone', '$fax', '$email', '$website', '$method', ',$certifications,', ',$fitbikes,', ',$motioncapture,', ',$brandfriendly,', '$cost', '$info', '$directions', $submitted_by, 0, '$portfolio')"; + //echo("fitter entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/add.php?confirmed=yes'); + } elseif(isset($_POST[save_changes]) && $submitted_by != $edited_by) { + $sql = "INSERT INTO ".$prefix."FittersEdits (fitter_id_fk, editor_user_id_fk, edit_timestamp, fitter_name, fitter_name_tag, fitter_address, fitter_address_two, fitter_city, fitter_state, fitter_state_tag, fitter_zip, fitter_lat, fitter_lng, fitter_phone, fitter_fax, fitter_email, fitter_website, fitter_method, fitter_certifications, fitter_fitbikes, fitter_motioncapture, fitter_brandfriendly, fitter_cost, fitter_info, fitter_directions, fitter_submitted_by, fitter_valid, fitter_portfolio) VALUES ('$id', '$edited_by', '$edit_timestamp', '$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$lat', '$lng', '$phone', '$fax', '$email', '$website', '$method', ',$certifications,', ',$fitbikes,', ',$motioncapture,', ',$brandfriendly,', '$cost', '$info', '$directions', $submitted_by, 0, '$portfolio')"; + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/individual.php?fitter_id='.$id.'&wiki_change=edit_success'); + } elseif(isset($_POST[save_changes]) && $submitted_by == $edited_by) { + $sql = "UPDATE ".$prefix."Fitters + SET fitter_name = '".$name."', + fitter_name_tag = '".$name_tag."', + fitter_address = '".$address."', + fitter_address_two = '".$address_two."', + fitter_city = '".$city."', + fitter_state = '".$state."', + fitter_state_tag = '".$state_tag."', + fitter_phone = '".$phone."', + fitter_fax = '".$fax."', + fitter_zip = '".$zip."', + fitter_lat = '".$lat."', + fitter_lng = '".$lng."', + fitter_email = '".$email."', + fitter_website = '".$website."', + fitter_method = '".$method."', + fitter_certifications = ',".$certifications.",', + fitter_fitbikes = ',".$fitbikes.",', + fitter_motioncapture = ',".$motioncapture.",', + fitter_brandfriendly = ',".$brandfriendly.",', + fitter_cost = '".$cost."', + fitter_info = '".$info."', + fitter_directions = '".$directions."', + fitter_portfolio = '".$portfolio."' + WHERE fitter_id = $id"; + //echo $sql; + //exit(); + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/individual.php?fitter_id='.$id.'&wiki_change=update_success'); + } else { + header('Location: '.$site_url.'/individual.php?fitter_id='.$id.'&changes=failure'); + } + } else { + //echo("fitter NOT entered."); + $confirm_fitter = true; + } + // END CONFIRM ENTRY CHECK +} +// END ERROR MESSAGE CHECK +?> diff --git a/site/fitters/wiki_validate.php b/site/fitters/wiki_validate.php new file mode 100644 index 0000000..bc5978c --- /dev/null +++ b/site/fitters/wiki_validate.php @@ -0,0 +1,95 @@ + + + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+

Unvalidated Public Edits

+
+ +
+ + +
Edited on: by ".$editor_user_username.""; if ($boolEditorIsOwner) { echo " (original fitter submitter)"; } else { echo ""; } ?>
+
Info: + 400){ + $phrase = "…"; }else{ + $phrase = ""; } + + echo substr(htmlspecialchars(strip_tags(stripslashes($row[fitter_info]))), 0, 160); + echo $phrase; + ?> +
+ +
+ Location:
+ ">More information +
Validate this edit. Delete this edit. +
+ +
+ +
+ +
+ +
+
+
+ + +
+
+ + +
+ + + diff --git a/site/fitters/wiki_validate_X.php b/site/fitters/wiki_validate_X.php new file mode 100644 index 0000000..2caf6f2 --- /dev/null +++ b/site/fitters/wiki_validate_X.php @@ -0,0 +1,100 @@ + diff --git a/site/fitters/wiki_view.php b/site/fitters/wiki_view.php new file mode 100644 index 0000000..85732e2 --- /dev/null +++ b/site/fitters/wiki_view.php @@ -0,0 +1,227 @@ + + + + + +
+ +
+
+ + +
+ + +
+
+ +
+ +

+ + + +
+ + + +Editor: ".$strEditor.""; ?> +
+ +Edit Date: +
+ +Street Address: +
+Street Address Two: +
+City: +
+State: +
+Zip/Postal Code: +
+Phone: +
+Fax/Alt Phone: +
+E-mail: +
+Website: +
+Portfolio: + + +
+
+ +
+ +
+ +
+Default Tri-Fit Methodology: 0) { + while ($method_list = mysql_fetch_array($fetch)) { + echo ("$method_list[fitter_method_name]"); + } +} else { + echo ("Unanswered"); +} + +?> + + +
+Certifications: + +
+Fit Bikes: + +
+Motion-Capture Systems: + +
+Cost of Fit: + +

+
+ +
+ +
+General Info: +

+Directions to Location(s): + +
+ +
+ +
+
+
+
+ + +
+
+ + +
+ + + diff --git a/site/glist/templates/common/README b/site/glist/templates/common/README new file mode 100644 index 0000000..3d02b09 --- /dev/null +++ b/site/glist/templates/common/README @@ -0,0 +1 @@ +Note! Do not edit these templates. You should use the template editor in the admin, which saves changes in the local directory. This allows you to recover old templates if you accidentally mess up a template, or compare your customized templates to the original template. diff --git a/site/glist/templates/common/globals.txt b/site/glist/templates/common/globals.txt new file mode 100644 index 0000000..c96ca99 --- /dev/null +++ b/site/glist/templates/common/globals.txt @@ -0,0 +1,13 @@ +# This file is auto generated and contains a perl hash of +# your template globals. +# Generated on: Fri Dec 5 10:47:23 2003 + +{ + 'advanced_editor_background' => '#FFFFFF', + 'advanced_editor_font' => 'Verdana,Arial,sans-serif', + 'editor_base_color' => '#c5e1a3', + 'site_title' => 'Gossamer List', + 'site_url' => 'http://www.gossamer-threads.com' +}; + +# vim:syn=perl:ts=4:noet diff --git a/site/glist/templates/common/local/globals.txt b/site/glist/templates/common/local/globals.txt new file mode 100644 index 0000000..5a165bb --- /dev/null +++ b/site/glist/templates/common/local/globals.txt @@ -0,0 +1,15 @@ +# This file is auto generated and contains a perl hash of +# your template globals. +# Generated on: Mon Oct 30 09:48:53 2017 + +{ + 'fetch_lists' => 'sub { + my $tab = $DB->table(\'Lists\'); + $tab->select_options(\'ORDER BY lst_title\'); + + my $lists = $tab->select()->fetchall_hashref; + return { lists_loop => $lists }; +}' +}; + +# vim:syn=perl:ts=4:noet diff --git a/site/glist/templates/common/utils.js b/site/glist/templates/common/utils.js new file mode 100644 index 0000000..51b3d13 --- /dev/null +++ b/site/glist/templates/common/utils.js @@ -0,0 +1,10 @@ +var isSafari = <%if is_safari%>true<%else%>false<%endif%>; +<%if is_safari%>var safariVersion = '<%safari_version%>';<%endif%> +var isIE = <%if is_ie%>true<%else%>false<%endif%>; +<%if is_ie%>var ieVersion = '<%ie_version%>';<%endif%> +var isOpera = <%if is_opera%>true<%else%>false<%endif%>; +<%if is_opera%>var operaVersion = '<%opera_version%>';<%endif%> +var isMozilla = <%if is_mozilla%>true<%else%>false<%endif%>; +<%if is_mozilla%>var mozillaVersion = '<%mozilla_version%>';<%endif%> +var isKonqueror = <%if is_konqueror%>true<%else%>false<%endif%>; +<%if is_konqueror%>var konquerorVersion = '<%konqueror_version%>';<%endif%> diff --git a/site/glist/templates/gossamer/.tplinfo b/site/glist/templates/gossamer/.tplinfo new file mode 100644 index 0000000..9028194 --- /dev/null +++ b/site/glist/templates/gossamer/.tplinfo @@ -0,0 +1,3 @@ +{ + inheritance => '../common' +} diff --git a/site/glist/templates/gossamer/account_validation.eml b/site/glist/templates/gossamer/account_validation.eml new file mode 100644 index 0000000..0fa6538 --- /dev/null +++ b/site/glist/templates/gossamer/account_validation.eml @@ -0,0 +1,18 @@ +To: <%usr_email%> +Subject: <%site_title%> Validation +From: <%site_title%> <<%admin_email%>> + +Hi, <%pro_first_name%> <%pro_last_name%>. Welcome to the <%site_title%>! + +This e-mail has been sent to confirm that this is a valid e-mail +address. You will be unable to login until you have visited the +following URL: + +<%cgi_url%>/glist.cgi?do=user_account_validate&id=GT<%validate_code%>; + +Your real e-mail address will only be used to send you notification of +replies and forum archives (if you request them). Your real e-mail +address will not be visible to other users of the forum. + +Thanks for using <%site_title%> +<%site_url%> diff --git a/site/glist/templates/gossamer/include_style.txt b/site/glist/templates/gossamer/include_style.txt new file mode 100644 index 0000000..be5f20f --- /dev/null +++ b/site/glist/templates/gossamer/include_style.txt @@ -0,0 +1,16 @@ + + diff --git a/site/glist/templates/gossamer/language.txt b/site/glist/templates/gossamer/language.txt new file mode 100644 index 0000000..fe812ef --- /dev/null +++ b/site/glist/templates/gossamer/language.txt @@ -0,0 +1,224 @@ +# This file is the system default language.txt for for +# the 'gossamer' template set. +# Revision: $Id: language.txt,v 1.47 2005/04/06 23:17:53 bao Exp $ + +my $dump = { + 'ADD_ILLEGALVAL' => '', + 'ADD_NOTNULL' => '', + 'ADD_UNIQUE' => '', + 'ADM_CONNECTION_ERROR' => "A database connection could not be established. Please verify and update the information below.", + 'ADM_EML_INVALID' => 'Invalid email address', + 'ADM_INITIAL_EMAIL_ERROR' => 'Invalid Admin Email address', + 'ADM_INITIAL_ERROR' => 'Unable to create def file in \'%s\'.
+Please make sure this directory exists, and is writable by the server.
+If this is the wrong directory, you will need to manually set the directory
+in GList/Config/Data.pm. The specific error was: %s', + 'ADM_INITIAL_LOAD_ERROR' => 'Unable to load GList::SQL: %s', + 'ADM_INITIAL_PREFIX_ERROR' => 'Invalid prefix: \'%s\'. The prefix must consist of only letters, numbers and underscores.', + 'ADM_INITIAL_PWD_ERROR' => 'The password must be at least 4 characters long.', + 'ADM_INITIAL_SUCCESSFUL' => 'The data tables have been set up:
%s
', + 'ADM_INVALID' => 'Invalid data. Please provide the file name as pg=file_name.', + 'ADM_OLDPWD_ERR' => 'Invalid old password.', + 'ADM_PERMISSION_ERR' => 'You do not have permission to access this page.', + 'ADM_PWD_CHANGED' => 'Your password has been successfully changed.', + 'USR_TPL_UPDATED' => 'Mailing header and footer have been updated.', + 'USR_SUB_OVERLIMIT' => 'You cannot subscribe to the list because it has reached its subscription limit. Please contact site administrator.', + 'USR_SUB_INVALID_EMAIL' => 'Invalid email address.', + 'USR_SUB_STOPLIST' => 'Your email address is on the Stop List. Please contact site administrator.', + 'ADM_PWD_ERR' => 'No password entered.', + 'ADM_PWD_INVALID' => 'Invalid new password. The password must be at least 4 characters long.', + 'ADM_PWD_NOT_MATCH' => 'Both new password fields need to match.', + 'USR_SIGNUP_DISABLE' => 'The Signup feature has been disabled.', + 'SYS_DUPLICATE' => 'Duplicate', + 'SYS_INVALID_EMAIL' => 'Invalid email address', + 'USR_SIGNUP_CONFIRM_PASS' => 'Passwords do not match.', + 'USR_SIGNUP_EMAIL_INUSE' => 'Email address \'%s\' is already in use by another account.', + 'USR_SIGNUP_EMAIL_INVALID' => 'Email address \'%s\' does not look like a valid email address.', + 'USR_SIGNUP_USERNAME_INVALID' => 'Username must be at least 4 characters long and consist of only letters and numbers.', + 'USR_SIGNUP_USERNAME_TAKEN' => 'Username has already been taken.', + 'USR_SIGNUP_EMAIL_SUCCESSFUL' => "Thank you for joining Gossamer List. An email has been sent to you with a validation code. Once you receive it, you'll need to click on the link to validate your account.", + 'USR_SIGNUP_SUCCESSFUL' => "Thank you for joining Gossamer List.", + 'USR_SIGNUP_EMAIL_RESTRICTED' => 'Email address \'%s\' is not allowed, please use a different email address.', + 'USR_VALIDATE_FAILED' => 'Your validation code was invalid.', + 'USR_VALIDATE_SUCCESSFUL' => 'Your account has been validated successful.', + 'USR_ADDED' => '%s added successfully.', + 'USR_ADD_ERR' => 'Error: %s', + 'USR_ILLEGALVAL' => '', + 'USR_INVALID' => 'Username must be at least 3 characters long and consist of only letters, numbers, _, ., and - characters.', + 'USR_NOT_FOUND' => '%s not found.', + 'USR_RESULTS' => 'Your search returned %s record(s).', + 'USR_UNIQUE' => '', + 'USR_UPDATED' => 'Account %s has been updated.', + 'USR_VALIDATED' => '%s user(s) was successfully validated.', + 'USR__NOTNULL' => '', + 'DIR_ADDED' => 'Folder %s has been added.', + 'DIR_DELETED' => 'Folder %s has been deleted', + 'DIR_OPEN_ERR' => 'Unable to open directory \'%s\': %s', + 'DIR_PER_ERR' => 'Unable to create new files in directory \'%s\'. Please set appropriate permissions and save again.', + 'DIR_UPDATED' => 'Folder %s has been updated.', + 'FILESIZE_BYTES' => 'B', + 'FILESIZE_KILOBYTES' => 'KB', + 'FILESIZE_MEGABYTES' => 'MB', + 'FIL_CREATE_ERR' => 'Unable to create file %s, reason: %s', + 'FIL_OPEN_ERR' => 'Unable to open file %s, reason: %s', + 'FIL_SAVED' => 'File %s saved.', + 'FIL_SAVED_ERR' => 'Unable to overwrite file: %s (permission denied). Please set permissions properly and save again.', + 'LOG_DEACTIVATE' => 'Your account has been deactivated.', + 'LOG_NOT_EMAIL_VALIDATED' => 'Your email address has not yet been validated. We\'ve sent another verification email. If you do not receive it, please contact the site administrator.', + 'LOG_NOT_ADMIN_VALIDATED' => 'Your account has not yet been validated by administrator.', + 'LOG_ERROR' => 'Invalid username/password', + 'LOG_IN' => 'Enter your username and password to log in to %s', + 'LOG_LOGGED_OFF' => 'You have logged off %s', + 'LOG_REM_ERROR' => 'Please enter your email address', + 'LOG_REM_NOT_FOUND' => 'The email address entered was not found.', + 'LOG_REM_SUCCESS' => 'Your password is being emailed to you.', + 'LOG_SUBSCRIBE_ERROR' => 'You must enter th ID of the list you wish to subscribe to.', + 'LOG_SUBSCRIBE_ERROR2' => 'List \'%s\' does not exist on %s.', + 'LOG_SUBS_FAILURE' => 'There has been an error while processing your request. You may already be subscribed to the mailing list, or your email address may have been entered incorrectly. Please try again.', + 'LOG_UNSUBS_FAILURE' => 'There has been an error while processing your request. This email address does not exist in the list.', + 'LOG_SUBS_SUCCESS' => 'Your request has been processed successfully. Thank you for subscribing to %s.', + 'LOG_UNSUBS_FAILURE' => 'There was an error in processing your request. You may already be subscribed to the mailing list, or your email address may have been entered incorrectly. Please try again.', + 'LOG_UNSUBS_SUCCESS' => 'Your request has been processed successfully. You have been unsubscribed from %s. You may re-subscribe to the list at any time.', + 'LOG_VALIDATED' => 'Your email has been validated.', + 'LOG_VAL_ERROR' => 'Your validation code was invalid.', + 'LOG_VAL_ERROR2' => 'You have already been validated.', + 'LOG_WELCOME' => 'Welcome %s', + 'LOG_UPDATE_REMIND' => 'Welcome to Gossamer List! You should update your account information below before using Gossamer List.', + 'LST_ADD_SUCCESS' => 'List %s has been added successfully.', + 'LST_IMP_NOTNULL' => 'Invalid name and/or email address', + 'LST_INVALID' => 'Invalid input data.', + 'LST_IPT_INVALID' => 'Invalid import data', + 'LST_IPT_LIST_EMPTY' => 'Please select list(s) to add the subscriber to.', + 'LST_IPT_INVALID_EMAIL' => 'Invalid email address', + 'LST_IPT_OVERLIMIT' => 'Over subscriber limit', + 'LST_IPT_ON_STOPLIST' => 'On The StopList', + 'LST_IPT_DUPLICATE_EMAIL' => 'This email address has been taken', + 'LST_IPT_INVALID_FILE' => 'The data import must be a flatfile.', + 'LST_MOD_SUCCESS' => '%s has been updated successfully.', + 'LST_NOT_FOUND' => 'Your search returned 0 results.', + 'LST_RESULTS' => 'Your search returned %s list(s).', + 'LST_BOUNCED_RESULTS' => 'Your search returned %s bounced email(s).', + 'LST_SUB_DELETED' => '%s subscriber(s) was deleted.', + 'LST_SUB_MSG' => 'List \'%s\' has %s subscriber(s).', + 'LST_SUB_RESULTS' => 'Your search returned %s subscriber(s).', + 'ADM_STOPLIST' => 'Your search returned %s email addresses.', + 'ADM_STOPLIST_DELETED' => '%s email(s) was deleted.', + 'ADM_STOPLIST_ERROR' => 'Invalid data!', + 'LST_SUB_VALIDATED' => '%s subscriber(s) was validated.', + 'LST_SUB_UNBOUNCED' => '%s subscriber(s) had their bounced email count reset.', + 'LST_BOUNCED_REMOVED' => '%s subscriber(s) were removed.', + 'LST_SUB_MODIFIED' => 'Email %s was updated.', + 'LST_SUB_ADDED' => 'The following list(s) was updated: ', + 'LST_SUB_STOPLIST' => '%s email is on the Stop List. Please contact site administrator for more information.', + 'LST_UNSUB_BOUNCED' => '%s bounced email(s) deleted successfully.', + 'MLI_BOUNCED_NO_SERVER' => "No POP3 server name specified.", + 'MLI_BOUNCED_NO_USER' => "No POP3 email account username specified.", + 'MLI_BOUNCED_NO_PASS' => "No POP3 email account password specified.", + 'MLI_BOUNCED_EMAILS' => 'You have %s bounced email(s)', + 'MLI_CREATED_SUCCESS' => '%s mailing(s) created and ready to be sent.', + 'MLI_EMPTY' => 'Deleted Items is empty', + 'MLI_INVALID' => 'Please select a mailing', + 'MLI_OVERLIMIT_BOUNCEDS' => 'There are too many bounced emails in the POP account to check from the web, you must run this from shell.', + 'MLI_CHECK_BOUNCED' => 'Checking bounced emails....', + 'MLI_RESULTS' => 'Your search returned %s mailing(s).', + 'MLI_SUCCESS' => '%s mailing(s) sent.', + 'MLI_SUCCESS' => '%s mailing(s) sent.', + 'MLI_SCHEDULE_DELETED' => 'The schedule of mailing %s was deleted', + 'MLI_SCHEDULES_DELETED' => '%s scheduled mailings were deleted', + 'MLI_SCHEDULE_UPDATED' => 'The schedule of mailing ID %s has been updated', + 'MLI_MISSING_ID' => 'Missing mailing ID!', + 'MLI_INVALID_URL' => 'Invalid the text URL!', + 'MLI_SCHEDULE_MISSING_OPT' => 'Missing option for this action!', + 'MLI_SCHEDULE_MISSING_TYPE' => 'Select the schedule type!', + 'MLI_SCHEDULES_CREATED' => '%s mailings were scheduled for mailing', + 'MLI_SCHEDULE_MSG' => 'Set schedule for selected mailings below: ', + 'MSG_ADD_SUCCESS' => 'Added Message: %s', + 'MSG_ATTACH_ADD' => 'Cannot add attachments: %s', + 'MSG_ATTACH_ERR' => 'Please select an attachment file.', + 'MSG_EMPTY' => 'You must enter a message body.', + 'MSG_INVALID' => 'Invalid message ID; you must pass in msg_id=xxx.', + 'MSG_LST_EMPTY' => 'Your system does not have any lists.', + 'MSG_MKDIR_ERR' => 'Cannot create directory: %s', + 'MSG_MLI_ERR' => 'No list has been chosen', + 'MSG_MOD_SUCCESS' => 'Updated message: %s', + 'MSG_MSG_EMPTY' => 'Your message is empty.', + 'MSG_OUTOF_LIMIT' => 'Attachment exceeds size limit.', + 'MSG_RESULTS' => '%s message(s)', + 'MSG_SENDING' => 'Sending...', + 'MSG_SEND_INVALID' => 'You have to select message(s) from the list.', + 'MSG_CHECKING' => 'Checking data...', + 'MSG_EMAIL_SENT' => 'This message was sent to %s.', + 'RPT_CUS_FROM' => 'Total Mailings From %s', + 'RPT_SUMARY' => 'Total Mailings for ', + 'RPT_CUS_TO' => ' to %s', + 'RPT_NOT_FOUND' => '%s not found.', + 'RPT_NO_RESULT' => 'Your search results returned 0 results.', + 'RPT_TITLE' => 'Total Mailings for %s', + 'RPT_TITLE2' => 'Total Mailings', + 'SET_CFG_SUCCESS' => 'Configuration updated successfully.', + 'SET_MISC_ERR' => 'You must specify either an SMTP server or a path to sendmail, not both.', + 'SET_PATH_ERR' => "Please fill out the required fields.", + 'SYS_ADD_INVALID' => 'Invalid data.', + 'SYS_ADD_SUCCESS' => 'Folder %s has been added successfully.', + 'SYS_DELETED' => '%s entries were deleted.', + 'SYS_DELETED2' => '%s entries were deleted, %s records were declined.', + 'SYS_FATAL' => '

A fatal error has occured:

%s

Please enable debugging in setup for more details.

', + 'SYS_FILE_ERR' => 'Cannot open file: %s', + 'SYS_FILE_INVALID' => 'You must pass in the file ID and location.', + 'SYS_FILE_NOT_FOUND' => '%s not found.', + 'SYS_INVALID_ACTION' => 'No such action', + 'SYS_MOD_SUCCESS' => '#%s has been updated successfully.', + 'SYS_MOVED' => '%s message(s) were moved.', + 'SYS_MOVED2' => '%s record(s) were moved, %s records were declined.', + 'SYS_MOVE_ERR' => 'Please choose one or more messages to move by checking the boxes to the right of the message(s).', + 'SYS_PER_DENIED' => 'You do not have permission on this record.', + 'SYS_REGEXFAIL' => 'Please enter a valid email address in the Bounce/Reply to Email field.', + 'SYS_SEARCH_ERROR' => "Please enter at least one search value", + 'SYS_TARGET_ERR' => 'Please choose a folder from the drop-down menu to move the message(s) to.', + 'SYS_DATE_FORMAT_INVALID' => 'Please enter a date in the format: %s.', + 'SYS_DATE_FORMAT' => 'YYYY-MM-DD', + 'SYS_OVERLIMIT_LIST' => 'Your account has reached the maximum number of lists. If you want to increase the limit, please contact site administrator.', + 'SYS_OVERLIMIT_SUBLIST' => 'Your account has reached the maximum number of subscribers permitted per list. If you want to increase the limit, please contact site administrator.', + 'SYS_OVERLIMIT_EMAIL30' => 'Your account has reached the maximum number of emails permitted in the last 30 days. If you want to increase the limit, please contact site administrator.', + 'SYS_USEDBAR_EMAIL30' => "You are using %s% of your %s emails limit.", + 'SYS_USEDBAR_SUBLIST' => "You are using %s% of your %s subscribers limit.", + 'TAB_ADD_COLUMN_ERR' => 'Unable to add column \'%s\'. Reason: %s', + 'TAB_ADD_INDEX_ERR' => 'Unable to add index. Reason: %s', + 'TAB_ADD_SUCCESS' => '%s column was added succesful.', + 'TAB_ADD_UNIQUE_ERR' => 'Unable to add unique index. Reason: %s', + 'TAB_COL_EXISTS' => '
  • Column \'%s\' already exists, please choose another name.
  • ', + 'TAB_COL_FILE_ERR' => '
  • \'%s\' is not writable.
  • \n', + 'TAB_COL_FILE_IN' => '
  • You must specify the save location in the \'File Save Location\' text-box. One per line
  • ', + 'TAB_COL_FILE_TYPE' => '
  • You must specify the column type as either CHAR or VARCHAR in order to use the FILE type.
  • ', + 'TAB_COL_NAME_INVALID' => '
  • Column names must be started with pro_.
  • ', + 'TAB_COL_NAME' => '
  • Column names can only be letters, numbers and underscore (\'_\') characters.
  • ', + 'TAB_COL_NOTNULL' => '
  • Column %s is used with UNIQUE or INDEX but is not defined as NOT NULL.
  • ', + 'TAB_COL_SIZE' => '
  • Max length of CHAR fields is 255 characters.
  • ', + 'TAB_COL_SIZE_INT' => '
  • Max length of INT fields is 0.
  • ', + 'TAB_COL_VALUES' => '
  • You must specify the ENUM values in the \'Column Values\' textarea, one per line.
  • ', + 'TAB_DEL_SUCCESS' => '%s was deleted successfuly.', + 'TAB_MOD_ERR' => 'Column \'%s\' does not exist in the Users table.', + 'TAB_MOD_INVALID' => 'You must enter a column name.', + 'TAB_MOD_PERMIT_ERR' => '\'%s\' are required columns and cannot be deleted.', + 'TAB_MOD_SUCCESS' => '%s was updated successfuly.', + 'TAB_PRIMARY_ERR' => '
  • You cannot add a primary key to an existing table.
  • ', + 'TAB_RESYNC' => 'Database was updated successfuly.', + 'TITLE' => 'Gossamer List', + 'TPL_ADDED' => '%s has been added.', + 'TPL_DELETED' => 'Custom template \'%s\' has been deleted.', + 'TPL_DELETE_ERROR' => 'Template \'%s\' is in use, you cannot delete it.', + 'TPL_DELETE_FAILED' => 'Unable to delete custom template \'%s\': %s', + 'TPL_INVALID' => 'You did not fill out one or more required fields.', + 'TPL_LANG_SAVED' => 'Changes saved successfully.', + 'TPL_LANG_ERROR' => 'Please enter a value for the new language code.', + 'TPL_LANG_INVALID' => 'Prefix is required in language code (FILESIZE_BYTES as an example).', + 'TPL_GLOBAL_SAVED' => 'Changes saved successfully.', + 'TPL_GLOBAL_ERROR' => 'Please enter a value for the new global code.', + 'TPL_LOADED' => 'The system default templates have been loaded.', + 'TPL_RESTORED' => 'System template \'%s\' restored successfully.', + 'TPL_RESTORE_FAILED' => 'Unable to restore system template \'%s\': %s', + 'TPL_UPDATED' => '%s has been updated.', + 'TPL_SELECT_TITLE' => '--- Select a template ---', +}; + +# vim:syn=perl:ts=4:noet diff --git a/site/glist/templates/gossamer/local/language.txt b/site/glist/templates/gossamer/local/language.txt new file mode 100644 index 0000000..344bbfe --- /dev/null +++ b/site/glist/templates/gossamer/local/language.txt @@ -0,0 +1,9 @@ +# This file is auto generated and contains a perl hash of +# your language variables for the 'gossamer' template set. +# Generated on: Wed Jun 4 11:50:48 2008 + +{ + 'ADD_NOTNULL' => '%s cannot be null.' +}; + +# vim:syn=perl:ts=4:noet diff --git a/site/glist/templates/gossamer/remindme.eml b/site/glist/templates/gossamer/remindme.eml new file mode 100644 index 0000000..3d20803 --- /dev/null +++ b/site/glist/templates/gossamer/remindme.eml @@ -0,0 +1,21 @@ +To: <%usr_email%> +Subject: Temporary Password Request. +From: GList Administrator <<%admin_email%>> + +Hi <%usr_name%>, + +The following temporary password has been activated for your account. Please +login using the following information: + +<%cgi_url%>/glist.cgi +Username: <%usr_username%> +Password: <%usr_password%> + +PLEASE READ: This temporary account is only good for a single login. Once you +have logged in, please click on Account and change your password. + +Should you have any problems, please contact the site administrator at <%admin_email%> + +Thanks for using Gossamer List. +<%site_url%> + diff --git a/site/glist/templates/gossamer/subscribe.eml b/site/glist/templates/gossamer/subscribe.eml new file mode 100644 index 0000000..e77be0c --- /dev/null +++ b/site/glist/templates/gossamer/subscribe.eml @@ -0,0 +1,10 @@ +To: <%sub_email%> +Subject: Email to you from <%web_title%>. +From: <%pro_first_name%> <%pro_last_name%> <<%usr_email%>> + +Hi <%if sub_email%><%sub_name%><%else%><%sub_email%><%endif%>, + +The <%sub_email%> address has been subscribed to '<%lst_title%>'. + +To un-subscribe from <%lst_title%>, please use: +<%cgi_url%>/glist.cgi?do=user_rm;email=<%sub_email%>;lid=<%lst_id%> diff --git a/site/glist/templates/gossamer/unsubscribe.eml b/site/glist/templates/gossamer/unsubscribe.eml new file mode 100644 index 0000000..7913f4e --- /dev/null +++ b/site/glist/templates/gossamer/unsubscribe.eml @@ -0,0 +1,7 @@ +To: <%sub_email%> +Subject: Email to you from <%site_title%>. +From: <%pro_first_name%> <%pro_last_name%> <<%usr_email%>> + +Hi <%if sub_email%><%sub_name%><%else%><%sub_email%><%endif%>, + +You recently have unsubscribed the <%sub_email%> address from '<%lst_title%>'. diff --git a/site/glist/templates/gossamer/validation.eml b/site/glist/templates/gossamer/validation.eml new file mode 100644 index 0000000..f9ecd84 --- /dev/null +++ b/site/glist/templates/gossamer/validation.eml @@ -0,0 +1,13 @@ +To: <%sub_email%> +Subject: <%site_title%> validation +From: <%pro_first_name%> <%pro_last_name%> <<%usr_email%>> + +Hi <%sub_name%>, + +Welome to the <%lst_title%> list! +The <%sub_email%> address has been sent to confirm this is a valid e-mail address. You will not be able to receive our e-mails until you have visited the following URL: + +<%cgi_url%>/glist.cgi?do=user_validate&id=GT<%validate_code%> + +To un-subscribe from <%lst_title%>, please use: +<%cgi_url%>/glist.cgi?do=user_rm;email=<%sub_email%>;lid=<%lst_id%> diff --git a/site/glist/templates/safe/include_style.txt b/site/glist/templates/safe/include_style.txt new file mode 100644 index 0000000..90b3f61 --- /dev/null +++ b/site/glist/templates/safe/include_style.txt @@ -0,0 +1,16 @@ + + diff --git a/site/googlemaps/coaches_xml.php b/site/googlemaps/coaches_xml.php new file mode 100644 index 0000000..1580cee --- /dev/null +++ b/site/googlemaps/coaches_xml.php @@ -0,0 +1,52 @@ +','>',$xmlStr); +$xmlStr=str_replace('"','"',$xmlStr); +$xmlStr=str_replace("'",''',$xmlStr); +$xmlStr=str_replace("&",'&',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT * FROM gforum_Coaches WHERE coach_lat <> 0 AND coach_lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> \ No newline at end of file diff --git a/site/googlemaps/fitters_xml.php b/site/googlemaps/fitters_xml.php new file mode 100644 index 0000000..f143bbf --- /dev/null +++ b/site/googlemaps/fitters_xml.php @@ -0,0 +1,52 @@ +','>',$xmlStr); +$xmlStr=str_replace('"','"',$xmlStr); +$xmlStr=str_replace("'",''',$xmlStr); +$xmlStr=str_replace("&",'&',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT * FROM gforum_Fitters WHERE fitter_lat <> 0 AND fitter_lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> \ No newline at end of file diff --git a/site/googlemaps/map_json.php b/site/googlemaps/map_json.php new file mode 100644 index 0000000..16acb85 --- /dev/null +++ b/site/googlemaps/map_json.php @@ -0,0 +1,227 @@ + 'gforum_Coaches', + 'retailer' => 'gforum_Retailers', + 'runshop' => 'gforum_Runshops', + 'race' => 'gforum_Triathlons', + 'fitter' => 'gforum_Fitters', + 'triclub' => 'gforum_Triclubs', + 'roadshow' => 'gforum_Roadshow' +); + + +if ( isset($_POST['action'] )) { + + if ( $_POST["action"] == 'test' ) { + connectdb( 'runshop' ); + + fetchJson( 'runshop' ); + + echo 'testing'; + } + +} + +if (is_ajax()) { + if (isset($_POST["action"]) && !empty($_POST["action"])) { //Checks if action value exists + $action = $_POST["action"]; + switch($action) { //Switch case for value of action + case "test": return_json(); break; + } + } +} + +//Function to check if the request is an AJAX request +function is_ajax() { + + return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && + strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'; + +} + +function return_json(){ + $return = $_POST; + + echo json_encode($return); +} + +function connectdb( $slug = null ) { + + $data = array(); + + global $db_host, $db_user, $db_pass, $db_name; + global $db_tables; + + if ( $slug !== null && $db_tables[$slug] ) { + + $table = $db_tables[$slug]; + + $mysqli = new mysqli( $db_host, $db_user, $db_pass, $db_name); + if ( $mysqli->connect_errno ) { + echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " + . $mysqli->connect_error; + } + + // Select all the rows in the markers table + $query = select_table( $slug ); + + /* Prepared statement, stage 1: prepare */ + if ( ! ($stmt = $mysqli->prepare( $query ) ) ) { + echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error; + return; + } + + /* Execute statement */ + if ( !$stmt->execute() ) { + echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error; + return; + } + + /* Get results */ + if ( !( $result = db_get_result( $stmt ) ) ) { + echo "Getting result set failed: (" . $stmt->errno . ") " . $stmt->error; + return; + } + + $id = $slug . '_id'; + $name = $slug . '_name'; + $lat = $slug . '_lat'; + $lng = $slug . '_lng'; + $info1 = $slug . '_address'; + $info2 = $slug . '_address_two'; + $info3= $slug . '_city'; + $info4 = $slug . '_state'; + $phone = $slug . '_phone'; + $email = $slug . '_email'; + $website = $slug . '_website'; + $details = ''; + + if ( $slug == 'coach') + $details = '/coaches/individual.php?coach_id='; + + if ( $slug == 'retailer') + $details = '/retailers/individual.php?retailer_id='; + + if ( $slug == 'fitter') + $details = '/fitters/individual.php?fitter_id='; + + if ( $slug == 'runshop') + $details = '/runshops/individual.php?runshop_id='; + + if ( $slug == 'triclub') + $details = '/triclubs/individual.php?triclub_id='; + + if ( $slug == 'roadshow' ) { + $details = '/roadshow/individual.php?roadshow_id='; + } + + if ( $slug == 'race' ) { + $name = 'name'; + $lat = 'lat'; + $lng = 'lng'; + $info1 = 'date'; + $info2 = 'swim'; + $info3 = 'bike'; + $info4 = 'run'; + $id = 'uid'; + $phone = 'phone'; + $email = 'email'; + $details = '/individual.php?uid='; + } + + + + // Iterate through the rows, printing XML nodes for each + while ( $row = array_shift( $result ) ) { + + if ( $row[$lat] && $row[$lng] ) { + $data[] = array( + 'category' => $slug, + 'name' => htmlentities ($row[$name]), + 'lat' => $row[$lat], + 'lng' => $row[$lng], + 'info1' => htmlentities ($row[$info1]), + 'info2' => htmlentities ($row[$info2]), + 'info3' => htmlentities ($row[$info3]), + 'info4' => htmlentities ($row[$info4]), + 'phone' => htmlentities ($row[$phone]), + 'email' => htmlentities ($row[$email]), + 'website' => htmlentities ($row[$website]), + 'details' => $details . $row[$id], + ); + } + } + + + /* explicit close recommended */ + $stmt->close(); + $mysqli->close(); + + } else { + + $data = 'no data'; + + } + + $data = json_encode( $data ); + return $data; + +} + +function select_table( $slug = null ) { + + global $db_tables; + $query = ''; + + if ( $slug !== null ) { + + $table = $db_tables[$slug]; + + if ( $table ) { + + if ( $slug == 'race' ) { + $today = date('Y-m-d'); + $query ='SELECT * FROM ' . $table . ' WHERE date >= "' .$today . '"'; + } else { + $query ='SELECT * FROM ' . $table . ' WHERE ' . $slug . '_lat <> 0 AND ' .$slug . '_lng <> 0'; + } + + } + } + return $query; +} + + +function db_get_result( $Statement ) { + $RESULT = array(); + $Statement->store_result(); + for ( $i = 0; $i < $Statement->num_rows; $i++ ) { + $Metadata = $Statement->result_metadata(); + $PARAMS = array(); + while ( $Field = $Metadata->fetch_field() ) { + $PARAMS[] = &$RESULT[ $i ][ $Field->name ]; + } + call_user_func_array( array( $Statement, 'bind_result' ), $PARAMS ); + $Statement->fetch(); + } + return $RESULT; +} + + +?> diff --git a/site/googlemaps/map_json_cache.php b/site/googlemaps/map_json_cache.php new file mode 100644 index 0000000..6648750 --- /dev/null +++ b/site/googlemaps/map_json_cache.php @@ -0,0 +1,49 @@ +'; + +} + +function writeAllJson() { + global $db_tables; + foreach ( $db_tables as $slug => $table ) { + $data = fetchJson( $slug ); + writeJson( $data ); + } + +} + +?> diff --git a/site/googlemaps/openwater_xml.php b/site/googlemaps/openwater_xml.php new file mode 100644 index 0000000..13bdf3b --- /dev/null +++ b/site/googlemaps/openwater_xml.php @@ -0,0 +1,57 @@ +','>',$xmlStr); +$xmlStr=str_replace('"','"',$xmlStr); +$xmlStr=str_replace("'",''',$xmlStr); +$xmlStr=str_replace("&",'&',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT ".$field_lead."name, ".$field_lead."lat, ".$field_lead."lng FROM ".$prefix.$main_table." WHERE ".$field_lead."lat <> 0 AND ".$field_lead."lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> \ No newline at end of file diff --git a/site/googlemaps/phpsqlajax_dbinfo.php b/site/googlemaps/phpsqlajax_dbinfo.php new file mode 100644 index 0000000..fc7df38 --- /dev/null +++ b/site/googlemaps/phpsqlajax_dbinfo.php @@ -0,0 +1,12 @@ + diff --git a/site/googlemaps/phpsqlajax_genxml2.php b/site/googlemaps/phpsqlajax_genxml2.php new file mode 100644 index 0000000..f143bbf --- /dev/null +++ b/site/googlemaps/phpsqlajax_genxml2.php @@ -0,0 +1,52 @@ +','>',$xmlStr); +$xmlStr=str_replace('"','"',$xmlStr); +$xmlStr=str_replace("'",''',$xmlStr); +$xmlStr=str_replace("&",'&',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT * FROM gforum_Fitters WHERE fitter_lat <> 0 AND fitter_lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> \ No newline at end of file diff --git a/site/googlemaps/phpsqlajax_map.htm b/site/googlemaps/phpsqlajax_map.htm new file mode 100644 index 0000000..673f165 --- /dev/null +++ b/site/googlemaps/phpsqlajax_map.htm @@ -0,0 +1,69 @@ + + + + + Google Maps AJAX + mySQL/PHP Example + + + + + +
    + + \ No newline at end of file diff --git a/site/googlemaps/retailers_xml.php b/site/googlemaps/retailers_xml.php new file mode 100644 index 0000000..3380060 --- /dev/null +++ b/site/googlemaps/retailers_xml.php @@ -0,0 +1,52 @@ +','>',$xmlStr); +$xmlStr=str_replace('"','"',$xmlStr); +$xmlStr=str_replace("'",''',$xmlStr); +$xmlStr=str_replace("&",'&',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT * FROM gforum_Retailers WHERE retailer_lat <> 0 AND retailer_lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> \ No newline at end of file diff --git a/site/googlemaps/roadshow_xml.php b/site/googlemaps/roadshow_xml.php new file mode 100644 index 0000000..72bab3b --- /dev/null +++ b/site/googlemaps/roadshow_xml.php @@ -0,0 +1,52 @@ +',' ',$xmlStr); +$xmlStr=str_replace('"',' ',$xmlStr); +$xmlStr=str_replace("'",'',$xmlStr); +$xmlStr=str_replace("&",' and ',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT * FROM gforum_Roadshow WHERE roadshow_lat <> 0 AND roadshow_lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> \ No newline at end of file diff --git a/site/googlemaps/runshops_xml.php b/site/googlemaps/runshops_xml.php new file mode 100644 index 0000000..489b3b4 --- /dev/null +++ b/site/googlemaps/runshops_xml.php @@ -0,0 +1,52 @@ +','>',$xmlStr); +$xmlStr=str_replace('"','"',$xmlStr); +$xmlStr=str_replace("'",''',$xmlStr); +$xmlStr=str_replace("&",'&',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT * FROM gforum_Runshops WHERE runshop_lat <> 0 AND runshop_lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> diff --git a/site/googlemaps/triathlons_xml.php b/site/googlemaps/triathlons_xml.php new file mode 100644 index 0000000..d0f11de --- /dev/null +++ b/site/googlemaps/triathlons_xml.php @@ -0,0 +1,52 @@ +','>',$xmlStr); +$xmlStr=str_replace('"','"',$xmlStr); +$xmlStr=str_replace("'",''',$xmlStr); +$xmlStr=str_replace("&",'&',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT * FROM gforum_Triathlons WHERE lat <> 0 AND lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> \ No newline at end of file diff --git a/site/googlemaps/triclubs_xml.php b/site/googlemaps/triclubs_xml.php new file mode 100644 index 0000000..e21089f --- /dev/null +++ b/site/googlemaps/triclubs_xml.php @@ -0,0 +1,52 @@ +','>',$xmlStr); +$xmlStr=str_replace('"','"',$xmlStr); +$xmlStr=str_replace("'",''',$xmlStr); +$xmlStr=str_replace("&",'&',$xmlStr); +return $xmlStr; +} + +// Opens a connection to a MySQL server +$connection=mysql_connect ($host, $username, $password); +if (!$connection) { + die('Not connected : ' . mysql_error()); +} + +// Set the active MySQL database +$db_selected = mysql_select_db($database, $connection); +if (!$db_selected) { + die ('Can\'t use db : ' . mysql_error()); +} + +// Select all the rows in the markers table +$query = "SELECT * FROM gforum_Triclubs WHERE triclub_lat <> 0 AND triclub_lng <> 0"; +$result = mysql_query($query); +if (!$result) { + die('Invalid query: ' . mysql_error()); +} + +// Start XML file, echo parent node +echo ''.PHP_EOL; +echo ''.PHP_EOL; + +// Iterate through the rows, printing XML nodes for each +while ($row = @mysql_fetch_assoc($result)){ + // ADD TO XML DOCUMENT NODE + echo ''.PHP_EOL; +} + +// End XML file +echo ''; + +?> \ No newline at end of file diff --git a/site/local/include_breadcrumb.php b/site/local/include_breadcrumb.php new file mode 100644 index 0000000..268970a --- /dev/null +++ b/site/local/include_breadcrumb.php @@ -0,0 +1,9 @@ + diff --git a/site/local/include_common_head.php b/site/local/include_common_head.php new file mode 100644 index 0000000..5fb5534 --- /dev/null +++ b/site/local/include_common_head.php @@ -0,0 +1,14 @@ + + + + + +Slowtwitch.com: <? echo $pagetitle; ?> + + + + diff --git a/site/local/include_sidebar.php b/site/local/include_sidebar.php new file mode 100644 index 0000000..cad0a6e --- /dev/null +++ b/site/local/include_sidebar.php @@ -0,0 +1,7 @@ + + +
    + + diff --git a/site/local/index.php b/site/local/index.php new file mode 100644 index 0000000..464abad --- /dev/null +++ b/site/local/index.php @@ -0,0 +1,158 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Local Listings

    +
    This collection of retailers is the most complete and comprehensive listings in North America. The purpose is to introduce triathelets to as much pertinent information as possible.
    +
    + +
    +
    + +
    + +
    +

    Running Stores

    + + ( stores) +
    +
    + +
    +
    + +
    + +
    +

    Bike Shops

    + + ( retailers) +
    +
    + +
    +
    + +
    + +
    +

    Coaches

    + + ( coaches) +
    +
    + +
    +
    + +
    + +
    +

    Fitters

    + + ( fitters) +
    +
    + +
    +
    + +
    + +
    +

    Triathlon Clubs

    + + ( clubs) +
    +
    + +
    +
    + +
    + +
    +

    Race Calendar

    + '".$min_date."'")); + ?> + ( races) +
    +
    + +
    +
    + +
    + +
    +

    Road Show

    + + ( road show stops) +
    +
    + +
    +
    + +
    + +
    +

    Map of Everything

    + (over listings) +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/local/info.php b/site/local/info.php new file mode 100644 index 0000000..a4fff37 --- /dev/null +++ b/site/local/info.php @@ -0,0 +1 @@ + diff --git a/site/local/map.php b/site/local/map.php new file mode 100644 index 0000000..b9dd2ac --- /dev/null +++ b/site/local/map.php @@ -0,0 +1,112 @@ + + + + + + +
    + +
    +
    + + + + +
    + + +
    +
    + +
    +

    Local Listings

    + +
    + Jump to location: + + + or + + + +
    + +
    + Showing results near your location. +
    +
    + +
    + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + Hide Categories ▲ +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/local/mysql.class.php b/site/local/mysql.class.php new file mode 100644 index 0000000..fc69db7 --- /dev/null +++ b/site/local/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/local/settings.php b/site/local/settings.php new file mode 100644 index 0000000..543e79e --- /dev/null +++ b/site/local/settings.php @@ -0,0 +1,164 @@ +db_connect_id) { + echo "


    Error:


    + Connection to database failed
    +








    "; + + exit(); +} + +function geocode($address) { + // Initialize delay in geocode speed + $delay = 0; + $base_url = "https://" . MAPS_HOST . "/maps/api/geocode/xml?&key=" . KEY; + //echo ("Base URL: ".$base_url); + + $status = ""; + $geocode_pending = true; + + while ($geocode_pending) { + $address = str_replace(" ", "+", $address); + $address = str_replace("#", "", $address); + $address = str_replace("\'", "", $address); + $address = str_replace("/", "", $address); + $request_url = $base_url . "address=" . $address . "&sensor=false"; //urlencode($address); + $request_url = mb_convert_encoding($request_url, "UTF-8", "auto"); + //echo ($request_url."
    "); + // Create cUrl object to grab XML content using $request_url + $c = curl_init(); + curl_setopt($c, CURLOPT_URL, $request_url); + curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); + $xmlContent = trim(curl_exec($c)); + curl_close($c); + + // Create SimpleXML object from XML Content + $xml = simplexml_load_string($xmlContent); + + // Print out all of the XML Object + //print header("Content-type: text/plain"); + //print_r($xml); + + $resolution = $xml->result->geometry->location_type; + + $status = $xml->status; + if (strcmp($status, "OK") == 0) { + // Successful geocode + $geocode_pending = false; + $lat = $xml->result->geometry->location->lat; + $lng = $xml->result->geometry->location->lng; + $latlng_array = array($lat, $lng); + return ($latlng_array); + } elseif (strcmp($status, "OVER_QUERY_LIMIT") == 0) { + // failure to geocode + $geocode_pending = false; + $status = "Address " . $address . " failed to geocode. "; + $status = $status . "Received status " . $status . "

    \n"; + return ($status); + } else { + // failure to geocode + $geocode_pending = false; + $status = "Address " . $address . " failed to geocode. "; + $status = $status . "Received status " . $status . "

    \n"; + return ($status); + } + } + +} + +function get_sid() { + if (isset($_SESSION['cookie']) and $_SESSION['cookie']) { + return ''; + } + else { + return '&'.SID; + } +} + +function is_admin() { + if(is_logged_in($user)){ + $username = base64_decode($_SESSION['user']); + if ($username === "Slowman" || $username === "Rappstar" || $username === "rrheisler" || $username === "Ewynn") { + return true; + } else { + return false; + } + } else { + return false; + } +} + +//global function for checking whether user is logged in or not. +//you will notice we will use it everwhere in the script. +function is_logged_in($user) { + global $db,$prefix; + + // return true if we're already logged in + if (isset($_SESSION['user']) && $_SESSION['user'] != '') { + return 1; + } + + // try and get the session id + if (isset($_REQUEST['gforum_1022870964_session'])) { + $session_id = $_REQUEST['gforum_1022870964_session']; + } + else if ($_REQUEST['from'] == 'gforum') { + foreach ($_COOKIE as $key => $value) { + if (preg_match('/gforum.*session/', $key)) { + $session_id = $value; + break; + } + } + if (! isset($session_id)) { + return 0; + } + } + // return false if we have no login info + else { + return 0; + } + + $result = mysql_query("SELECT session_user_id FROM ".$prefix."Session WHERE session_id='$session_id'") or die (mysql_error()); + $row = mysql_fetch_array($result); + $user_id = $row['session_user_id']; + $result = mysql_query("SELECT user_username,user_password,user_last_logon FROM ".$prefix."User WHERE user_id='$user_id'"); + $row = mysql_fetch_array($result); + + $_SESSION['user'] = base64_encode($row['user_username']); + $_SESSION['password'] = base64_encode($row['user_password']); + $_SESSION['user_id'] = base64_encode($user_id); + $_SESSION['session_id'] = $session_id; + $_SESSION['cookie'] = !(isset($_REQUEST['session'])); + + if ($_SESSION['user_id'] == '') { return 0; } + + // we're now logged in, so return 1 + return 1; + + // TODO: SLOWTWITCH CHANGE END +} + +?> diff --git a/site/local/test.php b/site/local/test.php new file mode 100644 index 0000000..c736b3b --- /dev/null +++ b/site/local/test.php @@ -0,0 +1,7 @@ + + + diff --git a/site/local/user_listings.php b/site/local/user_listings.php new file mode 100644 index 0000000..856d429 --- /dev/null +++ b/site/local/user_listings.php @@ -0,0 +1,268 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Your Local Listings

    + + + + +
    This is a list of all local assets registered to your specific forum user ID.
    + +
    + +
    +
    + +
    + +
    +

    Running Stores

    + ".$row['runshops_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } ?> +
    +
    + +
    +
    + +
    + +
    +

    Bike Shops

    + ".$row['retailer_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } ?> +
    +
    + +
    +
    + +
    + +
    +

    Coaches

    + ".$row['coach_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } ?> +
    +
    + +
    +
    + +
    + +
    +

    Fitters

    + ".$row['fitter_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } ?> +
    +
    + +
    +
    + +
    + +
    +

    Triathlon Clubs

    + ".$row['triclub_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } ?> +
    +
    + +
    +
    + +
    + +
    +

    Race Calendar

    + ".$row['name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } ?> +
    +
    + +
    +
    + You must be logged in with cookies enabled.
    "); } ?> + +
    +
    + + +
    +
    + + +

    + + + + + +".$row['coach_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } + + //fitters [Fitters] + $sql = "SELECT fitter_id, fitter_name FROM gforum_Fitters WHERE fitter_submitted_by = ".$useruid; + $results = mysql_query($sql) OR die(mysql_error()); + $i = 0; + while($row = mysql_fetch_array($results)) { + echo ("".$row['fitter_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } + + //runshops [Running Shops] + $sql = "SELECT runshop_id, runshop_name FROM gforum_Runshops WHERE runshop_submitted_by = ".$useruid; + $results = mysql_query($sql) OR die(mysql_error()); + $i = 0; + while($row = mysql_fetch_array($results)) { + echo ("".$row['runshop_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } + + //retailers [Retailers] + $sql = "SELECT retailer_id, retailer_name FROM gforum_Retailers WHERE retailer_submitted_by = ".$useruid; + $results = mysql_query($sql) OR die(mysql_error()); + $i = 0; + while($row = mysql_fetch_array($results)) { + echo ("".$row['retailer_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } + + //triclubs [Tri Clubs] + $sql = "SELECT triclub_id, triclub_name FROM gforum_Triclubs WHERE triclub_submitted_by = ".$useruid; + $results = mysql_query($sql) OR die(mysql_error()); + $i = 0; + while($row = mysql_fetch_array($results)) { + echo ("".$row['triclub_name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } + + //triathlons [Race Calendar] + $sql = "SELECT uid, name FROM gforum_Triathlons WHERE submitted_by = ".$useruid; + $results = mysql_query($sql) OR die(mysql_error()); + $i = 0; + while($row = mysql_fetch_array($results)) { + echo ("".$row['name']."
    "); + $i++; + } + if ($i == 0) { + echo ("none
    "); + } + + + **/ + +?> \ No newline at end of file diff --git a/site/racecalendar/add.php b/site/racecalendar/add.php new file mode 100644 index 0000000..6a9ebce --- /dev/null +++ b/site/racecalendar/add.php @@ -0,0 +1,524 @@ + + +"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); +?> + + + + + + +
    + +
    +
    + + +
    + +
    +
    + +
    + +

    Thank you

    + Thank you. Your race should be added within 24 hours. You will now be redirected back to the add page.

    "; + } else if ($confirm == 1){ ?> +

    Add a Race: Step 2 of 2

    + +

    Add a Race: Step 1 of 2

    + +

    Thank you

    + +

    If you would like to add your triathlon to our website, simply fill out the form below. Be sure to fill out every field. After filling out each field, click submit. You will then be prompted to confirm your race information before the information is sent to us.

    + + + + +
    +

    +
    +
    +
    Race Name
    +
    +
    + +
    +
    +
    +
    Race Date
    +
    +
    + + + +
    +
    +
    +
    Start Time
    +
    +
    + + : + + +
    +
    +
    +
    Race Type
    +
    +
    + +
    +
    +
    +
    Bike Surface
    +
    +
    + >Road + >Offroad + >Gravel +
    +
    +
    +
    Draft Legal (on-road only)
    +
    +
    + >Yes, draft legal. (Leave un-checked for non-drafting) +
    +
    +
    +
    Kids' Race
    +
    +
    + >Yes, this is a kids' race. (Leave un-checked for a "normal" race) +
    +
    +
    +
    Individual entry fee
    +
    +
    + +
    +
    +
    +
    Team entry fee
    +
    +
    + +
    +
    +
    +
    Registration fees disclosed?
    +
    +
    + >Yes, registration fees are included or disclosed at the beginning of registration. (check this box if your entry fee *includes* any & all registration/convenience fees; or if at a minimum all registration fees are disclosed at the beginning of registration). +
    +
    +
    +
    +
    +
    + *************************************************************** +
    + IMPORTANT: Fractional lengths must be entered as a decimal number
    + Examples: 0.25, 1.2, 0.1, 13.2. If your race contains only two legs, simply + leave the third leg blank. +
    +
    +
    +
    1st distance
    +
    +
    + + + +
    +
    +
    +
    2nd distance
    +
    +
    + + + +
    +
    +
    +
    3rd distance
    +
    +
    + + + +
    +
    +
    +
    +
    +
    + ************************************************************** +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Phone Contact
    +
    +
    + +
    +
    +
    +
    E-mail Contact
    +
    +
    + +
    +
    +
    +
    Course Info
    +
    +
    + +
    +
    +
    +
    More Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    Registration link
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    Results
    +
    +
    + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + + + Thank you. Your race should be added within 24 hours. You will now be redirected back to the add page.

    "; + echo ""; + } + + if ($confirm == 1){ + $confirm = 0; + if($type == 1){ $typename = 'Triathlon'; } + if($type == 2){ $typename = 'Duathlon'; } + if($type == 3){ $typename = 'Other'; } + if($type == 4){ $typename = 'Swim-Run'; } + include("include_add_confirm.php"); + } + } ?> + +
    + + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/racecalendar/add_X.php b/site/racecalendar/add_X.php new file mode 100644 index 0000000..abd069e --- /dev/null +++ b/site/racecalendar/add_X.php @@ -0,0 +1,203 @@ +"); +*/ + +//Insert into database +$pass = 'abc123'; +$errmsg = NULL; +//if(strcmp($_POST[password], $pass) == 0){ //Password is good + //Check for blank fields + if ((!$_POST[name])) $errmsg = $errmsg.'Race name, '; + if ($_POST[month]==0) $errmsg = $errmsg.'Race month, '; + if ($_POST[day]==0) $errmsg = $errmsg.'Race day, '; + if ($_POST[type]==0) $errmsg = $errmsg.'Race type, '; + if (!$_POST[indivfee]) $errmsg = $errmsg.'Individual entry fee, '; + if (!$_POST[swim]) $errmsg = $errmsg.'1st event distance, '; + if (!$_POST[bike]) $errmsg = $errmsg.'2nd event distance, '; + //if (!$_POST[run]) $errmsg = $errmsg.'3rd event distance, '; + if (!$_POST[state]) $errmsg = $errmsg.'State, '; + if (!$_POST[city]) $errmsg = $errmsg.'City, '; + if (!$_POST[address]) $errmsg = $errmsg.'Address, '; + if (!$_POST[phone]) $errmsg = $errmsg.'Phone, '; + if (!$_POST[email]) $errmsg = $errmsg.'Email, '; + if (strlen($_POST[courseinfo]) < 4) $errmsg = $errmsg.'Course info, '; + if (strlen($_POST[moreinfo]) < 4) $errmsg = $errmsg.'More info, '; + if (strlen($_POST[directions]) < 4) $errmsg = $errmsg.'Directions, '; + if (!$_POST[website]) $errmsg = $errmsg.'Website, '; + if (isset($errmsg)) { + $errmsg = 'The following fields cannot be left blank: '.$errmsg; + $errmsg = rtrim($errmsg, ', '); + } + if (!is_numeric($_POST[swim])) $errmsg = $errmsg.'1st event distance must be a number ONLY, '; + if (!is_numeric($_POST[bike])) $errmsg = $errmsg.'2nd event distance must be a number ONLY, '; + if ($_POST[run] != "" && !is_numeric($_POST[run])) $errmsg = $errmsg.'3rd event distance must be a number ONLY, '; + if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[name]) ) { + // Contains invalid characters. + $spacer = ""; + if ($errmsg) { $spacer = "
    "; } + $errmsg = $errmsg.$spacer."Please use only letters and numbers in the name"; + } + +//Check for duplicate entry +$sql_Races = "SELECT uid, name, type FROM gforum_Triathlons WHERE valid = 1"; + +$results_Races = mysql_query($sql_Races) or die(mysql_error()); + +$arr_Races = array(""); +$arr_Duplicates = array(""); +$i = 0; +while($row_races = mysql_fetch_array($results_Races)) { + // build an array that we can loop through. We will need to then duplicate this + $arr_Races[$i] = $row_races; + $i++; +} + +$spacer = ""; +if ($errmsg) { $spacer = "
    "; } +$dupmsg = NULL; + +foreach ($arr_Races AS $race) { + if ($dupmsg) { $spacer = "
    "; } + similar_text($race['name'], $_POST['name'], $percent); + if ($percent >= 75 && $race['type'] == $_POST['type']) { + // DEBUG: which USERUID are we processing + $dupmsg = $dupmsg.$spacer."POTENTIAL DUPLICATE: ".$race[uid].". ".$race[name]." (".round($percent,0)."%) Please check this race first and update it instead of adding a new one."; + } +} +//end check for duplicate entry + +if(!$errmsg){ + $name = mysql_real_escape_string(trim($_POST[name])); + $nametag = strtolower(str_replace(" ","", $name)); + if(strlen($nametag) > 12){ //Shorten it + $nametag = substr($nametag, 0, 12); + } + if(file_exists("/srv/www/htdocs/trifind/racepics/$_POST[picname1].img")){ + $picname1 = $_POST[picname1]; }else{ $picname1 = ""; } + if(file_exists("/srv/www/htdocs/trifind/racepics/$_POST[picname2].img")){ + $picname2 = $_POST[picname2]; }else{ $picname2 = ""; } + if(file_exists("/srv/www/htdocs/trifind/racepics/$_POST[picname3].img")){ + $picname3 = $_POST[picname3]; }else{ $picname3 = ""; } + $state = $_POST[state]; + $statetag = strtolower(str_replace(" ","", $state)); + $type = $_POST[type]; + $bike_surface = $_POST[bike_surface]; + $indivfee = mysql_real_escape_string(trim($_POST[indivfee])); + $teamfee = mysql_real_escape_string(trim($_POST[teamfee])); + if ($_POST[registration] != "") { $registration = $_POST[registration]; } else { $registration = 0; } + $swim = $_POST[swim]; + $oneunit = $_POST[oneunit]; + $twounit = $_POST[twounit]; + $threeunit = $_POST[threeunit]; + $onetype = $_POST[onetype]; + $twotype = $_POST[twotype]; + $threetype = $_POST[threetype]; + $bike = $_POST[bike]; + if ($_POST[run] != "") { $run = $_POST[run]; } else { $run = 0; } + if ($_POST[draft_legal] != "") { $draft_legal = $_POST[draft_legal]; } else { $draft_legal = 0; } + if ($_POST[kids_race] != "") { $kids_race = $_POST[kids_race]; } else { $kids_race = 0; } + $city = mysql_real_escape_string(trim($_POST[city])); + $address = mysql_real_escape_string(trim($_POST[address])); + $phone = mysql_real_escape_string(trim($_POST[phone])); + $email = mysql_real_escape_string(trim($_POST[email])); + $courseinfo = nl2br(substr(mysql_real_escape_string(trim($_POST[courseinfo])), 0, 4096)); + $moreinfo = nl2br(substr(mysql_real_escape_string(trim($_POST[moreinfo])), 0, 4096)); + $directions = nl2br(substr(mysql_real_escape_string(trim($_POST[directions])), 0, 4096)); + $register = mysql_real_escape_string(trim($_POST[register])); + $website = mysql_real_escape_string(trim($_POST[website])); + $results = mysql_real_escape_string(trim($_POST[results])); + $sixresults = mysql_real_escape_string(trim($_POST[sixresults])); + $hour = $_POST[hour]; + if($_POST[daypart] == 1){ $hour = $hour + 12; } + $minute = $_POST[minute]; + $year = $_POST[year]; + $month = $_POST[month]; + $day = $_POST[day]; + $date = "$year-$month-$day $hour:$minute:00"; + $submitted_by = $_POST[submitted_by]; + + // BEGIN POINTS CALCULATIONS + + $one_points = 0; + $two_points = 0; + $three_points = 0; + + $arrSwimPoints = array(1 => 17.6, 2 => 0.011, 3 => 0.01, 4 => 11); + $arrBikePoints = array(1 => 1, 2 => 0.00062, 3 => 0.00057, 4=> .62); + $arrRunPoints = array(1 => 4, 2 => 0.0025, 3 => 0.0023, 4 => 2.5); + $arrPaddlePoints = array(1 => 2.6667, 2 => 0.00167, 3 => 0.00153, 4 => 1.6667); + $arrSkiPoints = array(1 => 2.75, 2 => 0.00172, 3 => 0.00158, 4 => 1.72); + $arrMtbPoints = array(1 => 2, 2 => 0.00124, 3 => 0.00114, 4=> 1.24); + $arrPoints = array(1 => $arrSwimPoints, 2=> $arrBikePoints, 3 => $arrRunPoints, 4 => $arrPaddlePoints, 5 => $arrSkiPoints); + + $one_points = $swim*$arrPoints[$onetype][$oneunit]; + $two_points = $bike*$arrPoints[$twotype][$twounit]; + $three_points = $run*$arrPoints[$threetype][$threeunit]; + + $points = $one_points + $two_points + three_points; + + if ($points < 40) { $pointclass = 1; + } elseif ($points >= 40 AND $points < 100) { $pointclass = 2; + } elseif ($points >= 100 AND $points < 180) { $pointclass = 3; + } else { $pointclass = 4; } + + // END POINTS CALCULATION + + if($_POST[confirm1] == 1){ + $sql = "INSERT INTO gforum_Triathlons (onetype, twotype, threetype, oneunit, twounit, threeunit, racetags, pic1, pic2, pic3, valid, name, nametag, date, type, indivfee, teamfee, swim, bike, bike_surface, draft_legal, kids_race, run, state, statetag, city, address, phone, email, courseinfo, moreinfo, directions, register, website, results, sixresults, submitted_by, one_points, two_points, three_points, points, pointclass, registration) VALUES ('$onetype', '$twotype', '$threetype', '$oneunit', '$twounit', '$threeunit', '0', '$picname1', '$picname2', '$picname3', 0, '$name', '$nametag', '$date', $type, '$indivfee', '$teamfee', '$swim', '$bike', $bike_surface, $draft_legal, $kids_race, '$run', '$state', '$statetag', '$city', '$address', '$phone', '$email', '$courseinfo', '$moreinfo', '$directions', '$register', '$website', '$results', '$sixresults', '$submitted_by', $one_points, $two_points, $three_points, $points, $pointclass, $registration)"; + //echo("race entered!"); + //echo($sql); + mysql_query($sql) or die(mysql_error()); + } else { + //echo("race NOT entered."); + $confirm = 1; +} + } +//}else{ + // $errmsg = 'Incorrect key.'; +//} +?> diff --git a/site/racecalendar/ajax.rate.item.php b/site/racecalendar/ajax.rate.item.php new file mode 100644 index 0000000..694db67 --- /dev/null +++ b/site/racecalendar/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/racecalendar/comments_add.php b/site/racecalendar/comments_add.php new file mode 100644 index 0000000..d4d71a1 --- /dev/null +++ b/site/racecalendar/comments_add.php @@ -0,0 +1,31 @@ + + +
    + + + + +
    + +Add A Comment +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    + + +
    diff --git a/site/racecalendar/comments_add_X.php b/site/racecalendar/comments_add_X.php new file mode 100644 index 0000000..a5b1c1b --- /dev/null +++ b/site/racecalendar/comments_add_X.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/site/racecalendar/comments_show.php b/site/racecalendar/comments_show.php new file mode 100644 index 0000000..58e6d86 --- /dev/null +++ b/site/racecalendar/comments_show.php @@ -0,0 +1,52 @@ + + + +" data-num-posts="5" data-width="500">
    */ ?> +" num_posts="5" width="500">**/ ?> + + + + + +
    Comments
    + + + ">
    Reviewed by: ".$commenter_user_username.""; echo " on ".date("F j, Y g:i A", $arrComments[comment_time]); ?>
    + +
    + + + + + + No comments + + + **/ ?> diff --git a/site/racecalendar/comments_validate.php b/site/racecalendar/comments_validate.php new file mode 100644 index 0000000..f758411 --- /dev/null +++ b/site/racecalendar/comments_validate.php @@ -0,0 +1,88 @@ + + + + + + +
    + + +
    + + + + + +

    Unvalidated Comments

    +
    +
    + + + + "> + + + +
    Reviewed by: ".$commenter_user_username.""; echo " on ".date("F j, Y g:i A", $arrComments[comment_time]); echo " about ".$race_name."";?>
    + +
    Validate this comment. Delete this comment.
    +
    + +
    +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/site/racecalendar/comments_validate_X.php b/site/racecalendar/comments_validate_X.php new file mode 100644 index 0000000..d69aa57 --- /dev/null +++ b/site/racecalendar/comments_validate_X.php @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/site/racecalendar/comparison_test.php b/site/racecalendar/comparison_test.php new file mode 100644 index 0000000..1399be2 --- /dev/null +++ b/site/racecalendar/comparison_test.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/site/racecalendar/config.php b/site/racecalendar/config.php new file mode 100755 index 0000000..884c058 --- /dev/null +++ b/site/racecalendar/config.php @@ -0,0 +1,84 @@ += '4.0.4pl1' && strstr($_SERVER["HTTP_USER_AGENT"],'compatible')) { + if (extension_loaded('zlib')) { + ob_end_clean(); + ob_start('ob_gzhandler'); + } +} else if ($phpver > '4.0') { + if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) { + if (extension_loaded('zlib')) { + $do_gzip_compress = TRUE; + ob_start(array('ob_gzhandler',5)); + ob_implicit_flush(0); + header('Content-Encoding: gzip'); + } + } +} +$phpver = explode(".", $phpver); +$phpver = "$phpver[0]$phpver[1]"; +if ($phpver >= 41) { + $PHP_SELF = $_SERVER['PHP_SELF']; +} + +if (!ini_get("register_globals")) { +# import_request_variables('GPC'); +} + +function curPageURL() { + $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); + $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); + $port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : ''; + $url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.$_SERVER["REQUEST_URI"]; + return $url; +} + +$statecount = mysql_num_rows(mysql_query("SELECT * FROM gforum_TriathlonsStates")); + +?> diff --git a/site/racecalendar/delete_X.php b/site/racecalendar/delete_X.php new file mode 100644 index 0000000..890ad4b --- /dev/null +++ b/site/racecalendar/delete_X.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/site/racecalendar/duplicate_X.php b/site/racecalendar/duplicate_X.php new file mode 100644 index 0000000..4f1f3ef --- /dev/null +++ b/site/racecalendar/duplicate_X.php @@ -0,0 +1,100 @@ + + + + + + +
    + + +
    + + + + + +

    Checking For Duplicates…

    +Duplicate check includes a name similarity check, points similarity check (within +/- 5% total), type (triathlon/duathlon) check, and date match check.
    +
    + '2009-01-01'"; + +$results = mysql_query($sql) or die(mysql_error()); + +echo "Processing races…
    "; + +$arr_Races = array(""); +$arr_Duplicates = array(""); +$match_count = 0; +$i = 0; +while($row = mysql_fetch_array($results)) { + // build an array that we can loop through. We will need to then duplicate this + $arr_Races[$i] = $row; + $i++; +} + +$arr_Races_Match = array(""); +$arr_Races_Match = $arr_Races; + +foreach ($arr_Races AS $race) { + // DEBUG: which UIDs are we processing + //echo ("RACE_UID: ".$race[uid].". ".$race[name]."
    "); + + $j = 0; + foreach ($arr_Races_Match AS $match) { + if ($race[uid] != $match[uid]) { + similar_text($race[name], $match[name], $percent); + if ($percent >= 90 && ($race[points]/$match[points]*100) >= 95 && ($race[points]/$match[points]*100) <= 105 && (date("Ymd", $race[date]) == date("Ymd", $match[date])) && (!in_array($match[uid], $arr_Duplicates)) && ($race[type] == $match[type])) { + if ($j == 0) { + echo ("RACE_UID: ".$race[uid].". ".$race[name]." [".$race['points']." Points]
    "); + $j = 1; + array_push($arr_Duplicates, $race[uid]); + } + // DEBUG: which USERUID are we processing + echo ("     POTENTIAL MATCH: ".$match[uid].". ".$match[name]." [".$match['points']." Points] (".round($percent,0)."%)
    "); + $match_count++; + } + } + } +} + +echo "Done processing races.
    "; +echo $match_count." potential duplicates found."; + +//header('Location: https://slowtwitch.com/calendar/?tags_cleared='.$tags_cleared.'.php'); + +?> + +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/site/racecalendar/edit.php b/site/racecalendar/edit.php new file mode 100644 index 0000000..b012fa0 --- /dev/null +++ b/site/racecalendar/edit.php @@ -0,0 +1,448 @@ + + + + + +
    + +"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); + +// Populate with post data or populate with edit return data +if (isset($_POST[edit_return])) { + $row = $_POST; + $row[racedate] = strtotime($row[racedate]); +} else { + $uid = intval(mysql_escape_string($_GET[uid])); + $results = mysql_query("SELECT onetype, twotype, threetype, oneunit, twounit, threeunit, results, pic1, pic2, pic3, uid, name, nametag, type, indivfee, teamfee, swim, bike, run, state, statetag, city, address, phone, email, courseinfo, moreinfo, directions, register, website, submitted_by, valid, UNIX_TIMESTAMP(date) AS racedate, uid AS uid FROM gforum_Triathlons WHERE uid='".$uid."'"); + $row = mysql_fetch_array($results); +} + +if(is_logged_in($user)){ + + //Get user's uid + $username = base64_decode($_SESSION['user']); + $testresults = mysql_query("SELECT user_id FROM ".$prefix."User WHERE user_username='$username'") or die(mysql_error()); + $testrow = mysql_fetch_array($testresults); + $useruid = $testrow[user_id]; + + $race_owner = FALSE; + // is the current user the owner of the race? + if($useruid == $row[submitted_by] && $row[valid] == 1){ + $race_owner = TRUE; + } + + + if(!is_admin() && $race_owner != TRUE) { + header('Location:https://slowtwitch.com/calendar/'); + exit(); + } +} else { + header('Location:https://slowtwitch.com/calendar/'); + exit(); +} + +?> + + + +
    + + + + + +

    Edit a Race

    +

    To edit a race, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes to a NEW race, hit the "CREATE NEW RACE" button. To save changes to the existing race, hit the "SAVE CHANGES" button. You will have a chance to review the data before confirming.

    + +
    +

    + + + +we need to make a delete box similar to within the GLinks article pages. There is some code that exists currently from the current submit form that allows pics to be changed, so take a look at that first. + + + + + + + + + + + +**/?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Pictures:
    Race Name:
    Race Date: + + + + + +
    Start Time: + +: + + +
    Race Type: + +
    Individual entry fee:
    Team entry fee:
    +
    +****************************************************************************** +
    +IMPORTANT: Fractional lengths must be entered as a decimal number
    +Examples: 0.25, 1.2, 0.1, 13.2.�If your race contains only two legs, simply +leave the third leg blank."
    +
    +
    1st distance: + + +
    2nd distance: + + +
    3rd distance: + + +
    +
    +****************************************************************************** +
    State: + + +
    City:
    Address:
    Phone Contact:
    E-mail Contact:
    Course Info:
    More Info:
    Directions:
    Registration link: +(include http:// ) +
    Website: +(include http:// ) +
    + + + +
    +
    + + + +
    + +
    + + + + diff --git a/site/racecalendar/edit_Confirm.php b/site/racecalendar/edit_Confirm.php new file mode 100644 index 0000000..13f54a4 --- /dev/null +++ b/site/racecalendar/edit_Confirm.php @@ -0,0 +1,392 @@ + + + + + +
    + +"Alabama", + 'AK'=>"Alaska", + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'CA'=>"California", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'RI'=>"Rhode Island", + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); + +/** THIS SECTION DISPLAYS THE DATA FOR CONFIRMATION **/ +// Need to interlace this with the edit / upload / copy screen from above. +/**if($deletepics == 1){ +//delete pictures uploaded +$file1 = $picname1; +$file2 = $picname2; +$file3 = $picname3; +$file1 = stripslashes(str_replace("\"", "", $file1)); +$file2 = stripslashes(str_replace("\"", "", $file2)); +$file3 = stripslashes(str_replace("\"", "", $file3)); +$file1 = "/srv/www/htdocs/trifind/racepics/$file1.img"; +$file2 = "/srv/www/htdocs/trifind/racepics/$file2.img"; +$file3 = "/srv/www/htdocs/trifind/racepics/$file3.img"; +if(file_exists($file1)){ unlink($file1); } +if(file_exists($file2)){ unlink($file2); } +if(file_exists($file3)){ unlink($file3); } +}**/ + +$errmsg = NULL; +//Check for blank fields +if ((!$_POST[name])) $errmsg = $errmsg.'Race name, '; + if ($_POST[month]==0) $errmsg = $errmsg.'Race month, '; + if ($_POST[day]==0) $errmsg = $errmsg.'Race day, '; + if ($_POST[type]==0) $errmsg = $errmsg.'Race type, '; + if (!$_POST[indivfee]) $errmsg = $errmsg.'Individual entry fee, '; + if (!$_POST[swim]) $errmsg = $errmsg.'1st event distance, '; + if (!$_POST[bike]) $errmsg = $errmsg.'2nd event distance, '; + //if (!$_POST[run]) $errmsg = $errmsg.'3rd event distance, '; + if (!$_POST[state]) $errmsg = $errmsg.'State, '; + if (!$_POST[city]) $errmsg = $errmsg.'City, '; + if (!$_POST[address]) $errmsg = $errmsg.'Address, '; + if (!$_POST[phone]) $errmsg = $errmsg.'Phone, '; + if (!$_POST[email]) $errmsg = $errmsg.'Email, '; + if (strlen($_POST[courseinfo]) < 4) $errmsg = $errmsg.'Course info, '; + if (strlen($_POST[moreinfo]) < 4) $errmsg = $errmsg.'More info, '; + if (strlen($_POST[directions]) < 4) $errmsg = $errmsg.'Directions, '; + if (!$_POST[website]) $errmsg = $errmsg.'Website, '; + if (isset($errmsg)) { + $errmsg = 'The following fields cannot be left blank: '.$errmsg; + $errmsg = rtrim($errmsg, ', '); + } +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[name]) ) { + // Contains invalid characters. + $errmsg = "Please use only letters and numbers in the name"; +} + $name = trim($_POST[name]); + $nametag = strtolower(str_replace(" ","", $name)); + if(strlen($nametag) > 12){ //Shorten it + $nametag = substr($nametag, 0, 12); + } + $hour = $_POST[hour]; + if($_POST[daypart] == 1){ $hour = $hour + 12; } + $state = $_POST[state]; + $statetag = strtolower(str_replace(" ","", $state)); + $type = $_POST[type]; + $indivfee = trim($_POST[indivfee]); + $teamfee = trim($_POST[teamfee]); + $swim = $_POST[swim]; + $oneunit = $_POST[oneunit]; + $twounit = $_POST[twounit]; + $threeunit = $_POST[threeunit]; + $onetype = $_POST[onetype]; + $twotype = $_POST[twotype]; + $threetype = $_POST[threetype]; + $bike = $_POST[bike]; + $run = $_POST[run]; + $city = trim($_POST[city]); + $address = trim($_POST[address]); + $phone = trim($_POST[phone]); + $email = trim($_POST[email]); + $courseinfo = nl2br(substr(trim($_POST[courseinfo]), 0, 4096)); + $moreinfo = nl2br(substr(trim($_POST[moreinfo]), 0, 4096)); + $directions = nl2br(substr(trim($_POST[directions]), 0, 4096)); + $register = trim($_POST[register]); + $website = trim($_POST[website]); + $results = trim($_POST[results]); + $sixresults = trim($_POST[sixresults]); + $minute = $_POST[minute]; + $year = $_POST[year]; + $month = $_POST[month]; + $day = $_POST[day]; + $date = "$year-$month-$day $hour:$minute:00"; + $uid = $_POST[uid]; + + if($type == 1){ $typename = 'Triathlon'; } + if($type == 2){ $typename = 'Duathlon'; } + if($type == 3){ $typename = 'Other'; } +?> + + + + +
    + + + + + +

    Edit a Race

    +

    +Please confirm your race information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your race information before submitting. +

    + +

    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Date:
    Race Type:
    Course:
    Start:
    Location:
    Address:
    Contact: "; echo stripslashes($email); ?>
    Individual Price:
    Team Price:
    Course Info:
    More:
    Directions:
    Register: Click here"; ?>
    Website: $name"; ?>
    +
    +
    + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +This data will be saved as a NEW RACE. + + + +This data will be saved as a modification to the EXISTING RACE. + + + +

    +    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    + + + \ No newline at end of file diff --git a/site/racecalendar/edit_X.php b/site/racecalendar/edit_X.php new file mode 100644 index 0000000..5b798d8 --- /dev/null +++ b/site/racecalendar/edit_X.php @@ -0,0 +1,271 @@ + 12){ //Shorten it + $nametag = substr($nametag, 0, 12); + } + $state = $_POST[state]; + $statetag = strtolower(str_replace(" ","", $state)); + $type = $_POST[type]; + $indivfee = trim($_POST[indivfee]); + $teamfee = trim($_POST[teamfee]); + $swim = $_POST[swim]; + $oneunit = $_POST[oneunit]; + $twounit = $_POST[twounit]; + $threeunit = $_POST[threeunit]; + $onetype = $_POST[onetype]; + $twotype = $_POST[twotype]; + $threetype = $_POST[threetype]; + $bike = $_POST[bike]; + if ($_POST[run] != "") { $run = $_POST[run]; } else { $run = 0; } + $city = trim($_POST[city]); + $address = trim($_POST[address]); + $phone = trim($_POST[phone]); + $email = trim($_POST[email]); + $courseinfo = nl2br(substr(trim($_POST[courseinfo]), 0, 4096)); + $moreinfo = nl2br(substr(trim($_POST[moreinfo]), 0, 4096)); + $directions = nl2br(substr(trim($_POST[directions]), 0, 4096)); + $register = trim($_POST[register]); + $website = trim($_POST[website]); + $results = trim($_POST[results]); + $sixresults = trim($_POST[sixresults]); + $hour = $_POST[hour]; + //if($_POST[daypart] == 1){ $hour = $hour + 12; } + $minute = $_POST[minute]; + $year = $_POST[year]; + $month = $_POST[month]; + $day = $_POST[day]; + $date = "$year-$month-$day $hour:$minute:00"; + $uid = $_POST[uid]; + $submitted_by = $_POST[submitted_by]; + + $one_points = 0; + $two_points = 0; + $three_points = 0; + + /** $swim_points = array(1 => 17.6, 2 => 0.011, 3 => 0.01, 4 => 11); + $bike_points = array(1 => 1, 2 => 0.00062, 3 => 0.00057, 4=> .62); + $run_points = array(1 => 4, 2 => 0.0025, 3 => 0.0023, 4 => 2.5); + $paddle_points = array(1 => 2.6667, 2 => 0.00167, 3 => 0.00153, 4 => 1.6667); + $ski_points = array(1 => 2.75, 2 => 0.00172, 3 => 0.00158, 4 => 1.72); + $mtb_points = array(1 => 2, 2 => 0.00124, 3 => 0.00114, 4=> 1.24); + points = array(1 => $swim_points, 2=> $bike_points, 3 => $run_points, 4 => $paddle_points, 5 => $ski_points); **/ + + + if ($onetype == 1) { + if ($oneunit == 1) { + $one_points = $swim*17.6; + } elseif ($oneunit == 2) { + $one_points = $swim*0.011; + } elseif ($oneunit == 3) { + $one_points = $swim*0.01; + } elseif ($oneunit == 4) { + $one_points = $swim*11; + } + } elseif ($onetype == 2) { + if ($oneunit == 1) { + $one_points = $swim*1; + } elseif ($oneunit == 2) { + $one_points = $swim*0.00062; + } elseif ($oneunit == 3) { + $one_points = $swim*0.00057; + } elseif ($oneunit == 4) { + $one_points = $swim*0.62; + } + } elseif ($onetype == 3) { + if ($oneunit == 1) { + $one_points = $swim*4; + } elseif ($oneunit == 2) { + $one_points = $swim*0.0025; + } elseif ($oneunit == 3) { + $one_points = $swim*0.0023; + } elseif ($oneunit == 4) { + $one_points = $swim*2.5; + } + } elseif ($onetype == 4) { + if ($oneunit == 1) { + $one_points = $swim*2.67; + } elseif ($oneunit == 2) { + $one_points = $swim*0.00167; + } elseif ($oneunit == 3) { + $one_points = $swim*0.00153; + } elseif ($oneunit == 4) { + $one_points = $swim*1.67; + } + } elseif ($onetype == 5) { + if ($oneunit == 1) { + $one_points = $swim*2.75; + } elseif ($oneunit == 2) { + $one_points = $swim*0.00172; + } elseif ($oneunit == 3) { + $one_points = $swim*0.00158; + } elseif ($oneunit == 4) { + $one_points = $swim*1.72; + } + } + + + if ($twotype == 1) { + if ($twounit == 1) { + $two_points = $bike*17.6; + } elseif ($twounit == 2) { + $two_points = $bike*0.011; + } elseif ($twounit == 3) { + $two_points = $bike*0.01; + } elseif ($twounit == 4) { + $two_points = $bike*11; + } + } elseif ($twotype == 2) { + if ($twounit == 1) { + $two_points = $bike*1; + } elseif ($twounit == 2) { + $two_points = $bike*0.00062; + } elseif ($twounit == 3) { + $two_points = $bike*0.00057; + } elseif ($twounit == 4) { + $two_points = $bike*0.62; + } + } elseif ($twotype == 3) { + if ($twounit == 1) { + $two_points = $bike*4; + } elseif ($twounit == 2) { + $two_points = $bike*0.0025; + } elseif ($twounit == 3) { + $two_points = $bike*0.0023; + } elseif ($twounit == 4) { + $two_points = $bike*2.5; + } + } elseif ($twotype == 4) { + if ($twounit == 1) { + $two_points = $swim*2.67; + } elseif ($twounit == 2) { + $two_points = $swim*0.00167; + } elseif ($twounit == 3) { + $two_points = $swim*0.00153; + } elseif ($twounit == 4) { + $two_points = $swim*1.67; + } + } elseif ($twotype == 5) { + if ($twounit == 1) { + $two_points = $swim*2.75; + } elseif ($twounit == 2) { + $two_points = $swim*0.00172; + } elseif ($twounit == 3) { + $two_points = $swim*0.00158; + } elseif ($twounit == 4) { + $two_points = $swim*1.72; + } + } + + if ($threetype == 1) { + if ($threeunit == 1) { + $three_points = $run*17.6; + } elseif ($threeunit == 2) { + $three_points = $run*0.011; + } elseif ($threeunit == 3) { + $three_points = $run*0.01; + } elseif ($threeunit == 4) { + $three_points = $run*11; + } + } elseif ($threetype == 2) { + if ($threeunit == 1) { + $three_points = $run*1; + } elseif ($threeunit == 2) { + $three_points = $run*0.00062; + } elseif ($threeunit == 3) { + $three_points = $run*0.00057; + } elseif ($threeunit == 4) { + $three_points = $run*0.62; + } + } elseif ($threetype == 3) { + if ($threeunit == 1) { + $three_points = $run*4; + } elseif ($threeunit == 2) { + $three_points = $run*0.0025; + } elseif ($threeunit == 3) { + $three_points = $run*0.0023; + } elseif ($threeunit == 4) { + $three_points = $run*2.5; + } + } elseif ($threetype == 4) { + if ($threeunit == 1) { + $three_points = $swim*2.67; + } elseif ($threeunit == 2) { + $three_points = $swim*0.00167; + } elseif ($threeunit == 3) { + $three_points = $swim*0.00153; + } elseif ($threeunit == 4) { + $three_points = $swim*1.67; + } + } elseif ($threetype == 5) { + if ($threeunit == 1) { + $three_points = $swim*2.75; + } elseif ($threeunit == 2) { + $three_points = $swim*0.00172; + } elseif ($threeunit == 3) { + $three_points = $swim*0.00158; + } elseif ($threeunit == 4) { + $three_points = $swim*1.72; + } + } + + $points = $one_points + $two_points + three_points; + + if ($points < 40) { $pointclass = 1; + } elseif ($points >= 40 AND $points < 100) { $pointclass = 2; + } elseif ($points >= 100 AND $points < 180) { $pointclass = 3; + } else { $pointclass = 4; } + + if(isset($_POST[add_race])){ + $sql = "INSERT INTO gforum_Triathlons(onetype, twotype, threetype, oneunit, twounit, threeunit, racetags, pic1, pic2, pic3, valid, name, nametag, date, type, indivfee, teamfee, swim, bike, run, state, statetag, city, address, phone, email, courseinfo, moreinfo, directions, register, website, results, sixresults, submitted_by, one_points, two_points, three_points, points, pointclass) VALUES('$onetype', '$twotype', '$threetype', '$oneunit', '$twounit', '$threeunit', '0', '$picname1', '$picname2', '$picname3', 0, '$name', '$nametag', '$date', $type, '$indivfee', '$teamfee', $swim, $bike, $run, '$state', '$statetag', '$city', '$address', '$phone', '$email', '$courseinfo', '$moreinfo', '$directions', '$register', '$website', '$results', '$sixresults', '$submitted_by', $one_points, $two_points, $three_points, $points, $pointclass)"; + mysql_query($sql); + //echo($sql); + //$results = mysql_query("SELECT uid FROM gforum_Triathlons WHERE date = '$date' AND name = '$name' LIMIT 1"); + //$row = mysql_fetch_array($results); + //header('Location: https://slowtwitch.com/calendar/individual.php?uid='.$row[uid]); + header('Location: https://slowtwitch.com/calendar/add.php?confirmed=yes'); + } elseif(isset($_POST[save_changes])) { + $sql = "UPDATE gforum_Triathlons + SET onetype = '$onetype', + twotype = '$twotype', + threetype = '$threetype', + oneunit = '$oneunit', + twounit = '$twounit', + threeunit = '$threeunit', + name = '$name', + nametag = '$nametag', + date = '$date', + type = '$type', + indivfee = '$indivfee', + teamfee = '$teamfee', + swim = $swim, + bike = $bike, + run = $run, + state= '$state', + statetag = '$statetag', + city = '$city', + address = '$address', + phone = '$phone', + email = '$email', + courseinfo = '$courseinfo', + moreinfo = '$moreinfo', + directions = '$directions', + register = '$register', + website = '$website', + one_points = $one_points, + two_points = $two_points, + three_points = $three_points, + points = $points, + pointclass = $pointclass + WHERE uid = '$uid'"; + mysql_query($sql); + header('Location: https://slowtwitch.com/calendar/individual.php?uid='.$uid); + } else { + echo "no action taken"; + } +?> diff --git a/site/racecalendar/fixpoints_X.php b/site/racecalendar/fixpoints_X.php new file mode 100644 index 0000000..1ce5e02 --- /dev/null +++ b/site/racecalendar/fixpoints_X.php @@ -0,0 +1,125 @@ + + + + + + +
    + + +
    + + + + + +

    Checking Points…

    +
    + '$min_date'"; + +$results = mysql_query($sql) or die(mysql_error()); + +echo "Processing races…
    "; + +$arr_Races = array(""); +$i = 0; +while($row = mysql_fetch_array($results)) { + $uid = $row[uid]; + $name = $row[name]; + $swim = $row[swim]; + $bike = $row[bike]; + if ($row[run] != "") { $run = $row[run]; } else { $run = 0; } + $oneunit = $row[oneunit]; + $twounit = $row[twounit]; + $threeunit = $row[threeunit]; + $onetype = $row[onetype]; + $twotype = $row[twotype]; + $threetype = $row[threetype]; + + $one_points = 0; + $two_points = 0; + $three_points = 0; + + $arrSwimPoints = array(1 => 17.6, 2 => 0.011, 3 => 0.01, 4 => 11); + $arrBikePoints = array(1 => 1, 2 => 0.00062, 3 => 0.00057, 4=> .62); + $arrRunPoints = array(1 => 4, 2 => 0.0025, 3 => 0.0023, 4 => 2.5); + $arrPaddlePoints = array(1 => 2.6667, 2 => 0.00167, 3 => 0.00153, 4 => 1.6667); + $arrSkiPoints = array(1 => 2.75, 2 => 0.00172, 3 => 0.00158, 4 => 1.72); + $arrMtbPoints = array(1 => 2, 2 => 0.00124, 3 => 0.00114, 4=> 1.24); + $arrPoints = array(1 => $arrSwimPoints, 2=> $arrBikePoints, 3 => $arrRunPoints, 4 => $arrPaddlePoints, 5 => $arrSkiPoints); + + $one_points = $swim*$arrPoints[$onetype][$oneunit]; + $two_points = $bike*$arrPoints[$twotype][$twounit]; + $three_points = $run*$arrPoints[$threetype][$threeunit]; + + $points = $one_points + $two_points + $three_points; + + $points = round($points, 0); + + //echo ("Race ID: $uid - $one_points / $two_points / $three_points -- $points
    "); + + // throw an error on bad units + if ($points > 260) { + echo ("Excessive Points. RACE_UID: ".$uid.". ".$name." [".$points." Points]
    "); + } + + + if ($points != $row[points]) { + if ($points < 40) { $pointclass = 1; + } elseif ($points >= 40 AND $points < 100) { $pointclass = 2; + } elseif ($points >= 100 AND $points < 180) { $pointclass = 3; + } else { $pointclass = 4; } + + $sql_Fix = "UPDATE ".$prefix."Triathlons + SET one_points = ".($one_points).", + two_points = ".($two_points).", + three_points = ".($three_points).", + points = ".($points).", + pointclass = ".($pointclass)." + WHERE uid = ".$uid; + + mysql_query($sql_Fix) OR die(mysql_error()); + echo ("Race #".$uid." updated.
    "); + } +} + +echo "Done processing races.
    "; + +//header('Location: https://slowtwitch.com/calendar/?tags_cleared='.$tags_cleared.'.php'); + +?> + +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/site/racecalendar/include_add_confirm.php b/site/racecalendar/include_add_confirm.php new file mode 100644 index 0000000..c5dcee6 --- /dev/null +++ b/site/racecalendar/include_add_confirm.php @@ -0,0 +1,322 @@ +

    Please confirm your race information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your race information before submitting.

    +

    + +

    + 0){ + fopen("/srv/www/htdocs/trifind/racepics/$nametagmod1.img", "w"); + move_uploaded_file($_FILES['imagefile']['tmp_name'][0],"/srv/www/htdocs/trifind/racepics/$nametagmod1.img"); + print ""; + print "    "; +} + +if($_FILES[imagefile][size][1] > 0){ + fopen("/srv/www/htdocs/trifind/racepics/$nametagmod2.img", "w"); + move_uploaded_file($_FILES['imagefile']['tmp_name'][1],"/srv/www/htdocs/trifind/racepics/$nametagmod2.img"); + print ""; + print "    "; +} + +if($_FILES[imagefile][size][2] > 0){ + fopen("/srv/www/htdocs/trifind/racepics/$nametagmod3.img", "w"); + move_uploaded_file($_FILES['imagefile']['tmp_name'][2],"/srv/www/htdocs/trifind/racepics/$nametagmod3.img"); + print ""; +}?> +

    + +
    +
    +
    Race Name
    +
    +
    + +
    +
    +
    +
    Date
    +
    +
    + +
    +
    +
    +
    Race Type
    +
    +
    + +
    +
    +
    +
    Bike Surface
    +
    +
    + + +
    +
    +
    +
    Drafting rules
    +
    +
    + + +
    +
    +
    +
    Kid's race?
    +
    +
    + + +
    +
    +
    +
    Course
    +
    +
    + + +
    +
    +
    +
    Start
    +
    +
    + +
    +
    +
    +
    Location
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Contact
    +
    +
    + "; echo stripslashes($email); ?> +
    +
    +
    +
    Individual Price
    +
    +
    + +
    +
    +
    +
    Team Price
    +
    +
    + +
    +
    +
    +
    Registration/convenience fees included?
    +
    +
    + + +
    +
    +
    +
    Course Info
    +
    +
    + +
    +
    +
    +
    More
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    Register
    +
    +
    + Click here"; ?> +
    +
    +
    +
    Website
    +
    +
    + $name"; ?> +
    +
    +
    +
    Results
    +
    +
    + $results"; ?> +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    diff --git a/site/racecalendar/include_breadcrumb.php b/site/racecalendar/include_breadcrumb.php new file mode 100644 index 0000000..2b100e9 --- /dev/null +++ b/site/racecalendar/include_breadcrumb.php @@ -0,0 +1,12 @@ + diff --git a/site/racecalendar/include_buttons.php b/site/racecalendar/include_buttons.php new file mode 100644 index 0000000..9b59d33 --- /dev/null +++ b/site/racecalendar/include_buttons.php @@ -0,0 +1,106 @@ + + +
    + + + + + + +
    +
    " style="display: inline;"> + +
    + +
    " style="display: inline;"> + +
    + +
    " style="display: inline;"> + +
    + + + +
    + + +
    + +
    Entered By: $username"); + } +} +?> diff --git a/site/racecalendar/include_common_content.php b/site/racecalendar/include_common_content.php new file mode 100644 index 0000000..1c1d9ea --- /dev/null +++ b/site/racecalendar/include_common_content.php @@ -0,0 +1,37 @@ + + + + + +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    +
    +
    diff --git a/site/racecalendar/include_common_footer.php b/site/racecalendar/include_common_footer.php new file mode 100644 index 0000000..b1915a9 --- /dev/null +++ b/site/racecalendar/include_common_footer.php @@ -0,0 +1 @@ + diff --git a/site/racecalendar/include_common_head.php b/site/racecalendar/include_common_head.php new file mode 100644 index 0000000..ac996bc --- /dev/null +++ b/site/racecalendar/include_common_head.php @@ -0,0 +1,25 @@ + + + + + +Slowtwitch.com Race Calendar: <? echo $pagetitle; ?> + + + + + + + + + + diff --git a/site/racecalendar/include_edit_confirm.php b/site/racecalendar/include_edit_confirm.php new file mode 100644 index 0000000..9035da1 --- /dev/null +++ b/site/racecalendar/include_edit_confirm.php @@ -0,0 +1,309 @@ +
    +

    Please confirm your race information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your race information before submitting.

    +

    + + + +
    +
    +
    Race Name
    +
    +
    + +
    +
    +
    +
    Date
    +
    +
    + +
    +
    +
    +
    Race Type
    +
    +
    + +
    +
    +
    +
    Bike Surface
    +
    +
    + + +
    +
    +
    +
    Drafting rules
    +
    +
    + + +
    +
    +
    +
    Kid's race?
    +
    +
    + + +
    +
    +
    +
    Course
    +
    +
    + + +
    +
    +
    +
    Start
    +
    +
    + +
    +
    +
    +
    Location
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Contact
    +
    +
    + "; echo stripslashes($email); ?> +
    +
    +
    +
    Individual Price
    +
    +
    + +
    +
    +
    +
    Team Price
    +
    +
    + +
    +
    +
    +
    Registration/convenience fees included?
    +
    +
    + + +
    +
    +
    +
    Course Info
    +
    +
    + +
    +
    +
    +
    More
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    Register
    +
    +
    + Click here"; ?> +
    +
    +
    +
    Website
    +
    +
    + $name"; ?> +
    +
    +
    +
    Results
    +
    +
    + $results"; ?> +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This data will be saved as a NEW RACE. + + + + This data will be saved as a modification to the EXISTING RACE. + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    diff --git a/site/racecalendar/include_navigation.php b/site/racecalendar/include_navigation.php new file mode 100644 index 0000000..65f0ad0 --- /dev/null +++ b/site/racecalendar/include_navigation.php @@ -0,0 +1,150 @@ + '2008-01-01'")); +$intcount = mysql_num_rows(mysql_query("SELECT date FROM gforum_Triathlons WHERE points >= 40 AND points < 100 AND valid = 1 AND date > '2008-01-01'")); +$midcount = mysql_num_rows(mysql_query("SELECT date FROM gforum_Triathlons WHERE points >= 100 AND points < 180 AND valid = 1 AND date > '2008-01-01'")); +$ultracount = mysql_num_rows(mysql_query("SELECT date FROM gforum_Triathlons WHERE points > 180 AND valid = 1 AND date > '2008-01-01'"));**/ + +/**$sqlstatelist = "SELECT gts.statetag AS statetag, gts.statelong AS statelong, COUNT(gt.uid) AS numraces +FROM gforum_TriathlonsStates AS gts +LEFT JOIN gforum_Triathlons AS gt +ON gts.statetag = gt.statetag AND gt.date > '2008-01-01' +GROUP BY gts.statetag ORDER BY gts.statetag ASC";**/ + +$sqlregionlist = "SELECT gtr.regionlong AS regionlong, gtr.regionid AS regionid, gtr.regionname AS regionname, gts.statetag AS statetag, gts.statelong AS statelong, COUNT(gt.uid) AS numraces +FROM gforum_TriathlonsStates AS gts +LEFT JOIN gforum_Triathlons AS gt +ON gts.statetag = gt.statetag AND gt.date > '".$min_date."' +LEFT JOIN gforum_TriathlonsRegions AS gtr +ON gts.regionid = gtr.regionid +GROUP BY gtr.regionlong, gts.statetag ORDER BY gtr.regionlong ASC"; + +//$resultstatelist = mysql_query($sqlstatelist); + +$resultregionlist = mysql_query($sqlregionlist); + +?> + +
    +

    Browse Races

    +
    +Sprint ($sprintcount)"); +echo ("

    International ($intcount)"); +echo ("

    Mid-Distance ($midcount)"); +echo ("

    Ultra ($ultracount)
    "); **/ + +$currentregion = ''; +$regioncount = ''; +$tempstring = ''; +$currenttag = ''; +$showhide = ''; +$region_dropdown = ''; +$state_string = ''; +//while($rowstatelist = mysql_fetch_array($resultstatelist)){ +while($rowregionlist = mysql_fetch_array($resultregionlist)){ + $selected_region = ''; + $selected_state = ''; + if ($currentregion != $rowregionlist[regionlong]) { + if ($selected_item == $currentrid) { + $selected_region = ' selected="seleted"'; + } + if ($currentregion != '') { + $region_dropdown .= "$state_string"; + echo ("
    " . $currentregion . " (" . $regioncount . ")+
    "); + echo $tempstring; + echo ('
    '); + } + $currentregion = $rowregionlist[regionlong]; + $currentrid = $rowregionlist[regionid]; + $currenttag = $rowregionlist[regionname]; + $regioncount = 0; + $tempstring = ''; + $state_string = ''; + } + if ($selected_item == $rowregionlist[statetag]) { + $selected_state = ' selected="selected"'; + } + $state_string .= ""; + $tempstring = $tempstring. "$rowregionlist[statelong] ($rowregionlist[numraces])\n"; + $regioncount += $rowregionlist[numraces]; +} + +echo ("
    ".$currentregion." (".$regioncount.")+
    "); +echo $tempstring; +echo ('
    '); +if ( $selected_item == 'top') { $selected_region = ' selected="selected"'; } +$region_dropdown .= ""; +?> + +Alabama ( '2008-01-01'"))); ?>)

    +

    Alaska

    +

    Alberta

    +

    Arizona ( '2008-01-01'"))); ?>)

    +

    Arkansas

    +

    British Columbia

    +

    California

    +

    Colorado

    +

    Connecticut

    +

    Delaware

    +

    Florida

    +

    Georgia

    +

    Hawaii

    +

    Idaho

    +

    Illinois

    +

    Indiana

    +

    Iowa

    +

    Kansas

    +

    Kentucky

    +

    Louisiana

    +

    Maine

    +

    Manitoba

    +

    Maryland

    +

    Massachusetts

    +

    Mississippi

    +

    Missouri

    +

    Michigan

    +

    Minnesota

    +

    Montana

    +

    Nebraska

    +

    Nevada

    +

    New Brunswick

    +

    Newfoundland

    +

    New Hampshire

    +

    New Jersey

    +

    New Mexico

    +

    New York

    +

    North Carolina

    +

    North Dakota

    +

    Nova Scotia

    +

    Ohio

    +

    Oklahoma

    +

    Ontario

    +

    Oregon

    +

    Pennsylvania

    +

    Prince Edward Island

    +

    Quebec

    +

    Rhode Island

    +

    Saskatchewan

    +

    South Carolina

    +

    South Dakota

    +

    Tennessee

    +

    Texas

    +

    Utah

    +

    Virginia

    +

    Vermont

    +

    Washington

    +

    West Virginia

    +

    Wisconsin

    +

    Wyoming

    +**/ +?> + +
    + Search Races   +
    +
    +
    diff --git a/site/racecalendar/include_race.php b/site/racecalendar/include_race.php new file mode 100644 index 0000000..ae3f4d9 --- /dev/null +++ b/site/racecalendar/include_race.php @@ -0,0 +1,58 @@ +
    +
    +

    ">

    +
    + +

    (Avg. rating based on )

    + +
    + Date: +
    + +
    +
    + + Bike Surface:
    + Location:
    + ">More info > +
    +
    diff --git a/site/racecalendar/include_rating.php b/site/racecalendar/include_rating.php new file mode 100644 index 0000000..d56f31b --- /dev/null +++ b/site/racecalendar/include_rating.php @@ -0,0 +1,61 @@ +What do you think of these?  On the rating that shows up on the race info +page, we ought to put in parentheses the number of people whose ratings make +up the average rating per category. + +Should the race get an overall rating?  The only one of these categories +below that is not specifically good or bad is course difficulty.  If you +think challenging is inherently good, then we could give an overall rating. +Me, I do think it's good. But, perhaps we could just get rid of this course +challenge and then everything is really good or bad, and we can give an +overall rating. + + +1. COURSE DENSITY + +dense   O O O O O  sparse + +2. RACE MARSHALS + +none  O O O O O   many + +3. COURSE SAFETY + +felt safe  O O O O O  felt less safe + +4. PRE-/POST-RACE FOOD + +sparse  O O O O O   plentiful/tasty + +5. AID STATIONS + +sparse  O O O O O   plentiful + +6. BATHROOMS + +sparse  O O O O O   plentiful + +7. START TIMES + +late  O O O O O   timely + +8. RESULTS + +late  O O O O O   timely + +9. AWARDS or QUAL SLOTS + +lacking  O O O O O   substantial + +10. LOCAL CULTURE & COMMUNITY + +limited   O O O O O  plentiful + +ONE VOTE PER IP + +LEAVE BLANK TO "N/A" A GIVEN CATEGORY + +At the top -- aggregate rating + +Button at top ("RATE THIS RACE") + +Button at the bottom as well (in case user did not see button at top) \ No newline at end of file diff --git a/site/racecalendar/include_rating_X.php b/site/racecalendar/include_rating_X.php new file mode 100644 index 0000000..e69de29 diff --git a/site/racecalendar/include_share.php b/site/racecalendar/include_share.php new file mode 100644 index 0000000..b006341 --- /dev/null +++ b/site/racecalendar/include_share.php @@ -0,0 +1,6 @@ + + + + + diff --git a/site/racecalendar/include_sidebar.php b/site/racecalendar/include_sidebar.php new file mode 100644 index 0000000..19a2eea --- /dev/null +++ b/site/racecalendar/include_sidebar.php @@ -0,0 +1,14 @@ + + +
    + + + +
    + + diff --git a/site/racecalendar/include_starfunc.php b/site/racecalendar/include_starfunc.php new file mode 100644 index 0000000..ea4dbd4 --- /dev/null +++ b/site/racecalendar/include_starfunc.php @@ -0,0 +1,40 @@ += 0)or($tut_rating == 0)) && ($tut_rating <= 0.50)){ + echo "Not Rated"; + } + if((($tut_rating >= 0.50)or($tut_rating == 0.50)) && ($tut_rating <= .99)){ + echo ""; + } + if((($tut_rating >= 1.00)or($tut_rating == 1.50)) && ($tut_rating <= 1.49)){ + echo ""; + } + if((($tut_rating >= 1.50)or($tut_rating == 1.50)) && ($tut_rating <= 1.99)){ + echo ""; + } + if((($tut_rating >= 2.00)or($tut_rating == 2.00)) && ($tut_rating <= 2.49)){ + echo ""; + } + + if((($tut_rating >= 2.50)or($tut_rating == 2.50)) && ($tut_rating <= 2.99)){ + echo ""; + } + + if((($tut_rating >= 3.00)or($tut_rating == 3.00)) && ($tut_rating <= 3.49)){ + echo ""; + } + + if((($tut_rating >= 3.50)or($tut_rating == 3.50)) && ($tut_rating <= 3.99)){ + echo ""; + } + if((($tut_rating >= 4.00)or($tut_rating == 4.00)) && ($tut_rating <= 4.49)){ + echo ""; + } + if((($tut_rating >= 4.50)or($tut_rating == 4.50)) && ($tut_rating <= 4.99)){ + echo ""; + } + if($tut_rating == 5.0){ + echo ""; + } +} +?> diff --git a/site/racecalendar/include_status.php b/site/racecalendar/include_status.php new file mode 100644 index 0000000..cdde733 --- /dev/null +++ b/site/racecalendar/include_status.php @@ -0,0 +1,17 @@ +
    Admin:"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table." WHERE ".$field_lead."valid = 0 AND ".$field_lead."date >= '".$min_date."'")); + echo("
    Validate Entries (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Edits")); + echo("
    Validate Edits (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Comment WHERE comment_valid = 0")); + echo("
    Validate Comments (".$unvalid_count.")"); + echo("
    Check Point Errors"); + echo("
    Check Duplicates"); + if (!eregi("racetag_X.php", $_SERVER['SCRIPT_NAME'])) { + echo("
    Clear Old Racetags"); + } +} +?> diff --git a/site/racecalendar/index.php b/site/racecalendar/index.php new file mode 100644 index 0000000..5b430a4 --- /dev/null +++ b/site/racecalendar/index.php @@ -0,0 +1,88 @@ + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Races

    + + Add Race + +
    + + +
    +
    +
    + + + '".$min_date."'")); + ?> +

    Welcome to Slowtwitch.com's Independent North American Race Calendar

    +

    races and counting for . We aspire to present the most comprehensive calendar of independent events for North American racers, along with features providing participants a greater sense of community. If you have a suggestion or critique that might allow us to better reach our aspirations, please contact us. Otherwise, enjoy our calendar and its features.

    +

    This calendar is a listing of independent races. That means races that are not Ironman. We love Ironman races and mean no disrespect. Just, go here and you'll find them; it's no secret where they are. If you want races that are not part of the Ironman series, that's what you'll find here.

    +

    Browsing the calendar

    +

    You do not need to log in to do this. You'll find a list of multisport events in your state by using the links on the left. You'll soon be able to sort by region as well. After clicking on your state you'll note that triathlons and duathlons will be listed by date. You can further refine your search by specifying options such as race type, distance, location, and rating.

    +

    Canadian races

    +

    You'll see your provinces mixed in alphabetically with U.S. States. Because triathletes in the U.S. and Canada frequently cross national boundaries to race, we're treating our North American calendar as if these boundaries did not exist. Accordingly, British Columbia and Washington are both in the Northwest region, Ontario and Michigan are both in the Great Lakes region, and so on.

    +

    How contestants build their own personal race calendars

    +

    When you find a race that piques your interest, just click "tag this race." This aggregate events just as you would collect items in an online shopping cart. You'll find these events displayed on your forum user profile or, we should say, you will find them there. We're working on this functionality, including the ability to either display or hide your personal race calendar as you choose. We'll alert you via a forum thread when this functionality is turned on.

    + +

    How to enter a race

    +

    You must be a registered user to add an event to the calendar. There is one common type of registration on Slowtwitch, and if you are registered to post on our Reader Forum you are one of + + who have made a registration, and this means you're able to add races to our calendar. Likewise, if you register to add to our calendar, you're registered to post on the forum.

    +

    If you're not registered, the login prompt is to the left of the page, near the top. The registration process is straightforward, easy, and free. It will require you to receive an email and click on a link to complete your registration. All this should take you only a minute or two. Then...

    +

    1. Click the ADD A RACE button to begin adding to the calendar.

    +

    2. Once you SUBMIT your race, you'll also need to CONFIRM your submission via a link at the bottom of the page. We will check to make sure you are not adding a duplicate race. You may be warned of a potential duplicate. This is just a warning based on name similarities. If you are sure you are not adding a duplicate race, click the SUBMIT RACE button.

    +

    3. Once you successfully add your race, it will not immediately be visible to you. We must validate the addition on our end before anyone can see it. We do this so that spammers won't use the race registration as a way to spam our calendar.

    +

    How to edit published information about a race

    +

    Any registered user can update a race. The changes must be reviewed by an administrator, but the goal is to use the collective knowledge base of our community to keep the calendar up to date.

    +

    How to comment on a race

    +

    Any registered user can comment on a race using the form contained on the individual race page. Your comments are subject to validation by an administrator.

    + +
    + +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/racecalendar/individual.php b/site/racecalendar/individual.php new file mode 100644 index 0000000..2cb6752 --- /dev/null +++ b/site/racecalendar/individual.php @@ -0,0 +1,341 @@ + 0){ + $total = 0; + while($testrow = mysql_fetch_array($test)){ + if($testrow[rating] < 6){ $total = $total + $testrow[rating]; } + if($testrow[rating] == 6){ $num = $num - 1; } + } + $avg = $total / $num; +}else{ + //No ratings + $avg = 0; +} +?> + + + + + + +
    + +
    +
    + + +
    + +
    +
    + +
    +

    Races

    + +
    + +
    + + Back +
    + +
    +
    +

    +
    +
    + Comment +
    +
    +
    + Email:
    + Website: +
    +
    + +

    Commenter: your comments have been submitted and will be validated within 24 hours.

    + + + +

    Editor: your changes have been submitted and will be validated within 24 hours.

    + + + +

    Group Edits: there are group edits waiting to be validated.

    + +
    +
    + +
    + +
    + "; + print "    "; + } + + if(file_exists("/srv/www/htdocs/trifind/racepics/$row[pic2].img")){ + print "\"$row[name]\""; + print "    "; + } + + if(file_exists("/srv/www/htdocs/trifind/racepics/$row[pic3].img")){ + print "\"$row[name]\""; + print "

    "; + } + ?> +
    +
    +

    Race Information

    +
    + Date:
    + Race Type:
    + + Bike Surface:
    + + Drafting rules:?
    + + + Kids Race?
    + + + Course:
    + Start:
    + Location:
    + Address:
    + Contact: $row[email]"; ?>
    + Individual Price:
    + Team Price: +
    + +
    + Date:
    + Course:
    + Location:
    + Address:
    +
    +
    +
    +

    General Information

    +
    + + Registration fees included or disclosed up front?:
    + Course Info: "; ?>
    + More: "; ?>
    + Directions: "; ?>
    + 0){ + $substring = "http"; + if (!is_int(strpos($row[register], $substring))) { + $row[register] = "http://".$row[register]; + } + ?> + Register: Click here"; ?> + + +
    +
    + +
    +
    +
    + +
    + + Map location is based off of a geocode of the addressed entered using Google's Google Maps API. If your address does not geocode properly, you can either update the address (we will attempt to re-geocode after any updates to your entry) or you can use Google's geocoding tool found here: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html to obtain a lat/long for your location and enter that. To use the utility, type in an address that is close to your location and then drag-and-drop the marker to obtain the desired lat/long. If you choose to enter a lat/long, you must check the box on the edit page that says, "override geocode with entered lat/long." + +
    +
    + +
    +

    Who was in this race?

    +
    + + + + 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value' and user_show_racetags=1") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i > 1){ echo ", "; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username]"; + // TODO: SLOWTWITCH EDIT END + } + $i++; + } + ?> +
    +
    +
    + + +

    +
    + = 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i >= 1){ echo "
    "; } + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + } + $i++; + } + if($numcount <= 0){ echo "No users"; } + ?> +
    +
    +
    + +
    + + +
    + + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/racecalendar/logout.php b/site/racecalendar/logout.php new file mode 100644 index 0000000..15d4262 --- /dev/null +++ b/site/racecalendar/logout.php @@ -0,0 +1,7 @@ + diff --git a/site/racecalendar/mod_rewrite.txt b/site/racecalendar/mod_rewrite.txt new file mode 100644 index 0000000..b8d3858 --- /dev/null +++ b/site/racecalendar/mod_rewrite.txt @@ -0,0 +1,15 @@ + + ServerName forum.slowtwitch.com + DocumentRoot /srv/www/htdocs/trifind + Options +FollowSymLinks + RewriteEngine On + RewriteRule ^/racereports/(.*)-([0-9]+).html$ /indivreport.php?report=$2 + RewriteRule ^/racereports/page([0-9]+).html$ /racereports.php?page=$1 + RewriteRule ^/editprofile/(.*).html$ /editprofile.php?username1=$1 + RewriteRule ^/profiles/(.*).html$ /profile.php?username1=$1 + RewriteRule ^/blogs/(.*)-([0-9]+).html$ /indivblog.php?blog=$2 + RewriteRule ^/(.*)/(.*)-([0-9]+).html$ /individual.php?uid=$3 + RewriteRule ^/state/(.*).html$ /statelist.php?state=$1 + RewriteRule ^/blogs/page([0-9]+).html$ /blog.php?page=$1 + RewriteRule ^/(.*).html$ /$1.php + diff --git a/site/racecalendar/mysql.class.php b/site/racecalendar/mysql.class.php new file mode 100755 index 0000000..6d82189 --- /dev/null +++ b/site/racecalendar/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/racecalendar/phpthumb/cache/index.php b/site/racecalendar/phpthumb/cache/index.php new file mode 100644 index 0000000..cee9927 --- /dev/null +++ b/site/racecalendar/phpthumb/cache/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/racecalendar/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg b/site/racecalendar/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg new file mode 100644 index 0000000..af7980d Binary files /dev/null and b/site/racecalendar/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg differ diff --git a/site/racecalendar/phpthumb/cache/source/index.php b/site/racecalendar/phpthumb/cache/source/index.php new file mode 100644 index 0000000..cee9927 --- /dev/null +++ b/site/racecalendar/phpthumb/cache/source/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/racecalendar/phpthumb/demo/index.php b/site/racecalendar/phpthumb/demo/index.php new file mode 100644 index 0000000..266a496 --- /dev/null +++ b/site/racecalendar/phpthumb/demo/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/racecalendar/phpthumb/demo/phpThumb.demo.check.php b/site/racecalendar/phpthumb/demo/phpThumb.demo.check.php new file mode 100644 index 0000000..7dd987c --- /dev/null +++ b/site/racecalendar/phpthumb/demo/phpThumb.demo.check.php @@ -0,0 +1,278 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.check.php // +// James Heinrich // +// // +// Configuration analyzer for phpThumb settings and server // +// settings that may affect phpThumb performance // +// Live demo is at http://phpthumb.sourceforge.net/demo/ // +// // +////////////////////////////////////////////////////////////// + +$ServerInfo['gd_string'] = 'unknown'; +$ServerInfo['gd_numeric'] = 0; +ob_start(); +if (!@include_once('../phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.functions.php")'); +} +if (!@include_once('../phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.class.php")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +if (include_once('../phpThumb.config.php')) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + } +} +$ServerInfo['gd_string'] = phpthumb_functions::gd_version(true); +$ServerInfo['gd_numeric'] = phpthumb_functions::gd_version(false); +$ServerInfo['im_version'] = $phpThumb->ImageMagickVersion(); +$gd_info = gd_info(); + +?> + + + + phpThumb configuration analyzer + + + + +This demo analyzes your settings (phpThumb.config.php and server/PHP) for phpThumb().
    +
    + + + + + + + + + + + + +
    <-- bad to good -->
                                    
    + + phpthumb_functions::SafeURLread('http://phpthumb.sourceforge.net/?latestversion=1', $dummy), + 'this' => $phpThumb->phpthumb_version, +); +foreach ($versions['raw'] as $key => $value) { + eregi('^([0-9\.]+)\-?(([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))?', $value, $matches); + @list($huge, $major, $minor) = @explode('.', @$matches[1]); + @list($year, $month, $day, $hour, $min) = @$matches[3]; + $versions['base'][$key] = $matches[1]; + $versions['huge'][$key] = $huge; + $versions['major'][$key] = $major; + $versions['minor'][$key] = $minor; + $versions['stamp'][$key] = $matches[2]; + $versions['year'][$key] = $year; + $versions['month'][$key] = $month; + $versions['day'][$key] = $day; + $versions['hour'][$key] = $hour; + $versions['min'][$key] = $min; + $versions['date'][$key] = @mktime($hour, $min, 0, $month, $day, $year); +} + +$downloadlatest = 'Download the latest version from http://phpthumb.sourceforge.net'; +echo ''; +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +?> +
    Latest phpThumb version:'.$versions['raw']['latest'].''.$downloadlatest.'
    This phpThumb version:info@silisoftware.com'; +} elseif (($versions['base']['latest'] == $versions['base']['this']) && ($versions['stamp']['this'] > $versions['stamp']['latest'])) { + // new than latest, must be beta version + echo 'lightblue'; + $message = 'You must be using a pre-release beta version. Please report bugs to info@silisoftware.com'; +} elseif ($versions['base']['latest'] == $versions['base']['this']) { + // latest version + echo 'lime'; + $message = 'You are using the latest released version.'; +} elseif ($versions['huge']['latest'].$versions['major']['latest'] == $versions['huge']['this'].$versions['major']['this']) { + echo 'olive'; + $message = 'One (or more) minor version(s) have been released since this version.
    '.$downloadlatest; +} elseif (floatval($versions['huge']['latest'].str_pad($versions['major']['latest'], 2, '0', STR_PAD_LEFT)) < floatval($versions['huge']['this'].str_pad($t_major, 2, '0', STR_PAD_LEFT))) { + echo 'yellow'; + $message = 'One (or more) major version(s) have been released since this version, you really should upgrade.
    '.$downloadlatest; +} else { + echo 'orange'; + $message = 'Fundamental changes have been made since this version.
    '.$downloadlatest; +} +echo '">'.$phpThumb->phpthumb_version; +echo '
    '.$message.'.
    PHP version:'.phpversion(); +echo 'PHP5 is ideal (support for numerous built-in filters which are much faster than my code).
    PHP v4.3.2+ supports ImageSaveAlpha which is required for proper PNG/ICO output.
    ImageRotate requires PHP v4.3.0+ (but buggy before v4.3.3).
    EXIF thumbnail extraction requires PHP v4.2.0+.
    Most things will work back to PHP v4.1.0, and mostly (perhaps buggy) back to v4.0.6, but no guarantees for any version older than that.
    GD version:'.@$ServerInfo['gd_string']; +echo 'GD2-bundled version is ideal.
    GD2 (non-bundled) is second choice, but there are a number of bugs in the non-bundled version.
    GD1 will also (mostly) work, at much-reduced image quality and several features disabled. phpThumb can perform basic resizing with ImageMagick only, even if GD is not available.
    ImageMagick version:'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a'); +echo 'ImageMagick is faster than GD, can process larger images without PHP memory_limit issues, can resize animated GIFs. phpThumb can perform basic resizing with ImageMagick only, even if GD is not available.
    GD features:'; +$GDfeatures['red'] = array('JPG Support', 'PNG Support'); +$GDfeatures['orange'] = array('GIF Read Support', 'GIF Create Support', 'FreeType Support'); +foreach ($GDfeatures as $missingcolor => $features) { + foreach ($features as $dummy => $feature) { + echo '
    '.htmlentities($feature).'
    '; + } +} +echo '
    PNG support is required for watermarks, overlays, calls to ImageMagick and other internal operations.
    JPG support is obviously quite useful, but ImageMagick can substitute
    GIF read support can be bypassed with ImageMagick and/or internal GIF routines.
    GIF create support can be bypassed with ImageMagick (if no filters are applied)
    FreeType support is needed for TTF overlays.
    GD extension "EXIF"'.(extension_loaded('exif') ? 'TRUE' : 'FALSE'); +echo 'EXIF extension required for auto-rotate images. Also required to extract EXIF thumbnail to use as source if source image is too large for PHP memory_limit and ImageMagick is unavailable.
    magic_quotes_runtime:'.$phpThumb->phpThumbDebugVarDump((bool) @get_magic_quotes_runtime()); +echo 'This setting is evil. Turn it off.
    magic_quotes_gpc:'.$phpThumb->phpThumbDebugVarDump((bool) @get_magic_quotes_gpc()); +echo 'This setting is bad. Turn it off, if possible. phpThumb will attempt to work around it if it is enabled
    safe_mode:'.$phpThumb->phpThumbDebugVarDump((bool) @ini_get('safe_mode')); +echo 'Best if off. Calls to ImageMagick will be disabled if on (limiting max image resolution, no animated GIF resize).
    allow_url_fopen:'.$phpThumb->phpThumbDebugVarDump((bool) @ini_get('allow_url_fopen')); +echo 'Best if on. HTTP source images will be unavailable if disabled and CURL is unavailable.
    curl_version:'.(function_exists('curl_version') ? curl_version() : 'n/a') ; +echo 'Best if available. HTTP source images will be unavailable if CURL unavailable and allow_url_fopen is also disabled.
    disable_functions:'.eregi_replace('(shell_exec|system|passthru|exec)(,|$)', '\\1(\\2)', $disable_functions); +echo 'Best if nothing disabled. Calls to ImageMagick will be prevented if exec+system+shell_exec+passthru are disabled.
    memory_limit:'.($memory_limit ? $memory_limit : 'unlimited'); +echo 'The higher the better. Divide by 5 to get maximum megapixels of source image that can be thumbnailed (without ImageMagick).'.($memory_limit ? ' Your setting ('.$memory_limit.') allows images up to approximately '.number_format($memory_limit / 5, 1).' megapixels' : '').'
    + + \ No newline at end of file diff --git a/site/racecalendar/phpthumb/demo/phpThumb.demo.demo.php b/site/racecalendar/phpthumb/demo/phpThumb.demo.demo.php new file mode 100644 index 0000000..e8a70d2 --- /dev/null +++ b/site/racecalendar/phpthumb/demo/phpThumb.demo.demo.php @@ -0,0 +1,249 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.demo.php // +// James Heinrich // +// // +// Demo showing a wide variety of parameters that can be // +// passed to phpThumb.php // +// Live demo is at http://phpthumb.sourceforge.net/demo/ // +// // +////////////////////////////////////////////////////////////// +$ServerInfo['gd_string'] = 'unknown'; +$ServerInfo['gd_numeric'] = 0; +ob_start(); +if (!@include_once('../phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.functions.php")'); +} +if (!@include_once('../phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.class.php")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +if (include_once('../phpThumb.config.php')) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + } +} +$ServerInfo['phpthumb_version'] = $phpThumb->phpthumb_version; +$ServerInfo['im_version'] = $phpThumb->ImageMagickVersion();; +$ServerInfo['gd_string'] = phpthumb_functions::gd_version(true); +$ServerInfo['gd_numeric'] = phpthumb_functions::gd_version(false); +unset($phpThumb); +?> + + + + Demo of phpThumb() - thumbnails created by PHP using GD and/or ImageMagick + + + + +This is a demo of phpThumb() (current version: v)
    +
    +Note: this server is working on GD "= 2) { + echo ', so images should be of optimal quality.'; +} else { + echo ', so images (especially watermarks) do not look as good as they would on GD v2.'; +} +?>
    + +
    +phpThumb.demo.showpic.php demo here
    +Difference between GD1 and GD2
    +
    +
    + The following images have the textured background behind them to illustrate transparency effects. + Note that some browsers, notably Internet Explorer, are incapable of displaying alpha-channel PNGs. + See my page on the PNG transparency problem. + Other modern browsers such as Mozilla/Firefox display alpha-transparent PNGs with no problems. +

    + + + +PNG transparency problem in Internet Explorer'; +$only_gd = '
    (only works with GD (any version), this server is '.($ServerInfo['gd_string'] ? 'running GD "'.$ServerInfo['gd_string'].'" so it will' : 'not running any recognized version of GD so it will not').' work)'; +$only_gd2 = '
    (only works with GD v2.0+, this server is running GD "'.($ServerInfo['gd_string'] ? $ServerInfo['gd_string'] : 'n/a').'" so it '.(($ServerInfo['gd_numeric'] >= 2) ? 'will' : 'will not').' work)'; +$only_php42 = '
    (only works with PHP v4.2.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.2.0', '>=') ? 'will' : 'will not').' work)'; +$only_php43 = '
    (only works with PHP v4.3.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.3.0', '>=') ? 'will' : 'will not').' work)'; +$only_php432 = '
    (only works with PHP v4.3.2+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.3.2', '>=') ? 'will' : 'will not').' work (correctly))'; +$only_php500 = '
    (only works with PHP v5.0.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '5.0.0', '>=') ? 'will' : 'will not').' work (correctly))'; +$php5_or_IM = '
    (only works with PHP v5.0.0+ or ImageMagick, this server is running PHP v'.phpversion().' and "'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a').'" so it '.(($ServerInfo['im_version'] && version_compare(phpversion(), '5.0.0', '>=')) ? 'will' : 'will not').' work (correctly))'; +$only_exif = '
    (only works when the EXIF extension is loaded, so on this server it '.(extension_loaded('exif') ? 'will' : 'will not').' work)'; +$only_im = '
    (requires ImageMagick, this server is running "'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a').'" so it '.($ServerInfo['im_version'] ? 'will' : 'will not').' work)'; + +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200'), 'description' => 'width=200px'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&q=10'), 'description' => 'width=200px, JPEGquality=10%'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['watermark'].'&w=400&aoe=1&bg=ffffff'), 'description' => 'width=400px, AllowOutputEnlargement enabled'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=250&sx=600&sy=5&sw=100&sh=100&aoe=1'), 'description' => 'section from (600x5 - 700x105) cropped and enlarged by 250%, AllowOutputEnlargement enabled'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.urlencode('http://silisoftware.com/images/SiliSoft.gif').'&w=100'), 'description' => 'HTTP source image'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&fltr[]=wmi|'.$img['watermark'].'|BL'), 'description' => 'width=200px, watermark (bottom-left, 75% opacity)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&fltr[]=wmi|'.$img['watermark'].'|*|25'), 'description' => 'width=200px, watermark (tiled, 25% opacity)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=png', $phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=gif', $phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=jpeg'), 'description' => 'source image (GIF) transpancy with transparent output (PNG, GIF) vs. specified background color (JPEG)'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['anigif'], $phpThumbBase.'src='.$img['anigif'].'&w=25&f=gif', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=png', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=ico', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=bmp', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=jpeg'), 'description' => 'resize animated GIF. Notice how output format affects the result: GIF is animated and transparent; PNG and ICO are tranparent but not animated (first frame is rendered as a still image); JPEG and BMP are neither transparent nor animated. Any filters will disable animated resizing (may be fixed in a future version).
    '.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['alpha'].'&f=png', $phpThumbBase.'src='.$img['alpha'].'&f=ico', $phpThumbBase.'src='.$img['alpha'].'&f=gif', $phpThumbBase.'src='.$img['alpha'].'&f=jpeg'), 'description' => 'PNG alpha transparency test, using test image from the PNG transparency test page'.$only_php432); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=usm|80|0.5|3'), 'description' => 'normal vs. unsharp masking at default settings'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=blur|1', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=blur|5'), 'description' => 'normal vs. blur at default (1) and heavy (5)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gblr', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sblr'), 'description' => 'normal vs. gaussian blur vs. selective blur'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=L&bg=0000FF&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['landscape'].'&w=100&h=100&far=T&bg=FF0000&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=C&bg=0000FF&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['landscape'].'&w=100&h=100&far=B&bg=FF0000&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=R&bg=0000FF&f=png&fltr[]=bord|1'), 'description' => 'Forced Aspect Ratio, colored background, PNG output'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=150&ar=L', $phpThumbBase.'src='.$img['landscape'].'&w=150&ar=L'), 'description' => 'auto-rotate counter-clockwise to landscape from portrait & lanscape'.$only_php42.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&hp=100&wl=200', $phpThumbBase.'src='.$img['landscape'].'&hp=100&wl=200'), 'description' => 'auto-selection of W and H based on source image orientation'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['unrotated'].'&w=150&h=150', $phpThumbBase.'src='.$img['unrotated'].'&w=150&h=150&ar=x'), 'description' => 'original image vs. auto-rotated based on EXIF data'.$only_php42.$only_exif.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&ra=30&bg=0000FF', $phpThumbBase.'src='.$img['landscape'].'&w=200&ra=30&f=png', $phpThumbBase.'src='.$img['alpha'].'&ra=30&f=png', $phpThumbBase.'src='.$img['alpha'].'&ra=30&f=gif'), 'description' => 'Rotated 30° (counter-clockwise), width=200px, blue background vs. transparent background vs. rotated image with pre-existing alpha'.$only_php42.$only_gd); +//$Examples[] = array('getstrings' => array($phpThumbBase.'src=images/1-bit.gif&ra=30&f=png', $phpThumbBase.'src=images/4-bit.gif&ra=30&f=png', $phpThumbBase.'src=images/8-bit.gif&ra=30&f=png'), 'description' => '2-color, 16-color, 256-color transparent GIFs'.$only_php42.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&h=300&far=1&bg=CCCCCC', $phpThumbBase.'src='.$img['landscape'].'&w=200&h=300&iar=1'), 'description' => 'Normal resize behavior (left) vs. Forced non-proportional resize (right)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=150&h=150&zc=1', $phpThumbBase.'src='.$img['portrait'].'&w=150&h=150&zc=1'), 'description' => 'Zoom-Crop'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bord|2|20|10|009900&f=png'), 'description' => '2px border, curved border corners (20px horizontal radius, 10px vertical radius)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ric|50|20&f=png'), 'description' => 'curved border corners (20px vertical radius, 50px horizontal radius)
    '.$png_alpha.$only_gd2.$only_php432); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sat|75', $phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sat|-100'), 'description' => 'saturation -75% vs. normal vs. -100%'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ds|75', $phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ds|-100'), 'description' => 'desaturated 75% vs. normal vs. -100%'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=clr|25|00FF00'), 'description' => 'colorized 25% to green (#00FF00)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gray', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sep'), 'description' => 'grayscale vs. sepia'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask3'].'&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask1'].'&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask2'].'&f=jpeg&bg=9900CC&q=100'), 'description' => 'Assorted alpha masks (seen below) applied
    '.$png_alpha.$only_php432.'
    JPEG/GIF output is flattened to "bg" background color'.$only_gd2.'
    '); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=drop|5|10|000000|225&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask3'].'&fltr[]=drop|5|10|000000|225&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=drop|5|10|000000|225&fltr[]=elip&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&fltr[]=drop|5|10|000000|225&f=png'), 'description' => 'Drop shadow. Note how the order in which filters are applied matters.'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&f=jpeg&bg=00FFFF'), 'description' => 'Elipse
    '.$png_alpha.$only_php432.'
    JPEG/GIF output is flattened to "bg" background color'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|x', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|y', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|xy'), 'description' => 'flipped on X, Y and X+Y axes'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bvl|10|FFFFFF|000000', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bvl|10|000000|FFFFFF'), 'description' => '10px bevel edge filter'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=fram|3|2|CCCCCC|FFFFFF|000000', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=fram|3|2|CC9966|333333|CCCCCC'), 'description' => '3+2px frame filter'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=neg'), 'description' => 'Negative filter (inverted color)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=th|105', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask1'].'&fltr[]=th|105&f=png'), 'description' => 'Threshold filter; showing preserved alpha channel'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=150', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=rcd|16|1', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=rcd|16|0', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=gray&fltr[]=rcd|8|1'), 'description' => 'ReduceColorDepth filter; original vs. 16-color dither vs. 16-color nodither vs. 4-gray dither'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['levels'].'&w=200', $phpThumbBase.'src='.$img['levels'].'&w=200&fltr[]=lvl'), 'description' => 'original vs. Levels filter (default settings)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=200', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=wb', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=wb&fltr[]=lvl'), 'description' => 'original vs. White Balance vs. White Balance + Levels'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=hist|rgb', $phpThumbBase.'src='.$img['levels'].'&w=200&fltr[]=hist|*'), 'description' => 'histograms of RGB vs. grayscale'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=edge'), 'description' => 'Edge Detect filter'.$php5_or_IM.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=emb'), 'description' => 'Emboss filter'.$php5_or_IM.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=mean'), 'description' => 'Mean Removal filter'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=smth'), 'description' => 'Smooth filter'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gam|0.6', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gam|1.6'), 'description' => 'Gamma corrected to 0.6 vs. 1.6'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=brit|50', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=brit|-50'), 'description' => 'Brightness filter (original vs. +50 vs. -50)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=cont|50', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=cont|-50'), 'description' => 'Contrast filter (original vs. +50 vs. -50)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=over|'.$img['frame1'].'|0', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=over|'.$img['frame2'].'|1'), 'description' => 'Overlay vs. Underlay

    Original over/under images:
    '.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|phpThumb|18|C|FF0000|loki.ttf|100|5|20&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|copyright+'.date('Y').'|3|BR|00FFFF||50&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|copyright+'.date('Y').'%0AphpThumb()|3|L|00FFFF&f=png'), 'description' => 'Text overlay, TTF and built-in fonts, multiple lines, metacharacters (height, width)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|thumbnail+=+^Xx^Y|3|BR|00FFFF||50&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|click%0Ahere%0A^FkkB|10|L|FF00FF|arial.ttf|100|0||333399|50|y&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|resized:+^Xx^Y+to+^xx^y|10|B|FFFFFF|arial.ttf|100|0||000000|100|x&f=png'), 'description' => 'metacharacters (height, width), background color, background extend'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'new=FF0000&w=100&h=50&fltr[]=bvl|10&fltr[]=wmt|hello|14|C|00FFFF|arial.ttf&f=png', $phpThumbBase.'new=FF0000|25&w=150&h=50&fltr[]=bvl|10&fltr[]=wmt|25%+opaque|14|C|0066FF|arial.ttf&f=png'), 'description' => 'Image created with "new", red background, bevel, TTF text'.$only_gd); + +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['bmp'].'&w=200'), 'description' => 'BMP source, width=200px'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['tiff'], $phpThumbBase.'src='.$img['tiff'].'&w=200&aoe=1'), 'description' => 'TIFF source, width=200px'.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['wmf'].'&w=200'), 'description' => 'WMF source, width=200px'.$only_im); +//$Examples[] = array('getstrings' => array(''), 'description' => ''); + +foreach ($Examples as $key => $ExamplesArray) { + echo '#'.$key.''; + echo '
    '; + foreach ($ExamplesArray['getstrings'] as $dummy => $GETstring) { + echo ''; + echo ''; + echo ' '; + } + echo '
    '; + echo '<img src="'.implode('">'."\n".'<img src="', $ExamplesArray['getstrings']).'">'; + echo $ExamplesArray['description'].'
    '; + echo '


    '; +} + +echo '#pathinfo'; +echo '
    '; +echo ''; +echo '
    '; +echo '<img src="../phpThumb.php/fltr[]=sep;200x200;'.$img['portrait'].'">'; +echo 'PATH_INFO example
    '; +echo '


    '; + +?> + + +
    + + + + + + + + + + + + + + + + +
    + Illustration of potential difference between GD1.x and GD2.x
    + In most cases the thumbnails produced by phpThumb() on GD v1.x are perfectly + acceptable, but in some cases it may look ugly. Diagonal lines and reducing a + very large source image increase chance for bad results (the house/sky picture + has both problems). Here are three static examples: +
    GD v2.0.15kayak.jpg generated with phpThumb() on GD v2.0.15bottle.jpg generated with phpThumb() on GD v2.0.15sky.jpg generated with phpThumb() on GD v2.0.15
    GD v1.6.2kayak.jpg generated with phpThumb() on GD v1.6.2bottle.jpg generated with phpThumb() on GD v1.6.2sky.jpg generated with phpThumb() on GD v1.6.2

    +
    +
    + +Demo of phpThumb.demo.showpic.php
    +
    +Small picture (400x300), window opened at wrong size (640x480):
    + +
    +
    +Big picture (2272x1704), window opened at wrong size (640x480):
    + +
    +
    +
    + +'; +foreach ($img as $key => $value) { + echo '
  • '.basename($value).'
  • '; +} +echo '
    '; + +?> + + \ No newline at end of file diff --git a/site/racecalendar/phpthumb/demo/phpThumb.demo.object.php b/site/racecalendar/phpthumb/demo/phpThumb.demo.object.php new file mode 100644 index 0000000..39ae163 --- /dev/null +++ b/site/racecalendar/phpthumb/demo/phpThumb.demo.object.php @@ -0,0 +1,72 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.object.php // +// James Heinrich // +// // +// Example of how to use phpthumb.class.php as an object // +// // +////////////////////////////////////////////////////////////// + +// Note: phpThumb.php is where the caching code is located, if +// you instantiate your own phpThumb() object that code is +// bypassed and it's up to you to handle the reading and +// writing of cached files. + + + +require_once('../phpthumb.class.php'); + +// create 3 sizes of thumbnail +$thumbnail_widths = array(160, 320, 640); +foreach ($thumbnail_widths as $thumbnail_width) { + + // Note: If you want to loop through and create multiple + // thumbnails from different image sources, you should + // create and dispose an instance of phpThumb() each time + // through the loop and not reuse the object. + $phpThumb = new phpThumb(); + + // set data + $phpThumb->setSourceFilename($_FILES['userfile']['tmp_name']); + // or $phpThumb->setSourceData($binary_image_data); + // or $phpThumb->setSourceImageResource($gd_image_resource); + + // set parameters (see "URL Parameters" in phpthumb.readme.txt) + $phpThumb->w = $thumbnail_width; + //$phpThumb->h = 100; + //$phpThumb->fltr[] = 'gam|1.2'; + + // set options (see phpThumb.config.php) + // here you must preface each option with "config_" + $phpThumb->config_output_format = 'jpeg'; + $phpThumb->config_imagemagick_path = '/usr/local/bin/convert'; + //$phpThumb->config_allow_src_above_docroot = true; // needed if you're working outside DOCUMENT_ROOT, in a temp dir for example + + // generate & output thumbnail + $output_filename = './thumbnails/'.basename($_FILES['userfile']['name']).'_'.$thumbnail_width.'.'.$phpThumb->config_output_format; + if ($phpThumb->GenerateThumbnail()) { // this line is VERY important, do not remove it! + if ($output_filename) { + if ($phpThumb->RenderToFile($output_filename)) { + // do something on success + echo 'Successfully rendered:
    '; + } else { + // do something with debug/error messages + echo 'Failed (size='.$thumbnail_width.'):
    '.implode("\n\n", $phpThumb->debugmessages).'
    '; + } + } else { + $phpThumb->OutputThumbnail(); + } + } else { + // do something with debug/error messages + echo 'Failed (size='.$thumbnail_width.'):
    '.implode("\n\n", $phpThumb->debugmessages).'
    '; + } + + // remember to unset the object each time through the loop + unset($phpThumb); +} + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/demo/phpThumb.demo.random.php b/site/racecalendar/phpthumb/demo/phpThumb.demo.random.php new file mode 100644 index 0000000..40e3209 --- /dev/null +++ b/site/racecalendar/phpthumb/demo/phpThumb.demo.random.php @@ -0,0 +1,95 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.random.php // +// James Heinrich // +// // +// Display a random image from a specified directory. // +// Run with no parameters for usage instructions. // +// // +////////////////////////////////////////////////////////////// + +function SelectRandomImage($dirname='.', $portrait=true, $landscape=true, $square=true) { + // return a random image filename from $dirname + // the last 3 parameters determine what aspect ratio of images + // may be returned + $possibleimages = array(); + if ($dh = opendir($dirname)) { + while ($file = readdir($dh)) { + if (is_file($dirname.'/'.$file) && eregi('\.(jpg|jpeg|gif|png|tiff|bmp)$', $file)) { + if ($gis = @GetImageSize($dirname.'/'.$file)) { + if ($portrait && ($gis[0] < $gis[1])) { + // portrait + $possibleimages[] = $file; + } elseif ($landscape && ($gis[0] > $gis[1])) { + // landscape + $possibleimages[] = $file; + } elseif ($square) { + // square + $possibleimages[] = $file; + } + } + } + } + closedir($dh); + } + if (empty($possibleimages)) { + return false; + } + if (phpversion() < '4.2.0') { + mt_srand(time()); + } + $randkey = mt_rand(0, count($possibleimages) - 1); + return realpath($dirname.'/'.$possibleimages[$randkey]); +} + +if (@$_REQUEST['dir']) { + if (is_dir($_REQUEST['dir'])) { + + if (!@$_REQUEST['o']) { + $_REQUEST['o'] = 'PLS'; + } + $_REQUEST['o'] = strtoupper($_REQUEST['o']); + $portrait = (strpos(@$_REQUEST['o'], 'P') !== false); + $landscape = (strpos(@$_REQUEST['o'], 'L') !== false); + $square = (strpos(@$_REQUEST['o'], 'S') !== false); + $randomSRC = SelectRandomImage($_REQUEST['dir'], $portrait, $landscape, $square); + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + $randomSRC = str_replace('\\', '/', eregi_replace('^'.realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath($randomSRC))); + } else { + $randomSRC = str_replace(realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath($randomSRC)); + } + + $otherParams = array(); + foreach ($_GET as $key => $value) { + if (($key == 'dir') || ($key == 'o')) { + continue; + } + if (is_array($value)) { + foreach ($value as $vkey => $vvalue) { + $otherParams[] = urlencode($key).'['.urlencode($vkey).']='.urlencode($vvalue); + } + } else { + $otherParams[] = urlencode($key).'='.urlencode($value); + } + } + header('Location: ../phpThumb.php?src='.urlencode($randomSRC).'&'.implode('&', $otherParams)); + exit; + + } else { + die($_REQUEST['dir'].' is not a directory'); + } + +} else { + + echo 'Usage: '.basename($_SERVER['PHP_SELF']).'?dir=<directory>&<phpThumb parameters>&o=(P|L|S)

    Examples:
      '; + echo '
    • '.basename($_SERVER['PHP_SELF']).'?./images/&o=L (landscape images only)
    • '; + echo '
    • '.basename($_SERVER['PHP_SELF']).'?./images/&o=PS (portrait or square images only)
    • '; + echo '
    '; + +} + +?> diff --git a/site/racecalendar/phpthumb/demo/phpThumb.demo.showpic.php b/site/racecalendar/phpthumb/demo/phpThumb.demo.showpic.php new file mode 100644 index 0000000..e7162f3 --- /dev/null +++ b/site/racecalendar/phpthumb/demo/phpThumb.demo.showpic.php @@ -0,0 +1,98 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +// // +// phpThumb.demo.showpic.php // +// James Heinrich // +// 23 Feb 2004 // +// // +// This code is useful for popup pictures (e.g. thumbnails // +// you want to show larger, such as a larger version of a // +// product photo for example) but you don't know the image // +// dimensions before popping up. This script displays the // +// image with no window border, and resizes the window to // +// the size it needs to be (usually better to spawn it // +// large (600x400 for example) and let it auto-resize it // +// smaller), and if the image is larger than 90% of the // +// current screen area the window respawns itself with // +// scrollbars. // +// // +// Usage: // +// window.open('showpic.php?src=big.jpg&title=Big+picture', // +// 'popupwindowname', // +// 'width=600,height=400,menubar=no,toolbar=no') // +// // +// See demo linked from http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +?> + + + + <?php echo @$_GET['title']; ?> + + + + +'."\n"; + echo 'if (((screen.width * 1.1) > '.$imgdata[0].') || ((screen.height * 1.1) > '.$imgdata[1].')) {'."\n"; + // screen is large enough to fit whole picture on screen with 10% margin + echo 'document.writeln(\'\');'; + echo 'CrossBrowserResizeInnerWindowTo('.$imgdata[0].', '.$imgdata[1].');'."\n"; + echo '} else {'."\n"; + // image is too large for screen: add scrollbars by putting the image inside an IFRAME + echo 'document.writeln(\'\');'; + echo '}'."\n"; + echo ''; + +} else { + + // cannot determine correct window size, or correct size too large: add scrollbars by putting the image inside an IFRAME + echo ''; + +} + +?> + + \ No newline at end of file diff --git a/site/racecalendar/phpthumb/demo/readme.demos.txt b/site/racecalendar/phpthumb/demo/readme.demos.txt new file mode 100644 index 0000000..483dfc1 --- /dev/null +++ b/site/racecalendar/phpthumb/demo/readme.demos.txt @@ -0,0 +1,41 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb() included and related demos // +// /// +////////////////////////////////////////////////////////////// + +The phpThumb() distribution includes several demos, and it +should be self-evident what they do when you run them: + +* phpThumb.demo.demo.php - shows a wide variety of samples, + basically all the different features and filters of phpThumb. + Note: sample image files are not included in the distribution + but can be downloaded from http://phpthumb.sourceforge.net/demo + +* phpThumb.demo.check.php - configuration checker, will check + your config file and server configuration and warn of any + potential problems + +* phpThumb.demo.object.php - example of how to call phpThumb + as an object. + +* phpThumb.demo.random.php - select & display a random thumbnail + from a directory of images. + +* phpThumb.demo.showpic.php - auto-resizes a popup window to + match the dimensions of the image it is displaying + + + +Other people have created useful demos and/or extensions to +phpThumb(). Some of these I know of are: + +* iManager - http://www.j-cons.com/news/ +* iBrowser - http://www.j-cons.com/news/ +* ThumbnailSelector - http://www.silisoftware.com/scripts/ThumbnailSelector + +If you know of any others you think should be mentioned here +please let me know: info@silisoftware.com \ No newline at end of file diff --git a/site/racecalendar/phpthumb/docs/phpthumb.changelog.txt b/site/racecalendar/phpthumb/docs/phpthumb.changelog.txt new file mode 100644 index 0000000..e75aa7f --- /dev/null +++ b/site/racecalendar/phpthumb/docs/phpthumb.changelog.txt @@ -0,0 +1,1040 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// + +¤ = structure change or important new feature +* = less important new feature or change + +v1.7.0 - February 15, 2006 + ¤ ImageMagick output is used directly far more frequently + for much improved speed and minor quality improvement. + ¤ ImageMagick now processes most of the image filters if + possible (will fall back to GD methods if unavailable) + ¤ GD support is now optional if ImageMagick is installed. + Known limitations include: + - no support for HTTP source images + - ICO output is buggy (in some ImageMagick versions) + - most &fltr[] filters don't work at all + - 'ar', 'ra', 'far' don't work + ¤ Added output support for ICO (icon) format (&f=ico). + Currently only supports single-image icons, but multi- + resolution support may be added in future versions + New file: phpthumb.ico.php + ¤ Added output support for BMP (bitmap) format (&f=bmp). + Currently only supports 24-bit RGB format (for simplicity) + ¤ Added new configuration & compatability checker + New file: demo/phpThumb.demo.check.php + * ImageMagick-generated thumbnails now have extra hidden + contents (EXIF data, etc) stripped (by using -thumbnail + instead of -resize) resulting in smaller filesizes + * Added background fill color, opacity and extent options to + 'wmt' filter (thanks craigØpc-fanatics*com) + * Added metacharacter (^*) support for 'wmt', currently: + source filesize in bytes (^Fb), kB (^Fk), MB (^Fm), + source image width (^X), source image height (^Y), + thumbnail width (^x), thumbnail height (^y) and caret (^^) + (Feature Request #1357815) + (thanks ticklemeozmoØusers*sourceforge*net) + * Moved ImageDestroy call from OutputThumbnail to end of + phpThumb.php to allow multiple calls to OutputThumbnail + * Added config_http_user_agent for site with browsersniffers + (thanks redrobØgmail*com) + * Added $PHPTHUMB_CONFIG['disable_pathinfo_parsing'] (default + false) which disables parsing $_SERVER[PATH_INFO] for + parameters. If you want to parse PATH_INFO, set to false + * Added $PHPTHUMB_CONFIG['disable_imagecopyresampled'] (default + false) which replaces ImageCopyResampled with + ImageCopyResampleBicubic for buggy PHP-GD versions + (thanks g*pelagattiØnetface*it) + * Added $PHPTHUMB_CONFIG['cache_prefix'] to allow sharing of + cache files across virtual servers (Feature Request #1395332) + (thanks doggyfrØusers*sourceforge*net) + * Added $PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] with + default=true (increased speed) to allow direct passthru of + images that don't have GD support. (Feature Request #1396446) + (thanks zedboyØusers*sourceforge*net) + * Removed $PHPTHUMB_CONFIG['cache_differentiate_offsite'] because + it is now automatically tied in with nooffsitelink_enabled + (thanks doggysworldØlibertysurf*fr) + * Removed phpThumb.demo.cacheconvert2.php + * Debug messages are now passed back from filters + * $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] now + defaults to true for much-improved cached performance + (thanks redrobØgmail*com) + * $PHPTHUMB_CONFIG['cache_differentiate_offsite'] now defaults + to false + * Added $PHPTHUMB_DEFAULTS['ar']='x' to phpThumb.config.php.default + * Added ImageDestroy($this->gdimg_source) to GenerateThumbnail() + to save memory before applying image filters + * gd_info() no longer member of phpthumb_functions + * cache files now default to using SERVER_NAME without 'www.' + * phpUnsharpMask::applyUnsharpMask() should be faster under PHP5 by + using ImageFilter(IMG_FILTER_GAUSSIAN_BLUR) when radius==1 + * Added alternate CURL method for HTTP source images if + allow_url_fopen is disabled (thanks webweberØmotiondraw*com) + * Replaced $this->osslash with DIRECTORY_SEPARATOR constant + * Bugfix: [#1398327] 'new' got broken (1x1 images) + * Bugfix: [#1412552] HTTP source images with special characters were + not getting urlencoded + * Bugfix: ImageSaveAlpha errors on GD v2.0.0 + * Bugfix: phpThumbDebug now entirely disabled if high_security=true + * Bugfix: source images with transparency lost transparency when + rotated (thanks roalklØyahoo*com) + * Bugfix: square source images were not resized when only (w|h)(p|l) + parameters passed + * Bugfix: source images are passed through unmodified in more cases + * Bugfix: ImageMagick not used on systems where it exists outside + defined open_basedir + * Bugfix: ImageMagickVersion() now returns correct versionstring + * Bugfix: ImageMagick warnings no longer cause ImageMagick to fail + * Bugfix: ErrorImage no longer fatal to phpThumbDebug + * Bugfix: "Array to string conversion" in foreach($a as $v) loops + (thanks zeeshanØtargetedmedia*co*uk) + * Bugfix: safe mode warnings in ImageCreateFromStringReplacement + (thanks adminØalex-home*net) + * Bugfix: nooffsitelink broken if !nooffsitelink_require_refer + (thanks depronØgmx*net) + * Bugfix: phpThumb failed when magic_quotes_runtime=true + (thanks stansawyerØyahoo*com) + * Bugfix: several issues with HTTP image sources + (thanks redrobØgmail*com) + * Bugfix: phpThumb_tempnam() would return incomplete temp filenames + under Windows, which may result in orphaned zero-byte temp files + in C:\ if multiple drives exist + +v1.6.2 - November 24, 2005 + ¤ Animated GIF output is now possible if ImageMagick is + available and no filters (other than resize) are applied + (thanks brandenbassØgmail*com for idea) + * Added $PHPTHUMB_CONFIG['cache_force_passthru'] to work + around cached-image-only-works-second-time issue + (thanks yakoØ11y11*com) + * Bugfix: black borders on some image edges + (thanks atelierØdelirius*ch && chuckØcatalyststudio*com) + * Bugfix: uncaught PHP warning in RenderToFile DebugMessage + * Bugfix: allow phpThumbDebug in noGD PHP installations + * Bugfix: 'hash' warning in high_security mode + (thanks bernhardØwtf*at) + * Bugfix: non-TTF rotated text watermarks now work (unrotated) + with no warnings if ImageRotate is unavailable + (thanks aparviaiØusers*sourceforge*net) + +v1.6.1 - August 26, 2005 + ¤ Filters now use GD functions where available (using + ImageFilter, only available in PHP v5.0.0+ with bundled + version of GD). Enabled for: colorize, negative, + grayscale, brightness, contrast, gaussian blur, selective + blur, mean removal (thanks donlaurØmac*com) + ¤ Added config_prefer_imagemagick (defaults=true) + ¤ Added phpthumb_filters::Grayscale() 'gray' + ¤ Added phpthumb_filters::ReduceColorDepth() 'rcd' + ¤ Added phpthumb_filters::Brightness() 'brit' + ¤ Added phpthumb_filters::Contrast() 'cont' + ¤ Added phpthumb_filters::Saturation() 'sat' + ¤ Added phpthumb_filters::EdgeDetect() 'edge' [PHP5 only] + ¤ Added phpthumb_filters::BlurGaussian() 'gblr' [PHP5 only] + ¤ Added phpthumb_filters::BlurSelective() 'gblr' [PHP5 only] + ¤ Added phpthumb_filters::MeanRemoval() 'mean' [PHP5 only] + ¤ Added phpthumb_filters::Smooth() 'smth' [PHP5 only] + * New timing debug info in phpThumbDebug + * Added config_cache_differentiate_offsite + * config_die_on_error now defaults to false + * ResolveSource works better + * cache filenames with 'fltr' parameters have changed + * Filters now skip processing if amount=0 or similar + * [#1263051] 'far' now accepts L,R,T,B,C as values giving + alignment of left/right/top/bottom/center respectively. + Old value of '1' defaults to centered + (thanks webgrappaØusers*sourceforge*net) + * Bugfix: RenderToFile() now fails properly when output format + is unknown + * Bugfix: PNG transparency wasn't working with 'far' + * Bugfix: source images with EXIF thumbnails that differ in + aspect ratio no longer use EXIF thumbnails as source unless + no other options exist + * Bugfix: setting 'src' with setParameter now invokes + setSourceFilename to properly set $this->sourceFilename + (thanks Gazou) + * Bugfix: 'zc' had poor quality when used with ImageMagick + * Bugfix: 'aoe' parameter broken when not using ImageMagick + (thanks frankieali4Øhotmail*com) + * Bugfix: fixed issue with symbolic links + (thanks hornet136Øgmail*com) + * Bugfix: config_max_source_pixels now defaults to same + calculation as used in phpThumb.config.php + (thanks vukshaØhotmail*com) + * Bugfix: Offsite cached thumbnails no longer use unique + referer (now either nothing or "_offsite") + (thanks swaayeØyahoo*com) + * Bugfix: "Unknown image type identified by “] + where is the target hex color to white balance + on, this color is what "should be" white, or light + gray. The filter attempts to maintain brightness so + any gray color can theoretically be used. If is + omitted the filter guesses based on brightest pixels + in each of RGB + ¤ Cached files are used by a Location header instead of + being passed through phpThumb.php using readfile + (thanks newtnØthrillnerds*com) + * Added 'cache_source_filemtime_ignore_local' and + 'cache_source_filemtime_ignore_remote' configurations + to ignore source modification and/or removal + (thanks raynerapeØgmail*com) + * Added 'md5s' parameter, which is the MD5 hash of the + source image -- if this parameter is passed with the + hash of the source image then the source image is not + checked for existance or modification and the cached + file is used (if available). If 'md5s' is passed an + empty string then phpThumb.php dies and outputs the + correct MD5 hash value. This parameter is the single- + file equivalent of 'cache_source_filemtime_ignore_*' + configuration paramters (thanks raynerapeØgmail*com) + * Added /demo/phpThumb.demo.object.php + * Unused parameter 'bgt' removed + * Added empty /cache/source/ directory to distribution + * Added /demo/ and /docs/ and /fonts/ directories + * Set default config_use_exif_thumbnail_for_speed = false + * Bugfix: Wrapped output buffering around all + include_once calls to prevent headers getting sent + accidentally + * Bugfix: md5_file and imagecolorallocatealpha calls + were undefined under PHP v4.1.x (thanks tomØemile*com) + * Bugfix: default 'f' parameter ('jpeg') overrode + config_output_format in object mode + (thanks mailØmmjaeger*com) + * Bugfix: suppressed error message for IIS shell_exec + errors (thanks tomØemile*com) + * Bugfix: Added PHP version check for stream_set_timeout + for HTTP sources (thanks raynerapeØgmail*com) + * Bugfix: overlay margins of 0.5-1.0 cause invalid image + dimensions error (thanks mailØmmjaeger*com) + * Bugfix: underlay margins were not working + (thanks mailØmmjaeger*com) + * Bugfix: [#1187735] EXIF thumbnails were incorrectly + output to the browser directly if requested thumbnail + exactly matched EXIF dimensions + (thanks rebootØusers*sourceforge*net) + +v1.5.2 - April 20, 2005 + ¤ phpThumb.config.php is renamed to + phpThumb.config.php.default to prevent accidental + overwriting. Please migrate your old settings to the new + file, delete your old config and rename the default to + phpThumb.config.php + ¤ Added new filters: + - 'blur' (Blur) [ex: &fltr[]=blur|] + where (0 < < 25) (default = 1) + (thanks thoensiØnetcom*no for code) + - 'hist' (Histogram) + [ex: &fltr[]=hist|||||||] + Where is the color band(s) to display, from back + to front (one or more of "rgba*" for Red Green Blue + Alpha and Grayscale respectively); + is a semicolon-seperated list of hex colors to + use for each graph band (defaults to FF0000, 00FF00, + 0000FF, 999999, FFFFFF respectively); + and are the width and height of the overlaid + histogram in pixels, or if <= 1 then percentage of + source image width/height; + is the alignment (same as for "wmi" and "wmt"); + is opacity from 0 to 100; + is the edge (and inter-tile) margin in percent + - 'over' (OVERlay/underlay image) overlays an image on + the thumbnail, or overlays the thumbnail on another + image (to create a picture frame for example) + [ex: &fltr[]=over||||] + where is the image filename; is "0" (default) + for overlay the image on top of the thumbnail or "1" + for overlay the thumbnail on top of the image; is + the margin - can be absolute pixels, or if < 1 is a + percentage of the thumbnail size [must be < 0.5] + (default is 0 for overlay and 10% for underlay); + is opacity (0 = transparent, 100 = opaque) + (thanks raynerapeØgmail*com, shabazz3Ømsu*edu) + - 'gray' (GRAYscale) [ex: &fltr[]=gray] + is an alias to 100% desaturation + * New configuration 'cache_source_directory' allows the + unprocessed source image to be cached when source is + HTTP or from a database (thanks raynerapeØgmail*com) + * Added 'cache' subdirectory to phpThumb distribution + since this is the default location for the cache + folder. + * Default value for config_error_die_on_source_failure + changed to true (thanks shabazz3Ømsu*edu) + * Added checks to make sure $this->gdimg_output is a + resource before allowing calls to RenderToFile or + OutputThumbnail + * Better error messages when phpThumb.config.php missing + * Bugfix: watermark overlay margins were wrong + * Bugfix: 'lvl' filter no longer processes if not needed + * Bugfix: off-server thumbnail error message was wrong + * Bugfix: several PHP safe mode fixes + (thanks virginiaØalertbutnotalarmed*com) + * Bugfix: cache filenames broken for filter parameters + with paths (thanks srcericØusers.sourceforge.net) + +v1.5.1 - April 06, 2005 + * Added some security upgrades: + - 'config_*' parameters cannot be passed by GETstring + - 'config_nooffsitelink_require_refer' is a new option + (disabled by default) that only allows calls to + phpThumb() from a refering domain listed in + 'config_nooffsitelink_valid_domains' + - disallowed paramters now generate an error image if + present in the GETstring + - 'high_security_enabled' if set to true enabled new + mode of verification, and requires a small function + to generate a hash for calls to phpThumb: + echo ''; + This function is supplied at the bottom of + phpThumb.config.php (thanks paulØstonie*co*uk) + ¤ Added new parameter "new" (phpThumb.php only) which can + create a new image without using "src" parameter. Set + "&new=|" where is the background hex color, + is (optional) opacity (0=transparent, 100=opaque). + (thanks mailØmmjaeger*com) + ¤ Added new filters: + - 'sep' (Sepia) [ex: &fltr[]=sep||] + where is a number between 0 and 100 for the + amount of colorization (default=50), and is + the hex color to colorize to (default=A28065). + (thanks mailØmmjaeger*com) + - 'lvl' (Levels) [ex: &fltr[]=lvl||| + where can be one of 'r', 'g', 'b', 'a' (for + Red, Green, Blue, Alpha respectively), or '*' for all + channels based on average grayscale value (default). + and are the clip points for the levels + (range = 0-255) and are set to clip 0.1% of each end + by default. Use -1 for min and/or max to invoke auto- + detect mode. Using default parameters (&fltr[]=lvl) + is similar to Auto Contrast in Adobe Photoshop. + * Bugfix: Image MIME header was incorrect for cached + images. + * Bugfix: Cache was broken for images pulled from a + database in phpThumb.php + (thanks dragutin*cvetkovicØdragontech-ltd*com) + * Bugfix: Hotlink/Offsite prevention was broken when + image was already cached. + * Bugfix: ImageMagick path was incorrect in some cases + (thanks joshgØtwcny*rr*com) + * Bugfix: ProportionalResize() in phpthumb.functions.php + had a broken check for default values + (thanks Bert*ClaeysØarinso*com) + * Bugfix: transparency now preserved for GIF & PNG input + (thanks tristanØcyrax*ch) + * Bugfix: transparency now supported for GIF output + (thanks j_ivanovØabv*bg) + * Bugfix: alpha transparency could be lost in ApplyMask() + (thanks analyzerxØgmail*com) + * Bugfix: errors on 16/32-bit BMPs + (thanks mattØhellstrominc*com) + * Bugfix: Added datestamp to cached filenames for remote + (HTTP) files, and better warning for caching + (thanks a*gambinoØabramo*it) + * Faster BMP parsing (thanks sgeppertØmail*utexas*edu) + * Added 'error_die_on_source_failure' configuration to + allow invalid source images to show an error rather + than output unmodified source image. + (thanks mindpixelØgmail*com) + * Added $phpThumb->fatalerror which will contain the + text of the fatal error if 'error_die_on_error' is + false. (thanks mindpixelØgmail*com) + +v1.5.0 - February 4, 2005 + * Added new filter parameter 'fltr' that is an array and + can apply multiple effects in sequence. Current filters + that can be called are: + - 'gam' (Gamma Correction) [ex: &fltr[]=gam|] + where can be a number >0 to 10+ (default 1.0) + - 'ds' (DeSaturate) [ex: &fltr[]=ds|] + where is a number between zero (no change) + and 100 (complete desaturation -- grayscale), or it + can be a negative number for saturation boost. + (thanks mailØmmjaeger*com) + - 'clr' (Colorize) [ex: &fltr[]=clr||] + where is a number between 0 and 100 for the + amount of colorization, and is the hex color + to colorize to. (thanks mailØmmjaeger*com) + - 'neg' (Negative) [ex: &fltr[]=neg] + inverts the color + - 'th' (ThresHold) [ex: &fltr[]=th|] (range 0-255) + every grayscale pixel brighter than is set to + white, every darker pixel is set to black + (thanks mailØmmjaeger*com) + - 'usm' (UnSharpMask) [ex: &fltr[]=usm|||] + where is the amount (default = 80), is the + radius (default = 0.5), is the threshold + (default = 3). + - 'wmi' (WaterMarkImage) + [ex: &fltr[]=wmi||||] where is the + filename of the image to overlay, is the + alignment (one of BR, BL, TR, TL, C, R, L, T, B, * + where B=bottom, T=top, L=left, R=right, C=centre, + *=tile), is opacity from 0 to 100, is the + edge (and inter-tile) margin in percent + - 'wmt' (WaterMarkText) + [ex: &fltr[]=wmt||||||||] + where: + is the text to use as a watermark, + is the font size (1-5 for built-in font, or point + size for TrueType fonts), + is the alignment (one of BR, BL, TR, TL, C, R, L, + T, B, * where B=bottom, T=top, L=left, R=right, + C=centre, *=tile), + is the hex color of the text + is the filename of the TTF file (optional, if + omitted a built-in font will be used) + is opacity from 0 to 100, + is the edge (and inter-tile) margin in percent + is the angle + (thanks mailØmmjaeger*com) + - 'flip' [ex: &fltr[]=flip|x or &fltr[]=flip|y] + flip image on X or Y axis + (thanks mailØmmjaeger*com) + - 'elip' [ex: &fltr[]=elip] + similar to rounded corners but more extreme + (thanks mailØmmjaeger*com) + - 'mask' [ex: &fltr[]=mask|filename.png] + greyscale values of mask are applied as the alpha + channel to the main image. White is opaque, black + is transparent. + - 'bvl' (BeVeL) [ex: &fltr[]=bvl|||] + where is the bevel width, is the hex color + for the top and left shading, is the hex color + for the bottom and right shading + (thanks mailØmmjaeger*com) + - 'fram' (FRAMe) draws a frame, similar to border but + more configurable (thanks mailØmmjaeger*com) + [ex: &fltr[]=fram|||||] + where is the width of the main border, is + the width of each side of the bevel part, is the + hex color of the main border, is the highlight + bevel color, is the shadow bevel color + - 'drop' (DROP shadow) + [ex: &fltr[]=drop||||] + where is distance from image to shadow, is + width of shadow fade (not yet implemented), is + the hex color of the shadow, and is the angle of + the shadow (default=225) + - 'ric' (Rounded Image Corners) + [ex: &fltr[]=ric||] + where is the horizontal corner radius, + is the vertical corner radius + * Split out filter functions into phpthumb.filters.php + * 'usa','usr','ust' parameters have been removed and + replaced with the 'fltr' call (see above) + * 'wmf','wma','wmp','wmm' parameters have been removed + and replaced with the 'fltr' call (see above) + * 'brx','bry','bw' parameters have been removed + and replaced with the 'fltr' call (see above) + * 'bw=0' to force aspect ratio has been replaced by + 'far=1' (force aspect ratio) + * Filters that produce transparent sections (such as + Rounded Corners, Ellipse, Mask, Rotate) are now output + as 32-bit/alpha PNG, or flattened with "bg" background + color for JPEG/GIF output (thanks mailØmmjaeger*com) + * Added 'zc' (Zoom Crop) parameter + (thanks arcookeØgmail*com, mailØmmjaeger*com, + pl16056Ømacnews*de, kezzasmØusers*sourceforge*net, etc) + * AutoRotate now can use EXIF orientation tag ('ar=x') + * Added 'ttf_directory' configuration parameter for + TrueType watermarks (thanks mailØmmjaeger*com) + * Added "Last-Modified" header to cache portion of + phpThumb.php which should allow better user-side + caching of thumbnails. (thanks derekØnetsimple*net) + * Added 'cache_disable_warning' configuration which will + cause an error image to be displayed if the cache + directory isn't configured, unless explicitly disabled + * Added 'nooffsitelink_enabled' configuration which + prevents linking to thumbnails on your server from + another domain. Defaults to watermaking linked images + with text warning message. + (thanks anteØabstraktmedia*com) + * Added 'error_image_width' & 'error_image_height' + config variables (thanks mailØmmjaeger*com) + * Rounded image corners now requires GD v2.0.1 and PHP + v4.3.2. Corners are transparent (for PNG output) and + antialiased. + * Rotate by arbitary angle ('ra') now has a transparent + background for PNG output + * Cached filenames now have an additional component for + applied filters + * Cached filenames now have an additional component for + HTTP referer, but only if the refering domain does not + match the domain of the server (designed to prevent + imaged linked from offsite with error message being + cached the same as the local cached version) + * Added setSourceImageResource() to allow use of an + existing GD image resource for thumbnailing + (thanks danØgonmad*co*uk) + * Now including phpThumb.demo.demo1.php (main demo page) + and phpThumb.demo.demo2.php (configurable demo page) + in the phpThumb() distribution + (thanks mailØmmjaeger*com) + * Added many more debugging/tracing message points + * Added set_time_limit(30) to phpThumb.php + * Bugfix: ImageMagick not used if `which convert` points + to a link and not a file (thanks bkainersØgmail*com) + * Bugfix: 'bgt' parameter was sometimes misspelled 'bct' + * Bugfix: 'wmm' couldn't be set to zero + * Bugfix: 'wmm' parameter was only applied to top/left of + image + * Bugfix: auto-detection of document_root failed on + Windows (thanks xbartvØhotmail*com) + * Bugfix: phpThumbDebug could be bypassed if EXIF + thumbnail present (thanks olgradinØcheckfree*com) + * Bugfix: cache file wasn't being written if EXIF data + was used directly (thanks olgradinØcheckfree*com) + * Bugfix: phpThumb.demo.showpic.php was broken by popup + blockers for images larger than the screen. + (thanks mailØmmjaeger*com) + +v1.4.11 - October 11, 2004 + * Changed sx/sy/sw/sh parameters to allow decimal values + (>0 but <1) to represent percent of source image + (thanks mordorØdefault*co*yu) + * Added config_error_silent_die_on_error for no-output + die on fatal errors (thanks johannesØformformat*se) + * Added auto-detection of probable 'document_root' if + that key is not available in $_SERVER + * Bugfix: Check `which convert` failing with error + message (thanks chadØchadshome*com) + * Bugfix: Image cropping to invalid areas outside source + image caused text output (thanks mordorØdefault*co*yu) + +v1.4.10 - August 22, 2004 + * Bugfix: cached files not written in most cases + (thanks kizerØcourtkizer*com, snuffØinbox*ru) + * Bugfix: ApacheLookupURIarray() crashes in CGI mode + (thanks hanskrentelØyahoo*de) + * Bugfix: phpthumb_bmpfile2gd() was broken + (thanks iØmindlace*net) + +v1.4.9 - August 9, 2004 + * Bugfix: changed destination filename in RenderToFile() + (thanks alextkØwalla*com) + * Bugfix: problems with HTTP image source when called as + an object (thanks alextkØwalla*com) + +v1.4.8 - August 4, 2004 + * $this->error has changed to $this->errors and is now + an array of strings (instead of a single string) + * A lot more error conditions (invalid cache directory, + etc) are now reported in $this->errors + (thanks aidan*slingsbyØlineone*net) + * Removed all define(CONSTANT) in the phpThumb() + constructor - you can now access: + - PHPTHUMB_VERSION == $this->phpthumb_version; + - PHPTHUMB_OSSLASH == $this->osslash; + - PHPTHUMB_ISWINDOWS == $this->iswindows; + * Bugfix: Error message from apache_lookup_uri() failing + under Apache2 now reported cleanly + (thanks derbaffØyahoo*com) + * Bugfix: missing phpthumb_functions:: class name for + ImageTypeToMIMEtype() call in ExtractEXIFgetImageSize() + (thanks aidan*slingsbyØlineone*net) + * Bugfix: ImageTypeToMIMEtype() was broken for PHP older + than v4.3.0 (thanks georg*schreiberØbatch-pc*es) + * Bugfix: RenderToFile() now returns false if it fails + (thanks phpthumbØsendthemtomir*com) + * Bugfix: Corrupt JPEG/PNG/GIF files that failed + ImageCreateFrom*() were not being passed to ImageMagick + for fallback, nor passed through unmodified if IM was + unavailable or failed (thanks r*chongØmogenic*net) + * Bugfix: Improved backtick safe-mode limit detection + (thanks 1Øadamcarrington*com) + * Bugfix: EXIF thumbnails were being used as source when + they should not be (thanks aidan*slingsbyØlineone*net) + * Bugfix: Cached files were not being created or used + properly (thanks aidan*slingsbyØlineone*net) + * Bugfix: max_source_pixels not set correct on some PHP + versions (thanks derbaffØyahoo*com) + * Bugfix: 'down' parameter ignored for unprocessed and + cached files (thanks aidan*slingsbyØlineone*net) + +v1.4.7 - July 27, 2004 + * Included a modified version of "module.graphic.bmp.php" + from getID3() [http://getid3.sourceforge.net] as + "phpthumb.bmp.php" for BMP reading support without + ImageMagick. It works, but it's *very* slow, especially + for large images (as in 640x480 or larger). + * Added check to prevent error messages when shell_exec + is disabled (thanks webmasterØneester*com) + +v1.4.6 - July 22, 2004 + * Added new section to phpthumb.config.php where you can + easily specify defaults for any parameter you can set + in the URL. Normally URL parameters override these + default values, unless you set + $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE to false + * Renamed phpthumb.config.php to phpThumb.config.php + since it's part of phpThumb.php, not part of + phpthumb.class.php (change of case only, will not + affect Windows servers, but will affect *nix) + * Changed cached filename of rawImageData-source images + from urlencode('') to md5(rawImageData). This should + make caching thumbnails from non-file sources more + reliable. + * Added ImageMagick debugging information + * Removed unneccesary default values from cached + filenames. This may invalidate some previously cached + files. phpthumb.demo.cacheconvert.php has been updated + to handle v1.4.1-1.4.5 => v1.4.6+ cache filenames. + * Bugfix: Cached filename did not have file-modified + datestamp when used as implmented in phpThumb.php + * Bugfix: RenderToFile() now accepts relative filenames + (thanks aidan*slingsbyØlineone*net) + * Bugfix: AllowOutputEnlargment setting was ignored when + falling back to ImageMagick + * Bugfix: IgnoreAspectRatio setting was ignored when + falling back to ImageMagick + * Bugfix: config_temp_directory was ignored in gd_info() + in PHP < v4.3.0 when phpinfo() returns no GD + information (due to safe mode restrictions) + (thanks mimyrtekØmyrtek*com) + +v1.4.5 - June 28, 2004 + * Added new parameter 'down' where you can specify a + filename and OutputThumbnail() will cause the file + to be downloaded rather than displayed in the browser. + Demo images on silisoftware.com/scripts/phpThumb/demo/ + can all be downloaded to show off this feature. + (thanks stuartscrumpØyahoo*co*uk) + * Added ability to remove old files from cache directory + based on last-access time and/or number of cached files + and/or total size of cached files + (thanks jrmhaigØyahoo*co*uk) + * Added public CleanUpCacheDirectory() for cache cleaning + (see above) if you need to call it manually + * Included new file phpThumb.demo.cacheconvert.php to + convert old-style cache names to the current (and + hopefully last!) standard naming convention. + (thanks joshgØtwcny*rr*com) + * Added configuration value 'document_root' for rare case + when $_SERVER['DOCUMENT_ROOT'] return incorrect value + (thanks joshgØtwcny*rr*com) + * Now tries to create thumbnail with ImageMagick if + ImageCreateFromJPEG etc fails, before falling back to + outputting unmodified source data. + * Bugfix: HTTP image sources were broken + (thanks fritz*weisshartØt-online*de) + * Bugfix: ImageMagick callout wasn't being used if EXIF + thumbnail was available + (thanks joshgØtwcny*rr*com) + * Bugfix: HTTP src with space in filename was broken + (thanks drØrhodes360*com) + * Bugfix: version_compare_replacement() was broken for + PHP v4.1.0+ + +v1.4.4 - June 8, 2004 + * Bugfix: network-share (Windows) source filenames were + not possible. Now works, but you must use the network + name and not a mapped drive name, for example: + \\othercomputer\file.jpg - good + \\192.168.2.1\file.jpg - good + z:\file.jpg - won't work + This is a PHP limitation (see www.php.net/file-exists) + Note: you may want to use "/" slashes instead of "\" if + you have magic_quotes_gpc enabled to avoid stripslashes + problems. + (thanks drØrhodes360*com) + * Bugfix: missing "phpthumb_functions::" in + ImageCreateFromStringReplacement() + (thanks zapletalØsoftwaremedia*cz) + +v1.4.3 - May 25, 2004 + * Added new configuration variable 'config_temp_directory' + to allow you to specify a writable directory name for + temp files if you do not have access to the system temp + directory on your server (Safe Mode restrictions etc) + (thanks nickØregenmag*com) + * Added new configuration variable + 'config_error_die_on_error' which can be set to false if + you want to retrieve the error message without having it + dumped as an image - the error message is now available + in $phpThumb->error + * Images are passed through directly with no processing + and no caching if no parameters are passed to alter the + image (resize, crop, sharpening, etc) + (thanks nchmuraØusers*sourceforge*net) + * Added new configuration variable 'config_disable_debug' + which disabled phpThumbDebug from working if you have + security concerns about the displayed information + * Bugfix: Added detection at the top of phpThumb.php for + no-GD errors to avoid parse errors later in the code + (thanks nickØregenmag*com) + * Bugfix: RoundedImageCorners() had some off-by-1 errors + (thanks ola*thunbergØhome*se) + +v1.4.2 - May 10, 2004 + * Added IE-compatability mode for transparent corners + (set 'bct=256') + * Bugfix: version_compare_replacement() was broken in PHP + older than 4.1.0 + (thanks nickØregenmag*com) + +v1.4.1.1 - May 9, 2004 + * Bugfix: Removed ImageTrueColorToPalette hack. + See http://bugs.php.net/bug.php?id=28341 + * Bugfix: 'maxb' option for PNG/GIF output incorrect + bit depth under some circumstances + +v1.4.1 - May 9, 2004 + * Added 'maxb' (MAXimum Bytes) option to auto-set the + output image quality (JPEG) or bit depth (PNG/GIF) so + that the output thumbnail is less than 'maxb' bytes + (thanks e_belleØhotmail*com) + * Added 'bgt' parameter to make rounded corners from + 'brx'/'bry' option transparent when used with PNG + output. Note: PHP/GD appears buggy at this time, so this + option must force output to 256-color mode for this + to work. The feature will be updated when a non-broken + version of PHP/GD is released. + (thanks javierØircorion*net) + * Bugfix: Caching was broken + (thanks mikeØgdaymate*nl, jurewiczØgo3*pl) + +v1.4.0 - April 30, 2004 + * Rewritten as a PHP class. Split into several files: + - phpthumb.class.php = most processing code + - phpthumb.functions.php = support functions + - phpthumb.readme.txt = usage instructions + - phpthumb.changelog.txt = this file + - phpthumb.config.php = configuration file + - phpthumb.gif.php = Non-GD GIF reading support + - phpthumb.unsharp.php = Unsharp Masking support + - phpThumb.php = demo script that works + exactly as previous versions; this is a drop-in + replacement for existing phpThumb() installations + - phpThumb.demo.showpic.php = demo script that auto- + resizes a popup window to the size of the image + shown. Useful if you want popup images but do not + know the large image size beforehand + * Added optional call-out to ImageMagick (if avaible) if + source image is larger than PHP memory restrictions + allow. ImageMagick installation should be auto-detected + under *nix, but you should configure 'imagemagick_path' + for use under Windows. + * 'max_source_pixels' is now auto-calculated from PHP + configuration settings. Due to various server-level + restrictions that may override PHP settings this + calculated value may not always be correct, and you may + have to specify the value manually. + * Added rounded-corner border option. You must specify + both 'brx' (horizontal radius) and 'bry' (vertical + radius) as well as 'bw' (border width). If 'bw' is + greater than zero, the image will be shrunk to fit + inside the border with a margin of background color. + If 'bw' is zero, the corners of the image will be + cut off and filled with background color. + (thanks javierØircorion*net) + * Minor speed improvement for unsharp masking + +v1.3.7 - March 28, 2004 + * Bugfix: GD version detection was broken on PHP <4.3.0 + on servers where phpinfo() was disabled + (thanks javierØircorion*net) + * Bugfix: Non-GD GIF support was broken on restricted + PHP configurations + (thanks javierØircorion*net) + * Bugfix: phpThumb.gif.php output error messages if PHP + was running in Safe Mode + * Added 'iar' parameter (Ignore Aspect Ratio) to allow + non-proportional resizing (stretch image to fit). + You must specify 'h' and 'w' to use this option. + (thanks javierØircorion*net) + +v1.3.6 - March 14, 2004 + * Bugfix: was broken when register_globals turned on + (thanks joshgØtwcny*rr*com) + * Bugfix: Images with transparent backgrounds now have + the background color filled with the color specified + by the 'bg' parameter + * Bugfix: ImageCreateFromString() is broken in the + non-bundled GD. Added workaround, but please use + the bundled version of GD if possible + (thanks dnØxbe*ch) + * Bugfix: EXIF thumbnail caching was broken + * Bugfix: EXIF thumbnail handling was broken for PHP + v4.2.x + (thanks smithk1Øshaw*ca) + * Bugfix: Image borders with GD2 were misaligned + * Bugfix: virtual paths/filenames like /~user/foo.jpg + should now work properly, if PHP is installed as an + Apache module (see www.php.net/apache-lookup-uri) + * Bugfix: contents of any non-image file could be + displayed (including PHP & HTML files) + (thanks arsyanØarsyan*com) + * Added rotation parameters 'ra' and 'ar' + (thanks drØrhodes360*com) + * Added $CONFIG['output_allow_enlarging'], defaulted + to false, to prevent smaller-than-max-size images + from being enlarged beyond their original size. If + you want to be able to enlarge images, set this to + false. Can be overridden with the 'aoe' parameter + (thanks dnØxbe*ch) + * Changed all configuration variables to be under one + array named $CONFIG + * Moved color and font options for ErrorImage() to + $CONFIG variables + * Changed cached filename structure (again) to a more + flexible format that can handle future expansion + (old cached files are invalid and will be recreated) + * Added more debugging code to phpThumbDebug + +v1.3.5 - February 29, 2004 + * Added capability to use EXIF thumbnail that may be + embedded in source image (often is in digital camera + JPEGs) and source image dimensions are larger than + $config_max_source_pixels. This will overcome the + limitation where PHP runs out of memory processing + large images (usually >1600x1200). EXIF thumbnail + extraction requires PHP v4.2.0 or higher and EXIF + support compiled into PHP (or php_exif extension) + * Eliminated intermediate read-file-to-memory stage if + image is created from local file. Should allow + larger images to be processed without running out of + memory. + * Added optional 'goto' parameter to be used with the + 'file' parameter, where 'goto' is a URL that is + redirected to after image is rendered to file + (thanks wimbleØwebdonors*com) + * Added optional 'xto' parameter that will bypass all + processing and just return the embedded EXIF + thumbnail, if available. + * Added error-handling if ImageTypes() is unavailable + +v1.3.4 - February 15, 2004 + * Custom error image option (&err=img.jpg) which can + also be set as $config_error_message_image_default + (thanks carlØ4thstar*net) + * &f=text will now output plain-text error messages + * ErrorImage() now used for anti-hotlink messages (if + $config_nohotlink_erase_image is true) + +v1.3.3 - February 5, 2004 + * Bugfix: Added stripslashes() to filenames if + magic_quotes_gpc is enabled + (thanks arsyanØarsyan*com) + * Output can now be rendered to a file only (not to + browser) specified by the 'file' parameter + (thanks arsyanØarsyan*com) + * JPEG quality now has a maximum of 95%, as specified + in the GD documentation + +v1.3.2.1 - February 3, 2004 + * Bugfix: gd_version() was broken for GD v2.0+ + * Bugfix: removed debugging code + +v1.3.2 - February 3, 2004 + * Bugfix: when borders are enabled, portait images + with no width constraint, or landscape images with + no height constraint were smaller than neccesary by + double the border width + (thanks jjjØxs4all*nl) + * Added unsharp mask option thanks to Torstein Hønsi: + http://www.vikjavev.com/hovudsida/umtestside.php + Note: requires GD v2.x to function + (thanks jjjØxs4all*nl) + * Updated cache filenames to reflect new parameters, + this means old cached files will need to be deleted + (or not, they just will never get called again) and + new cached versions will be created. + * Added caching to gd_info() calls for minor speedup + +v1.3.1 - February 2, 2004 + * Added optional border (width and color configurable) + (thanks arsyanØarsyan*com) + * Added option to create fixed-dimension thumbnails + regardless of source aspect ration. Set the 'bw' + (BorderWidth) parameter (even to 0) and this will be + enabled. Outside the actual image will be filled + with 'bg' color (default FFFFFF) + (thanks arsyanØarsyan*com) + +v1.3.0 - January 27, 2004 + * Added watermarking option to overlay thumbnails with + a semi-transparent watermark image (copied from a + seperate source watermark image) + (thanks arsyanØarsyan*com) + * Added option for absolute filenames (on both Windows + and *nix) outside the DOCUMENT_ROOT directory + * Added debug output dump for diagnosing problems) + +v1.2.8 - January 19, 2004 + * added ability to specify relative pathnames as well + as absolute pathnames (pathname is relative to the + location of phpThumb.php if the passed source does + not begin with "/" + +v1.2.7 - January 7, 2004 + * Added patch to allow use of PHP older than 4.1.0 + (or GD without PNG support) for non-GD GIF support + (thanks hostwebserverØhotmail*com) + +v1.2.6 - January 4, 2004 + * Added patch to allow use of PHP older than 4.1.0 + (without the superglobals arrays) + +v1.2.5 - December 26, 2003 + * Added configuration options for default output image + format and max width/height + +v1.2.4 - December 20, 2003 + * Bugfix: temp directory for non-native GD support not + always returning valid directory + * Caching feature reintroduced (see configuration) + +v1.2.3 - December 19, 2003 + * Added anti-hotlink code so the thumbnail script on + one domain cannot be used by another domain. The + list of allowed domains defaults to the current + domain but is configurable below as + $config_nohotlink_valid_domains. The message, text + size, colors and whether to blank the image or not + are also configurable + * Bugfix: URL image sources were not able to use the + non-GD GIF-reading functions + +v1.2.2 - December 17, 2003 + * Added option to use http:// URL as image source + +v1.2.1 - December 11, 2003 + * Added option to get source data from a database + rather than a physical file + * Bugfix: resize not proportional when wide image + limited more by max height than max width + Thanks mathias_strasserØgmx*net + * Removed caching code + +v1.2.0 - December 10, 2003 + * Added GIF support for versions of GD that do not + have built-in GIF support (v1.6.x) via the "GIF + Util" class by Fabien Ezber (www.yamasoft.com) + GD's built-in GIF-reading functions are faster, and + are present in PHP v4.3.0 or newer, but all versions + of GD can display resized GIF thumbnails now. + +v1.1.2 - October 26, 2003 + * check for source image existance to prevent text + error messages + * if GD not available, a GIF saying "no GD" is shown + instead of showing the original image + * Cache feature introduced + +v1.1.1 - September 28, 2003 + * better resize code by sfisher10Øcox*net + +v1.1.0 - September 1, 2003 + * initial public release + * thumbnails can now be larger than source image + * graphical error messages + +v1.0.0 - January 7, 2002 + * initial private release diff --git a/site/racecalendar/phpthumb/docs/phpthumb.faq.txt b/site/racecalendar/phpthumb/docs/phpthumb.faq.txt new file mode 100644 index 0000000..070fb99 --- /dev/null +++ b/site/racecalendar/phpthumb/docs/phpthumb.faq.txt @@ -0,0 +1,203 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// Frequently Asked Questions (FAQ) about phpThumb() // +// /// +////////////////////////////////////////////////////////////// + + +Q: My question isn't answered here and I can't find any + forums, how do I get support? +A: Please email me directly at info@silisoftware.com with + any questions, suggestions, donations, etc. + + +Q: What is the GPL? Can I use this for commercial sites? +A: See the GPL FAQ: http://www.gnu.org/licenses/gpl-faq.html + In general, if you just want to call phpThumb.php in the + standard manner + then there is no problem, you're free to do this no matter + if you site is commercial or not, or what license your code + is released under. + If you're calling phpThumb() as an object then you will + probably run into license issues, so consult the above FAQ + and the GPL itself. + No matter if you use phpThumb() commercially or not, no + payment is required. However, donations are always welcome + and can be made at http://phpthumb.sourceforge.net + + +Q: Some images generate thumbnails, but some fail (the original + non-resized image is output instead). +A: Your PHP installation does not have a high enough memory_limit + and ImageMagick is not installed on the server. The PHP memory + required is 5 times the number of pixels in the image. + For example: + 640x480x5 = 1.5MB + 1600x1200x5 = 9.2MB + You can adjust the PHP memory limit in php.ini (if you have + permission on your server to do so), or (better yet) install + ImageMagick on the server and that will bypass the memory limit + issue. If you can't do either of the above, you can resize the + images manually (with your favourite image editor) to a size + that your memory_limit setting can handle, and/or you can + re-save the images with an image editor that can embed an EXIF + thumbnail (Photoshop for example) which phpThumb can use as an + image source (lower image quality, but perhaps better than + nothing). + + +Q: I'm getting is this error message: + Failed: RenderToFile() failed because + !is_resource($this->gdimg_output) +A: You missed the call to GenerateThumbnail() before + RenderToFile() or OutputThumbnail. + See /demo/phpThumb.demo.object.php for an example. + + +Q: I'm trying to save a phpThumb-generated image in Internet + Explorer and it saves in BMP format, why? +A: This is not phpThumb's fault, it is an IE issue: + http://support.microsoft.com/default.aspx?scid=kb;en-us;810978 + http://support.microsoft.com/default.aspx?scid=kb;en-us;260650 + + +Q: PNG images with transparent areas show up with gray background + in the areas that are supposed to be transparent. +A: Internet Explorer has had a broken PNG alpha-channel display + implementation for a decade, so it may never get fixed. Other + major browsers generally handle alpha-transparent PNGs fine. + See http://www.silisoftware.com/png_transparency/ + For an alpha-channel PNG display in IE hack, see this page: + http://www.koivi.com/ie-png-transparency/ + + +Q: I'm getting " does not exist" when I know the + file does exist +A: Check these two values are present and properly configured + in phpThumb.config.php (introduced in v1.6.0): + $PHPTHUMB_CONFIG['allow_src_above_docroot'] (default=false) + $PHPTHUMB_CONFIG['allow_src_above_phpthumb'] (default=true) + If your images are outside DOCUMENT_ROOT then you will have + to configure 'allow_src_above_docroot' to true. + + +Q: Should I use phpThumb.php, or use phpThumb() as an object? +A: phpThumb.php is easier to use (less coding) for basic uses. + phpThumb.php handles all caching; your own object will need + to have its own caching code. If you just want to display a + thumbnailed version of an existing image, use phpThumb.php + If you want to render one (or more) thumbnails to static + files (during upload, for example), that's an appropriate + use for the object mode. Also, phpThumb.config.php is only + used by phpThumb.php, so if you instantiate your own object + you need to manually set all configuration options because + phpThumb.config.php has NO effect. So, to repeat: + **always use phpThumb.php unless you NEED to have an object** + + +Q: Are there any front-end GUI interfaces to phpThumb()? +A: See /demo/readme.demo.txt + + +Q: Are there / have there been any security issues in phpThumb? +A: http://secunia.com/product/5199/ + + +Q: Why can't Flash work with images output from phpThumb()? +A: Flash doesn't like progressive JPEG. Set: + $PHPTHUMB_CONFIG['output_interlace'] = false; + + +Q: Image quality is not very good - why? +A: If you're using GD v1.x, no way around it. Upgrade to GD v2.x + + +Q: Image quality is very bad, very pixelated -- why? +A: You may be trying to resize images larger than the available + PHP memory, so phpThumb is simply extracting and using the + EXIF thumbnail as the image source, which is usually about + 160x120 (so if you resize it to 640x480 it will look very bad). + To calculate the required size for memory_limit in php.ini, + calculate the number of pixels in the image and multiply by 5: + For example, 1600x1200 = 1600 * 1200 * 5 = 9600000 = 10M + + +Q: Can I save the generated thumbnail to a file? +A: Yes, there are several ways to do so; the best way is to call + phpThumb as an object and call RenderToFile() to save the + thumbnail to whatever filename you want. + See /demo/phpThumb.demo.object.php for an example. + The other way is to use the 'file' parameter (see + /docs/phpthumb.readme.txt) but this parameter is deprecated + and may not exist in future versions of phpThumb(). + + +Q: "Off-server thumbnailing is not allowed" -- how do I enable it? +A: By default, phpThumb() only makes thumbnails for the same domain + that it is running on. To allow it to make thumbnails for a limited + number of other domains, add them (in phpThumb.config.php) like this: + $PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array( + @$_SERVER['HTTP_HOST'], 'example.com', 'www.example.com', + 'subdomain.example.net', 'example.org'); + To disable off-server thumbnail blocking, just set: + $PHPTHUMB_CONFIG['nohotlink_enabled'] = false; + + +Q: Is it possible to set the parameters (like w/h/fltr[]) in the config, + so that they can't be changed over the URL? +A: Take a look at $PHPTHUMB_DEFAULTS at the bottom of phpThumb.config.php + You'll want to set $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE=false, + possibly also $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS=true. + You may also want to investigate $PHPTHUMB_CONFIG['high_security_enabled'] + (see the example at the bottom of phpThumb.config.php for how to call + images in HighSecurity mode. + + +Q: Is there a way to use phpThumb() object to create thumbnails without the + parameters in the URL showing the location of the image etc? +A: There is a demo in /demo/phpThumb.demo.object.php. You could modify this + into your own file, but there still remains the problem of passing + parameters to the file, whether it's phpThumb.php or your own instantiation + of a phpThumb() object. I would suggest is putting as many of the common + parameters into phpThumb.config.php as possible under $PHPTHUMB_DEFAULTS, + so you then don't have to pass them for each image. If you don't want people + modifying the parameters, turn on $PHPTHUMB_CONFIG['high_security_enabled'] + and set a password (you'll need to generate the tags with phpThumbURL() + provided at the bottom of phpThumb.config.php). If you don't want people + accessing your source images at all, you can place them outside DOCUMENT_ROOT + on your server (as long as phpThumb/PHP has read access to the directory). + The other option is to put your source images in a MySQL database and set + $PHPTHUMB_CONFIG['mysql_query'] and related parameters in phpThumb.config.php + to pull your source images from the database. That way it's impossible to + retrieve the images except through phpThumb.php, and if high_security is enabled, + then nobody can modify the parameters to view anything except what you want to show. + So, yes, it's possible to use your own object, but it's probably better to use + phpThumb.php if possible -- one notable issue is that phpThumb.php handles all + the caching, so you're on your own to deal with that if you create your own object. + + +Q: phpThumb runs slowly, as if the images aren't cached, when I use HTTP source + images (not on my server). How can I make it go faster? +A: $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; + // if true, remote source images will not be checked for modification date and + // cached image will be used if available, even if source image is changed or removed + + +Q: What does the "cache_default_only_suffix" configuration option do? +A: Cache files are normally created with big ugly names like + "phpThumb_cache_www.example.com_src1a482c2c760463795ff18faf073b389f_par3e099041c2f4a73041a7f5d7e7fc481a_dat1119952152.jpeg" + but if cache_default_only_suffix is enabled, cache filenames are simplified to + "pic_thumb.jpg" (for example). The problem is that only one version of that + thumbnail is possible, and you can never call it again with a different size, + or different filters, etc. Generally you don't want that enabled, but it's + there because some people asked for it. + + +Q: Why is the visual size of rotated images smaller than the unrotated images? +A: phpThumb fits the rotated image into the 'w' and 'h' dimensions. + Try not specifying a 'w' parameter: phpThumb.php?src=file.png&ra=15 + That should leave the image the apparent same size as the unrotated image + (in actual fact the canvas size is enlarged to fit the rotated image in it). diff --git a/site/racecalendar/phpthumb/docs/phpthumb.license.txt b/site/racecalendar/phpthumb/docs/phpthumb.license.txt new file mode 100644 index 0000000..9fec808 --- /dev/null +++ b/site/racecalendar/phpthumb/docs/phpthumb.license.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/site/racecalendar/phpthumb/docs/phpthumb.readme.txt b/site/racecalendar/phpthumb/docs/phpthumb.readme.txt new file mode 100644 index 0000000..01e6839 --- /dev/null +++ b/site/racecalendar/phpthumb/docs/phpthumb.readme.txt @@ -0,0 +1,527 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// This code is released under the GNU GPL: // +// http://www.gnu.org/copyleft/gpl.html // +// // +// +-----------------------------------------------+ // +// | phpThumb() is free to use according to the | // +// | terms of the GPL. Donations also gratefully | // +// | GPL FAQ: http://gnu.org/licenses/gpl-faq.html | // +// | | // +// | Donations are gratefully accepted from happy | // +// | users :) See http://phpthumb.sourceforge.net | // +// | | // +// | If you like phpThumb(), please consider | // +// | writing a review at HotScripts.com: | // +// | http://www.hotscripts.com/Detailed/25654.html | // +// | | // +// | If you do use this code somewhere, send me | // +// | an email and tell me how/where you used it. | // +// +-----------------------------------------------+ // +// /// +////////////////////////////////////////////////////////////// + +============ +Description: +============ + +phpThumb() uses the GD library to create thumbnails from +images (GIF, PNG or JPEG) on the fly. The output size is +configurable (can be larger or smaller than the source), +and the source may be the entire image or only a portion +of the original image. True color and resampling is used +if GD v2.0+ is available, otherwise low-color and simple +resizing is used. Source image can be a physical file on +the server or can be retrieved from a database. GIFs are +supported on all versions of GD even if GD does not have +native GIF support thanks to the GIFutil class by Fabien +Ezber. AntiHotlinking feature prevents other people from +using your server to resize their thumbnails, or link to +your images from another server. The cache feature +reduces server load. + + +====== +Usage: +====== + +Call phpThumb() just like you would a normal image. +Examples: + + +See the "demo" link on http://phpthumb.sourceforge.net +for more usage examples). Parameters that can be passed +are listed below under "URL Parameters". + +NOTE: It's recommended you use the local image filename +wherever possible (rather than http://) because performance +is much better, less (or no) use of temp files, and the +last-modified check for cached files doesn't work for +remote files. + +To access files over a LAN with Windows share names you +must use the network name (or IP) and not a mapped drive +name, for example: + //othercomputer/file.jpg - good + //192.168.2.1/file.jpg - good + z:/file.jpg - won't work +This is a PHP limitation (see www.php.net/file-exists) +Note: you may want to use "/" slashes instead of "\" if +you have magic_quotes_gpc enabled to avoid stripslashes +problems, although either slash should work if +magic_quotes_gpc is disabled + + +================================ +Alternate PATH_INFO-style Usage: +================================ + +phpThumb.php can also be called by passing parameters not +after the usual "?" but like this: + phpThumb.php/=;x; +For example: + phpThumb.php/100;pic.jpg + phpThumb.php/100;images/pic.jpg + phpThumb.php/100;/images/pic.jpg + phpThumb.php/100x200;pic.jpg + phpThumb.php/x200;pic.jpg + phpThumb.php/f=jpeg;q=50;100x200;pic.jpg + phpThumb.php/fltr[]=usm;100;pic.jpg + + must be the last item. Dimensions must be the second- +last item. As many key/value pairs for parameters can be +passed before those last two items, with each pair joined by +equals ("=") and seperated by semicolon (";") + + +============== +Configuration: +============== + +There are some configuration options you may (but are +not required to) change. Most configuration options can +be set when you call phpThumb() - see list below), but +default configuration options (such as cache directory) +are in phpThumb.config.php - this is the only file you +should ever modify. + +The configuration file is distributed as +phpThumb.config.php.default to prevent accidental +overwriting of old configuration settings. Please +migrate your old settings to the new file (if upgrading), +or delete your old config and rename the default to +phpThumb.config.php + + +The amount of memory required for phpThumb depends on +several factors: the dimensions of the source image, +the dimensions of the output image, whether unsharp +masking is applied, whether watermarks are applied, etc. +The auto-detection of memory limits works as a general +"safe" value. You may be able to exceed the auto value +by a small or large amount, depending on whether you +apply watermarks and/or sharpening, and the output size +of your thumbnails. I do not currently have a reliable +formula for calculating such things, but I will attempt +to craft one for future versions of phpThumb(). Until +then, set "max_source_pixels" in phpThumb.config.php to a +value that works well for you (or leave it alone if the +defaults give you no problems). + +The configuration options you should maybe modify are: +* cache_directory - thumbnailing is slow and processor- + intensive. Enabling caching will dramatically speed + up future thumbnail serving +* max_source_pixels - This should be auto-detected, but + if auto-detection fails and you get an invalid image + from large source images, set this to about 20% of + your available PHP memory limit. +* imagemagick_path - If the source image is larger than + max_source_pixels allows, but ImageMagick is available + phpThumb() will use it to generate the thumbnail. + + +/////////////////////////////////////////////////////////// +Note: High-Security mode is recommended enabled if possible. + Set $PHPTHUMB_CONFIG['high_security_enabled'] in + phpThumb.config.php to enable it. Each call to phpThumb + needs to be made through the function supplied at the + bottom of phpThumb.config.php which create the hash: + require_once('phpThumb.config.php'); + echo ''; +/////////////////////////////////////////////////////////// + + +============================================== +Calling as an object (not using phpThumb.php): +============================================== + +NOTE: most people don't need to and should not do this. +If you just want to display resized images, please just +use phpThumb.php, not the object mode. To render output +to one (or more) files instead of the browser, you should +skip phpThumb.php and instantiate your own object. Please +take a look at /demo/phpThumb.demo.object.php for details. + +Note: phpThumb.php is where the caching code is located, if + you instantiate your own phpThumb() object that code is + bypassed and it's up to you to handle the reading and + writing of cached files. + + +=============== +URL Parameters: +=============== + + src = filename of source image + new = create new image, not thumbnail of existing image. + Requires "w" and "h" parameters set. + [ex: &new=FF0000|75] - red background, 75% opacity + Set to hex color string of background. Opacity is + optional (defaults to 100% opaque). + w = max width of output thumbnail in pixels + h = max height of output thumbnail in pixels + wp = max width for portrait images + hp = max height for portrait images + wl = max width for landscape images + hl = max height for landscape images + ws = max width for square images + hs = max height for square images + f = output image format ("jpeg", "png", or "gif") + q = JPEG compression (1=worst, 95=best, 75=default) + sx = left side of source rectangle (default = 0) + (values 0 < sx < 1 represent percentage) + sy = top side of source rectangle (default = 0) + (values 0 < sy < 1 represent percentage) + sw = width of source rectangle (default = fullwidth) + (values 0 < sw < 1 represent percentage) + sh = height of source rectangle (default = fullheight) + (values 0 < sh < 1 represent percentage) + zc = zoom-crop. Will auto-crop off the larger dimension + so that the image will fill the smaller dimension + (requires both "w" and "h"). Set "zc=1" to enable. + (overrides both "iar" and "far") + bg = background hex color (default = FFFFFF) + bc = border hex color (default = 000000) +fltr = filter system. Call as an array as follows: + - "brit" (Brightness) [ex: &fltr[]=brit|] + where is the amount +/- to adjust brightness + (range -255 to 255) + Availble in PHP5 with bundled GD only. + - "cont" (Constrast) [ex: &fltr[]=cont|] + where is the amount +/- to adjust contrast + (range -255 to 255) + Availble in PHP5 with bundled GD only. + - "gam" (Gamma Correction) [ex: &fltr[]=gam|] + where can be a number >0 to 10+ (default 1.0) + Must be >0 (zero gives no effect). There is no max, + although beyond 10 is pretty useless. Negative + numbers actually do something, maybe not quite the + desired effect, but interesting nonetheless. + - "sat" (SATuration) [ex: &fltr[]=sat|] + where is a number between zero (no change) + and -100 (complete desaturation = grayscale), or it + can be any positive number for increased saturation. + - "ds" (DeSaturate) [ex: &fltr[]=ds|] + is an alias for "sat" except values are inverted + (positive values remove color, negative values boost + saturation) + - "gray" (Grayscale) [ex: &fltr[]=gray] + remove all color from image, make it grayscale + - "th" (Threshold) [ex: &fltr[]=th|] + makes image greyscale, then sets all pixels brighter + than (range 0-255) to white, and all pixels + darker than to black + - "rcd" (Reduce Color Depth) [ex: &fltr[]=rcd||] + where is the number of colors (2-256) you want + in the output image, and is "1" for dithering + (deault) or "0" for no dithering + - "clr" (Colorize) [ex: &fltr[]=clr||] + where is a number between 0 and 100 for the + amount of colorization, and is the hex color + to colorize to. + - "sep" (Sepia) [ex: &fltr[]=sep||] + where is a number between 0 and 100 for the + amount of colorization (default=50), and is + the hex color to colorize to (default=A28065). + Note: this behaves differently when applied by + ImageMagick, in which case 80 is default, and lower + values give brighter/yellower images and higher + values give darker/bluer images + - "usm" (UnSharpMask) [ex: &fltr[]=usm|||] + where is the amount (default = 80), is the + radius (default = 0.5), is the threshold + (default = 3). + - "blur" (Blur) [ex: &fltr[]=blur|] + where (0 < < 25) (default = 1) + - "gblr" (Gaussian Blur) [ex: &fltr[]=gblr] + Availble in PHP5 with bundled GD only. + - "sblr" (Selective Blur) [ex: &fltr[]=gblr] + Availble in PHP5 with bundled GD only. + - "smth" (Smooth) [ex: &fltr[]=smth|] + where is the weighting value for the matrix + (range -10 to 10, default 6) + Availble in PHP5 with bundled GD only. + - "lvl" (Levels) [ex: &fltr[]=lvl||| + where can be one of 'r', 'g', 'b', 'a' (for + Red, Green, Blue, Alpha respectively), or '*' for all + channels based on average grayscale value (default). + and are the clip points for the levels + and are set to clip 0.1% of each end by default. + (range = 0-255) and are set to clip 0.1% of each end + by default. Use -1 for min and/or max to invoke auto- + detect mode. Using default parameters (&fltr[]=lvl) + is similar to Auto Contrast in Adobe Photoshop. + - "wb" (White Balance) [ex: &fltr[]=wb|] + where is the target hex color to white balance + on, this color is what "should be" white, or light + gray. The filter attempts to maintain brightness so + any gray color can theoretically be used. If is + omitted the filter guesses based on brightest pixels + in each of RGB + - "hist" (Histogram) + [ex: &fltr[]=hist|||||||] + Where is the color band(s) to display, from back + to front (one or more of "rgba*" for Red Green Blue + Alpha and Grayscale respectively); + is a semicolon-seperated list of hex colors to + use for each graph band (defaults to FF0000, 00FF00, + 0000FF, 999999, FFFFFF respectively); + and are the width and height of the overlaid + histogram in pixels, or if <= 1 then percentage of + source image width/height; + is the alignment (same as for "wmi" and "wmt"); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent + - "over" (OVERlay/underlay image) overlays an image on + the thumbnail, or overlays the thumbnail on another + image (to create a picture frame for example) + [ex: &fltr[]=over||||] + where is the image filename; is "0" (default) + for overlay the image on top of the thumbnail or "1" + for overlay the thumbnail on top of the image; is + the margin - can be absolute pixels, or if < 1 is a + percentage of the thumbnail size [must be < 0.5] + (default is 0 for overlay and 10% for underlay); + is opacity (0 = transparent, 100 = opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + (thanks raynerapeØgmail*com, shabazz3Ømsu*edu) + - "wmi" (WaterMarkImage) + [ex: &fltr[]=wmi||||] where + is the filename of the image to overlay; + is the alignment (one of BR, BL, TR, TL, C, + R, L, T, B, *) where B=bottom, T=top, L=left, + R=right, C=centre, *=tile); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent + - "wmt" (WaterMarkText) + [ex: &fltr[]=wmt|||||||||||] + where: + is the text to use as a watermark; + Any instance of metacharacters will be replaced + with their calculated value. Currently supported: + ^Fb = source image filesize in bytes + ^Fk = source image filesize in kilobytes + ^Fm = source image filesize in megabytes + ^X = source image width in pixels + ^Y = source image height in pixels + ^x = thumbnail width in pixels + ^y = thumbnail height in pixels + ^^ = the character ^ + is the font size (1-5 for built-in font, or point + size for TrueType fonts); + is the alignment (one of BR, BL, TR, TL, C, R, L, + T, B, * where B=bottom, T=top, L=left, R=right, + C=centre, *=tile); + is the hex color of the text; + is the filename of the TTF file (optional, if + omitted a built-in font will be used); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent; + is the angle + is the hex color of the background; + is background opacity from 0 (transparent) to + 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the direction(s) in which the background is + extended (either 'x' or 'y' (or both, but both + will obscure entire image)) + Note: works with TTF fonts only, not built-in + (thanks mailØmmjaeger*com, craigØpc-fanatics*com) + - "flip" [ex: &fltr[]=flip|x or &fltr[]=flip|y] + flip image on X or Y axis + - "ric" [ex: &fltr[]=ric||] + rounds off the corners of the image (to transparent + for PNG output), where is the horizontal radius + of the curve and is the vertical radius + - "elip" [ex: &fltr[]=elip] + similar to rounded corners but more extreme + - "mask" [ex: &fltr[]=mask|filename.png] + greyscale values of mask are applied as the alpha + channel to the main image. White is opaque, black + is transparent. + - "bvl" (BeVeL) [ex: &fltr[]=bvl|||] + where is the bevel width, is the hex color + for the top and left shading, is the hex color + for the bottom and right shading + - "bord" (BORDer) [ex: &fltr[]=bord|||| + where is the width in pixels, and are + horizontal and vertical radii for rounded corners, + and is the hex color of the border + - "fram" (FRAMe) draws a frame, similar to "bord" but + more configurable + [ex: &fltr[]=fram|||||] + where is the width of the main border, is + the width of each side of the bevel part, is the + hex color of the main border, is the highlight + bevel color, is the shadow bevel color + - "drop" (DROP shadow) + [ex: &fltr[]=drop||||] + where is distance from image to shadow, is + width of shadow fade (not yet implemented), is + the hex color of the shadow, and is the angle of + the shadow (default=225) +file = if set then thumbnail will be rendered to this + filename, not output and not cached. + (Deprecated. Disabled by default since v1.6.0. + You should instantiate your own object instead) +goto = URL to redirect to after rendering image to file + * Must begin with "http://" + * Requires file parameter set + (Deprecated. Disabled by default since v1.6.0. + You should instantiate your own object instead) + err = custom error image filename instead of showing + error messages (for use on production sites) +md5s = MD5 hash of the source image -- if this parameter is + passed with the hash of the source image then the + source image is not checked for existance or + modification and the cached file is used (if + available). If 'md5s' is passed an empty string then + phpThumb.php dies and outputs the correct MD5 hash + value. This parameter is the single-file equivalent + of 'cache_source_filemtime_ignore_*' configuration + paramters + xto = EXIF Thumbnail Only - set to only extract EXIF + thumbnail and not do any additional processing + ra = Rotate by Angle: angle of rotation in degrees + positive = counterclockwise, negative = clockwise + ar = Auto Rotate: set to "x" to use EXIF orientation + stored by camera. Can also be set to "l" or "L" + for landscape, or "p" or "P" for portrait. "l" + and "P" rotate the image clockwise, "L" and "p" + rotate the image counter-clockwise. + aoe = Output Allow Enlarging - override the setting for + $CONFIG['output_allow_enlarging'] (1=on, 0=off) + ("far" and "iar" both override this and allow output + larger than input) + iar = Ignore Aspect Ratio - disable proportional resizing + and stretch image to fit "h" & "w" (which must both + be set). (1=on, 0=off) (overrides "far") + far = Force Aspect Ratio - image will be created at size + specified by "w" and "h" (which must both be set). + Alignment: L=left,R=right,T=top,B=bottom,C=center + BL,BR,TL,TR use the appropriate direction if the + image is landscape or portrait. +maxb = MAXimum Byte size - output quality is auto-set to + fit thumbnail into "maxb" bytes (compression + quality is adjusted for JPEG, bit depth is adjusted + for PNG and GIF) +down = filename to save image to. If this is set the + browser will prompt to save to this filename rather + than display the image + + + +============== +General Notes: +============== + +* Always use the local image filename wherever possible + rather than a full http:// URL because performance is + much better, less (or no) use of temp files, and the + last-modified check for cached files doesn't work for + remote files. For example: + good: phpThumb.php?src=/images/nicepic.jpg + bad: phpThumb.php?src=/home/httpd/example/images/nicepic.jpg + worse: phpThumb.php?src=http://example.com/images/nicepic.jpg + +* Thumbnails will be scaled proportionately to fit in a + box of at most (width * height) pixels + (unless "iar" is set) + +* Thumbnail caching for URL or database sources requires + an absolute directory name for $config_cache_directory + Physical file cached thumbnails will be recreated if + the source file changes, but remote/database files + cannot (modification time isn't readily available) + +* If you need a GUI interface to phpThumb(), or for a user + to specify crop settings, or something like that please + see the list of known programs in /demo/readme.demos.txt + +* Cropping images can be specified with either exact pixel + values for sx/sy/sw/sh parameters, or if those are set + to a value >0 and <1 then these are interpreted as a + percentage of the source image width/height. For example, + to crop 25% off all sides, you would specify parameters: + phpThumb.php?src=pic.jpg&sx=.25&sy=.25&sw=.5&sh=.5 + +* phpThumb() may have tempfile access issues on servers + where Safe Mode is enabled, specificly when accessing + a file over HTTP, or when a non-bundled version of GD + is in use. Specifying "config_temp_directory" may help + +* Properly resolving /~user/ style filenames requires + apache_lookup_uri(), which is missing or broken in + Apache2, or if PHP is not installed as an Apache module. + phpThumb() does try and work around this if it is + unavailble, but you may have to specify a full filename + for "src" if you encounter problems. + +* phpThumb() should work with PHP v4.0.6+, but seems to + have a few quirks before v4.1.0 + EXIF thumbnail extraction requires PHP v4.2.0+ + Image rotation requires PHP v4.3.0+. There have been + reports of problems with PHP older than v4.3.3 + Some image filters require PHP v5.0.0+ + Run /demo/phpThumb.demo.check.php to examine your server + +* phpThumb() works better and faster when ImageMagick is + available. Most functions will work with only GD2, but + speed is much faster with ImageMagick, and much larger + images can be processed with ImageMagick than GD. + +* phpThumb() works with GD v1.x, but works better with + GD v2.0+ because of the true-color image support + and ImageCopyResampled(). Also, there appears to be a + bug in ImageCopyResized() which is used with GD v1.x + where the bottom and/or right line of pixels is set + to the background color (due to a rounding error?) + NOTE: Please use the bundled version of GD if at all + possible (with PHP v4.3.0+) because the non-bundled + version has bugs which may cause PHP to crash: + * http://bugs.php.net/bug.php?id=21518 + * http://bugs.php.net/bug.php?id=24174 + phpThumb() has a workaround for the above bug but + there may be other bugs, and the workaround is slow. + Alpha transparent output requires GD >= 2.0.1 and + PHP >= 4.3.2 + Most (if not all) filters require GD v2.x to function + at all. But many filters can be handled by ImageMagick + instead of GD. + +* Filters handled by ImageMagick or GD: + - brit;cont;ds;sat;gray;clr;sep;gam;neg;th;rcd;flip;edge; + emb;lvl;blur;gblr;usm; +* Filters handled only by ImageMagick: + - none yet +* Filters handled only by GD + PHP5: + - sblr;mean;smth; +* Filters handled only by GD2: + - bvl;wmi;wmt;over;wb;hist;fram;drop;mask;elip;ric;bord; diff --git a/site/racecalendar/phpthumb/fonts/readme.txt b/site/racecalendar/phpthumb/fonts/readme.txt new file mode 100644 index 0000000..2e5ef72 --- /dev/null +++ b/site/racecalendar/phpthumb/fonts/readme.txt @@ -0,0 +1,5 @@ +This is the default location for TTF fonts. + +You can safely delete or ignore this directory if you're not using +TTF fonts for text watermarks. You can also specify an alternate +directory in phpThumb.config.php \ No newline at end of file diff --git a/site/racecalendar/phpthumb/index.php b/site/racecalendar/phpthumb/index.php new file mode 100644 index 0000000..a722861 --- /dev/null +++ b/site/racecalendar/phpthumb/index.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/site/racecalendar/phpthumb/lee.jpg b/site/racecalendar/phpthumb/lee.jpg new file mode 100644 index 0000000..dcc65fb Binary files /dev/null and b/site/racecalendar/phpthumb/lee.jpg differ diff --git a/site/racecalendar/phpthumb/phpThumb.config.php b/site/racecalendar/phpthumb/phpThumb.config.php new file mode 100644 index 0000000..2a0a8ce --- /dev/null +++ b/site/racecalendar/phpthumb/phpThumb.config.php @@ -0,0 +1,241 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!file_exists(dirname(__FILE__).'/phpthumb.functions.php') || !include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once(phpthumb.functions.php) - realpath="'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'"'); +} +ob_end_clean(); + +// START USER CONFIGURATION SECTION: + +// * DocumentRoot configuration +// phpThumb() depends on $_SERVER['DOCUMENT_ROOT'] to resolve path/filenames. This value is usually correct, +// but has been known to be broken on some servers. This value allows you to override the default value. +// Do not modify from the auto-detect default value unless you are having problems. +//$PHPTHUMB_CONFIG['document_root'] = '/home/httpd/httpdocs'; +//$PHPTHUMB_CONFIG['document_root'] = 'c:\\webroot\\example.com\\www'; +//$PHPTHUMB_CONFIG['document_root'] = $_SERVER['DOCUMENT_ROOT']; +//$PHPTHUMB_CONFIG['document_root'] = realpath((@$_SERVER['DOCUMENT_ROOT'] && file_exists(@$_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'])) ? $_SERVER['DOCUMENT_ROOT'] : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', realpath('.')))); +$PHPTHUMB_CONFIG['document_root'] = realpath((getenv('DOCUMENT_ROOT') && ereg('^'.preg_quote(realpath(getenv('DOCUMENT_ROOT'))), realpath(__FILE__))) ? getenv('DOCUMENT_ROOT') : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__)))); + +// * Cache directory configuration (choose only one of these - leave the other lines commented-out): +// Note: this directory must be writable (usually chmod 777 is neccesary) for caching to work. +// If the directory is not writable no error will be generated but caching will be disabled. +$PHPTHUMB_CONFIG['cache_directory'] = dirname(__FILE__).'/cache/'; // set the cache directory relative to the phpThumb() installation +//$PHPTHUMB_CONFIG['cache_directory'] = $PHPTHUMB_CONFIG['document_root'].'/phpthumb/cache/'; // set the cache directory to an absolute directory for all source images +//$PHPTHUMB_CONFIG['cache_directory'] = './cache/'; // set the cache directory relative to the source image - must start with '.' (will not work to cache URL- or database-sourced images, please use an absolute directory name) +//$PHPTHUMB_CONFIG['cache_directory'] = null; // disable thumbnail caching (not recommended) + +$PHPTHUMB_CONFIG['cache_disable_warning'] = false; // If [cache_directory] is non-existant or not writable, and [cache_disable_warning] is false, an error image will be generated warning to either set the cache directory or disable the warning (to avoid people not knowing about the cache) + + +// * Cache culling: phpThumb can automatically limit the contents of the cache directory +// based on last-access date and/or number of files and/or total filesize. + +//$PHPTHUMB_CONFIG['cache_maxage'] = null; // never delete cached thumbnails based on last-access time +$PHPTHUMB_CONFIG['cache_maxage'] = 86400 * 30; // delete cached thumbnails that haven't been accessed in more than [30 days] (value is maximum time since last access in seconds to avoid deletion) + +//$PHPTHUMB_CONFIG['cache_maxsize'] = null; // never delete cached thumbnails based on byte size of cache directory +$PHPTHUMB_CONFIG['cache_maxsize'] = 10 * 1024 * 1024; // delete least-recently-accessed cached thumbnails when more than [10MB] of cached files are present (value is maximum bytesize of all cached files) + +//$PHPTHUMB_CONFIG['cache_maxfiles'] = null; // never delete cached thumbnails based on number of cached files +$PHPTHUMB_CONFIG['cache_maxfiles'] = 200; // delete least-recently-accessed cached thumbnails when more than [500] cached files are present (value is maximum number of cached files to keep) + + +// * Source image cache configuration +$PHPTHUMB_CONFIG['cache_source_enabled'] = false; // if true, source images obtained via HTTP are cached to $PHPTHUMB_CONFIG['cache_source_directory'] +$PHPTHUMB_CONFIG['cache_source_directory'] = dirname(__FILE__).'/cache/source/'; // set the cache directory for unprocessed source images + +// * cache source modification date configuration +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_local'] = false; // if true, local source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; // if true, remote source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed. WARNING: cached performance MUCH slower if this is set to false. + + +// * Simplified cache filename configuration +// Instead of creating unique cache filenames for all parameter combinations, create "simple" cache files (eg: "pic_thumb.jpg") +// If cache_default_only_suffix is non-empty, GETstring parameters (except 'src') are ignored and only $PHPTHUMB_DEFAULTS +// parameters (set at the bottom of phpThumb.config.php) are used for processing. +// The '*' character MUST be used to represent the source image name +$PHPTHUMB_CONFIG['cache_default_only_suffix'] = ''; // cached in normal phpThumb manner +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = '*_thumb'; // cache 'pic.jpg' becomes 'pic_thumb.jpg' (or 'pic_thumb.png' if PNG output is selected, etc) +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = 'small-*'; // cache 'pic.jpg' becomes 'small-pic.jpg' (or 'small-pic.png' if PNG output is selected, etc) + +$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache_'.str_replace('www.', '', @$_SERVER['SERVER_NAME']); +//$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache'; // allow phpThumb to share 1 set of cached files even if accessed under different servername/domains on same server + +$PHPTHUMB_CONFIG['cache_force_passthru'] = true; // if true, cached image data will always be passed to browser; if false, HTTP redirect will be used instead + + + +// * Temp directory configuration +// phpThumb() may need to create temp files. Usually the system temp dir is writable and can be used. +// Leave this value as NULL in most cases. If you get errors about "failed to open for writing" +// you should change this to a full pathname to a directory you do have write access to. +//$PHPTHUMB_CONFIG['temp_directory'] = '/tmp/'; +$PHPTHUMB_CONFIG['temp_directory'] = null; + + +// maximum number of pixels in source image to attempt to process entire image. +// If this is zero then no limit on source image dimensions. +// If this is nonzero then this is the maximum number of pixels the source image +// can have to be processed normally, otherwise the embedded EXIF thumbnail will +// be used (if available) or an "image too large" notice will be displayed. +// This is to be used for large source images (> 1600x1200) and low PHP memory +// limits. If PHP runs out of memory the script will usually just die with no output. +// To calculate this number, multiply the dimensions of the largest image +// you can process with your memory limitation (e.g. 1600 * 1200 = 1920000) +// As a general guideline, this number will be about 20% of your PHP memory +// configuration, so 8M = 1,677,722; 16M = 3,355,443; 32M = 6,710,886; etc. +if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && !defined('memory_get_usage') && !@ini_get('memory_limit')) { + // memory_get_usage() will only be defined if your PHP is compiled with the --enable-memory-limit configuration option. + $PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit +} else { + // calculate default max_source_pixels as 20% of memory limit configuration + $PHPTHUMB_CONFIG['max_source_pixels'] = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); + //$PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 1920000; // allow 1600x1200 images (2Mpx), no larger (about 10MB memory required) + //$PHPTHUMB_CONFIG['max_source_pixels'] = 3355443; // 16MB memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 3871488; // allow 2272x1704 images (4Mpx), no larger (about 16MB memory required) +} + + +// ImageMagick configuration +// If source image is larger than available memory limits as defined above in +// 'max_source_pixels' AND ImageMagick's "convert" program is available, phpThumb() +// will call ImageMagick to perform the thumbnailing of the source image to bypass +// the memory limitation. Leaving the value as NULL will cause phpThumb() to +// attempt to detect ImageMagick's presence with `which` +if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + // Windows: set absolute pathname + $PHPTHUMB_CONFIG['imagemagick_path'] = 'C:/Program Files/ImageMagick-6.2.5-Q16/convert.exe'; +} else { + // *nix: set absolute pathname to "convert", or leave as null if "convert" is in the path + //$PHPTHUMB_CONFIG['imagemagick_path'] = '/usr/local/bin/convert'; + $PHPTHUMB_CONFIG['imagemagick_path'] = null; +} + + +// * Default output configuration: +$PHPTHUMB_CONFIG['output_format'] = 'jpeg'; // default output format ('jpeg', 'png' or 'gif') - thumbnail will be output in this format (if available in your version of GD). This is always overridden by ?f=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxwidth'] = 0; // default maximum thumbnail width. If this is zero then default width is the width of the source image. This is always overridden by ?w=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxheight'] = 0; // default maximum thumbnail height. If this is zero then default height is the height of the source image. This is always overridden by ?h=___ GETstring parameter +$PHPTHUMB_CONFIG['output_interlace'] = true; // if true: interlaced output for GIF/PNG, progressive output for JPEG; if false: non-interlaced for GIF/PNG, baseline for JPEG. + +// * Error message configuration +$PHPTHUMB_CONFIG['error_image_width'] = 400; // default width for error images +$PHPTHUMB_CONFIG['error_image_height'] = 100; // default height for error images +$PHPTHUMB_CONFIG['error_message_image_default'] = ''; // Set this to the name of a generic error image (e.g. '/images/error.png') that you want displayed in place of any error message that may occur. This setting is overridden by the 'err' parameter, which does the same thing. +$PHPTHUMB_CONFIG['error_bgcolor'] = 'CCCCFF'; // background color of error message images +$PHPTHUMB_CONFIG['error_textcolor'] = 'FF0000'; // color of text in error messages +$PHPTHUMB_CONFIG['error_fontsize'] = 1; // size of text in error messages, from 1 (smallest) to 5 (largest) +$PHPTHUMB_CONFIG['error_die_on_error'] = true; // die with error message on any fatal error (recommended with standalone phpThumb.php) +$PHPTHUMB_CONFIG['error_silent_die_on_error'] = false; // simply die with no output of any kind on fatal errors (not recommended) +$PHPTHUMB_CONFIG['error_die_on_source_failure'] = true; // die with error message if source image cannot be processed by phpThumb() (usually because source image is corrupt in some way). If false the source image will be passed through unprocessed, if true (default) an error message will be displayed. + +// * Off-server Thumbnailing Configuration: +$PHPTHUMB_CONFIG['nohotlink_enabled'] = true; // If false will allow thumbnailing from any source domain +$PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' +$PHPTHUMB_CONFIG['nohotlink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nohotlink_text_message'] = 'Off-server thumbnailing is not allowed'; // text of error message + +// * Off-server Linking Configuration: +$PHPTHUMB_CONFIG['nooffsitelink_enabled'] = true; // If false will allow thumbnails to be linked to from any domain, if true only domains listed below in 'nooffsitelink_valid_domains' will be allowed. +$PHPTHUMB_CONFIG['nooffsitelink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' +$PHPTHUMB_CONFIG['nooffsitelink_require_refer'] = false; // If false will allow standalone calls to phpThumb(). If true then only requests with a $_SERVER['HTTP_REFERER'] value in 'nooffsitelink_valid_domains' are allowed. +$PHPTHUMB_CONFIG['nooffsitelink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nooffsitelink_text_message'] = 'Image taken from '.@$_SERVER['HTTP_HOST']; // text of error message + + +// * Border & Background default colors +$PHPTHUMB_CONFIG['border_hexcolor'] = '000000'; // Default border color - usual HTML-style hex color notation (overidden with 'bc' parameter) +$PHPTHUMB_CONFIG['background_hexcolor'] = 'FFFFFF'; // Default background color when thumbnail aspect ratio does not match fixed-dimension box - usual HTML-style hex color notation (overridden with 'bg' parameter) + +// * Watermark configuration +$PHPTHUMB_CONFIG['ttf_directory'] = dirname(__FILE__).'/fonts'; // Base directory for TTF font files +//$PHPTHUMB_CONFIG['ttf_directory'] = 'c:/windows/fonts'; + + +// * MySQL configuration +// You may want to pull data from a database rather than a physical file +// If so, modify the $PHPTHUMB_CONFIG['mysql_query'] line to suit your database structure +// Note: the data retrieved must be the actual binary data of the image, not a URL or filename +// see http://www.billy-corgan.com/blog/archive/000143.php for a brief tutorial on this section + +$PHPTHUMB_CONFIG['mysql_query'] = ''; +//$PHPTHUMB_CONFIG['mysql_query'] = 'SELECT `picture` FROM `products` WHERE (`id` = \''.mysql_escape_string(@$_GET['id']).'\')'; + +// These 4 values must be modified if $PHPTHUMB_CONFIG['mysql_query'] is not empty, but may be ignored if $PHPTHUMB_CONFIG['mysql_query'] is blank. +$PHPTHUMB_CONFIG['mysql_hostname'] = 'localhost'; +$PHPTHUMB_CONFIG['mysql_username'] = ''; +$PHPTHUMB_CONFIG['mysql_password'] = ''; +$PHPTHUMB_CONFIG['mysql_database'] = ''; + + +// * Security configuration +$PHPTHUMB_CONFIG['high_security_enabled'] = false; // if enabled, requires 'high_security_password' set to at least 5 characters, and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs +$PHPTHUMB_CONFIG['high_security_password'] = ''; // required if 'high_security_enabled' is true, must be at least 5 characters long +$PHPTHUMB_CONFIG['disable_debug'] = false; // prevent phpThumb from displaying any information about your system. If true, phpThumbDebug and error messages will be disabled +$PHPTHUMB_CONFIG['allow_src_above_docroot'] = false; // if true, allow src to be anywhere in filesystem; if false (default) only allow src within document_root +$PHPTHUMB_CONFIG['allow_src_above_phpthumb'] = true; // if true (default), allow src to be anywhere in filesystem; if false only allow src within sub-directory of phpThumb installation +$PHPTHUMB_CONFIG['allow_parameter_file'] = false; // if true, allow use of 'file' parameter; if false (default) the 'file' parameter is disabled/ignored +$PHPTHUMB_CONFIG['allow_parameter_goto'] = false; // if true, allow use of 'goto' parameter; if false (default) the 'goto' parameter is disabled/ignored + + +// * HTTP UserAgent configuration +//$PHPTHUMB_CONFIG['http_user_agent'] = ''; // PHP default: none +//$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; // Windows XP, Internet Explorer +$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; // Windows XP, Firefox + + +// * Compatability settings +$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] = false; // if true, $_SERVER[PATH_INFO] is not parsed. May be needed on some server configurations to allow normal behavior. +$PHPTHUMB_CONFIG['disable_imagecopyresampled'] = false; // if true, ImageCopyResampled is replaced with ImageCopyResampleBicubic. May be needed for buggy versions of PHP-GD. +$PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] = true; // if true, any image that can be parsed by GetImageSize() can be passed through; if false, only images that can be converted to GD by ImageCreateFrom(JPEG|GIF|PNG) functions are allowed + + +// * Speed optimizations configuration +$PHPTHUMB_CONFIG['prefer_imagemagick'] = true; // If true, use ImageMagick to resize thumbnails if possible, since it is usually faster than GD functions; if false only use ImageMagick if PHP memory limit is too low. +$PHPTHUMB_CONFIG['use_exif_thumbnail_for_speed'] = false; // If true, and EXIF thumbnail is available, and is larger or equal to output image dimensions, use EXIF thumbnail rather than actual source image for generating thumbnail. Benefit is only speed, avoiding resizing large image. + +// END USER CONFIGURATION SECTION + +/////////////////////////////////////////////////////////////////////////////// + +// START DEFAULT PARAMETERS SECTION +// If any parameters are constant across ALL images, you can set them here + +$PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE = true; // if true, any parameters in the URL will override the defaults set here; if false, any parameters set here cannot be overridden in the URL +$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = false; // if true, GETstring parameters will be ignored (except for 'src') and only below default parameters will be used; if false, both default and GETstring parameters will be used (depending on $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE). Will be auto-set true if !empty($PHPTHUMB_CONFIG['cache_default_only_suffix']) + +//$PHPTHUMB_DEFAULTS['w'] = 100; +//$PHPTHUMB_DEFAULTS['fltr'] = array('blur|10'); +//$PHPTHUMB_DEFAULTS['q'] = 90; + + +// END DEFAULT PARAMETERS SECTION + + + +/////////////////////////////////////////////////////////////////////////////// +// Function for generating hashed calls to phpThumb if 'high_security_enabled' +// example: +// require_once('phpThumb.config.php'); +// echo ''; + +function phpThumbURL($ParameterString) { + global $PHPTHUMB_CONFIG; + return 'phpThumb.php?'.$ParameterString.'&hash='.md5($ParameterString.@$PHPTHUMB_CONFIG['high_security_password']); +} + +/////////////////////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/phpThumb.php b/site/racecalendar/phpthumb/phpThumb.php new file mode 100644 index 0000000..e09a660 --- /dev/null +++ b/site/racecalendar/phpthumb/phpThumb.php @@ -0,0 +1,585 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.changelog.txt for recent changes // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +error_reporting(E_ALL); +ini_set('display_errors', '1'); +if (!@ini_get('safe_mode')) { + set_time_limit(60); // shouldn't take nearly this long in most cases, but with many filter and/or a slow server... +} +ini_set('magic_quotes_runtime', '0'); +if (@ini_get('magic_quotes_runtime')) { + die('"magic_quotes_runtime" is set in php.ini, cannot run phpThumb with this enabled'); +} +$starttime = array_sum(explode(' ', microtime())); + +// this script relies on the superglobal arrays, fake it here for old PHP versions +if (phpversion() < '4.1.0') { + $_SERVER = $HTTP_SERVER_VARS; + $_GET = $HTTP_GET_VARS; +} + +// instantiate a new phpThumb() object +ob_start(); +if (!include_once(dirname(__FILE__).'/phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.class.php').'")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +$phpThumb->DebugTimingMessage('phpThumb.php start', __FILE__, __LINE__, $starttime); + +// phpThumbDebug[0] used to be here, but may reveal too much +// info when high_security_mode should be enabled (not set yet) + +if (file_exists(dirname(__FILE__).'/phpThumb.config.php')) { + ob_start(); + if (include_once(dirname(__FILE__).'/phpThumb.config.php')) { + // great + } else { + ob_end_flush(); + $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); + } + ob_end_clean(); +} elseif (file_exists(dirname(__FILE__).'/phpThumb.config.php.default')) { + $phpThumb->ErrorImage('Please rename "phpThumb.config.php.default" to "phpThumb.config.php"'); +} else { + $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); +} + +if (!@$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] && empty($_GET) && !empty($_SERVER['PATH_INFO'])) { + $_SERVER['PHP_SELF'] = str_replace($_SERVER['PATH_INFO'], '', @$_SERVER['PHP_SELF']); + + $args = explode(';', substr($_SERVER['PATH_INFO'], 1)); + if (!empty($args)) { + $_GET['src'] = @$args[count($args) - 1]; + } + if (eregi('^([0-9]*)x?([0-9]*)$', @$args[count($args) - 2], $matches)) { + $_GET['w'] = $matches[1]; + $_GET['h'] = $matches[2]; + } + for ($i = 0; $i < count($args) - 2; $i++) { + @list($key, $value) = explode('=', @$args[$i]); + if (substr($key, -2) == '[]') { + $_GET[substr($key, 0, -2)][] = $value; + } else { + $_GET[$key] = $value; + } + } +} + +if (@$PHPTHUMB_CONFIG['high_security_enabled']) { + if (!@$_GET['hash']) { + $phpThumb->ErrorImage('ERROR: missing hash'); + } elseif (strlen($PHPTHUMB_CONFIG['high_security_password']) < 5) { + $phpThumb->ErrorImage('ERROR: strlen($PHPTHUMB_CONFIG[high_security_password]) < 5'); + } elseif ($_GET['hash'] != md5(str_replace('&hash='.$_GET['hash'], '', $_SERVER['QUERY_STRING']).$PHPTHUMB_CONFIG['high_security_password'])) { + $phpThumb->ErrorImage('ERROR: invalid hash'); + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[0]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '0') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +// returned the fixed string if the evil "magic_quotes_gpc" setting is on +if (get_magic_quotes_gpc()) { + $RequestVarsToStripSlashes = array('src', 'wmf', 'file', 'err', 'goto', 'down'); + foreach ($RequestVarsToStripSlashes as $dummy => $key) { + if (isset($_GET[$key])) { + $_GET[$key] = stripslashes($_GET[$key]); + } + } +} + +if (!@$_SERVER['PATH_INFO'] && !@$_SERVER['QUERY_STRING']) { + + echo 'phpThumb() v'.$phpThumb->phpthumb_version.'
    http://phpthumb.sourceforge.net

    ERROR: no parameters specified'; + unset($phpThumb); + exit; + +} + +if (@$_GET['src'] && isset($_GET['md5s']) && empty($_GET['md5s'])) { + if (eregi('^(f|ht)tps?://', $_GET['src'])) { + if ($rawImageData = phpthumb_functions::SafeURLread($_GET['src'], $error)) { + $md5s = md5($rawImageData); + } + } else { + $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($_GET['src']); + if (is_readable($SourceFilename)) { + $md5s = phpthumb_functions::md5_file_safe($SourceFilename); + } else { + $phpThumb->ErrorImage('ERROR: "'.$SourceFilename.'" cannot be read'); + } + } + if (@$_SERVER['HTTP_REFERER']) { + $phpThumb->ErrorImage('&md5s='.$md5s); + } else { + die('&md5s='.$md5s); + } +} + +if (!empty($PHPTHUMB_CONFIG)) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + if (!eregi('password', $key)) { + $phpThumb->DebugMessage('setParameter('.$keyname.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + } + } +} else { + $phpThumb->DebugMessage('$PHPTHUMB_CONFIG is empty', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[1]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '1') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +$parsed_url_referer = parse_url(@$_SERVER['HTTP_REFERER']); +if ($phpThumb->config_nooffsitelink_require_refer && !in_array(@$parsed_url_referer['host'], $phpThumb->config_nohotlink_valid_domains)) { + $phpThumb->ErrorImage('config_nooffsitelink_require_refer enabled and '.(@$parsed_url_referer['host'] ? '"'.$parsed_url_referer['host'].'" is not an allowed referer' : 'no HTTP_REFERER exists')); +} +$parsed_url_src = parse_url(@$_GET['src']); +if ($phpThumb->config_nohotlink_enabled && $phpThumb->config_nohotlink_erase_image && eregi('^(f|ht)tps?://', @$_GET['src']) && !in_array(@$parsed_url_src['host'], $phpThumb->config_nohotlink_valid_domains)) { + $phpThumb->ErrorImage($phpThumb->config_nohotlink_text_message); +} + +if ($phpThumb->config_mysql_query) { + if ($cid = @mysql_connect($phpThumb->config_mysql_hostname, $phpThumb->config_mysql_username, $phpThumb->config_mysql_password)) { + if (@mysql_select_db($phpThumb->config_mysql_database, $cid)) { + if ($result = @mysql_query($phpThumb->config_mysql_query, $cid)) { + if ($row = @mysql_fetch_array($result)) { + + mysql_free_result($result); + mysql_close($cid); + $phpThumb->setSourceData($row[0]); + unset($row); + + } else { + mysql_free_result($result); + mysql_close($cid); + $phpThumb->ErrorImage('no matching data in database.'); + } + } else { + mysql_close($cid); + $phpThumb->ErrorImage('Error in MySQL query: "'.mysql_error($cid).'"'); + } + } else { + mysql_close($cid); + $phpThumb->ErrorImage('cannot select MySQL database: "'.mysql_error($cid).'"'); + } + } else { + $phpThumb->ErrorImage('cannot connect to MySQL server'); + } + unset($_GET['id']); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[2]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '2') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if (@$PHPTHUMB_CONFIG['cache_default_only_suffix'] && (strpos($PHPTHUMB_CONFIG['cache_default_only_suffix'], '*') !== false)) { + $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = true; +} +$allowedGETparameters = array('src', 'new', 'w', 'h', 'wp', 'hp', 'wl', 'hl', 'ws', 'hs', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'zc', 'bc', 'bg', 'bgt', 'fltr', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'far', 'iar', 'maxb', 'down', 'phpThumbDebug', 'hash', 'md5s'); +foreach ($_GET as $key => $value) { + if (@$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS && ($key != 'src')) { + // disabled, do not set parameter + $phpThumb->DebugMessage('ignoring $_GET['.$key.'] because of $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS', __FILE__, __LINE__); + } elseif (in_array($key, $allowedGETparameters)) { + $phpThumb->DebugMessage('setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + $phpThumb->setParameter($key, $value); + } else { + $phpThumb->ErrorImage('Forbidden parameter: '.$key); + } +} + +if (!empty($PHPTHUMB_DEFAULTS) && is_array($PHPTHUMB_DEFAULTS)) { + $phpThumb->DebugMessage('setting $PHPTHUMB_DEFAULTS['.implode(';', array_keys($PHPTHUMB_DEFAULTS)).']', __FILE__, __LINE__); + foreach ($PHPTHUMB_DEFAULTS as $key => $value) { + if ($PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE || !isset($_GET[$key])) { + $phpThumb->DebugMessage('setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + $phpThumb->setParameter($key, $value); + } + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[3]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '3') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +//if (!@$_GET['phpThumbDebug'] && !$phpThumb->sourceFilename && !function_exists('ImageJPEG') && !function_exists('ImagePNG') && !function_exists('ImageGIF')) { +if (!@$_GET['phpThumbDebug'] && !is_file($phpThumb->sourceFilename) && !phpthumb_functions::gd_version()) { + if (!headers_sent()) { + // base64-encoded error image in GIF format + $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; + header('Content-Type: image/gif'); + echo base64_decode($ERROR_NOGD); + } else { + echo '*** ERROR: No PHP-GD support available ***'; + } + exit; +} + +// check to see if file can be output from source with no processing or caching +$CanPassThroughDirectly = true; +if ($phpThumb->rawImageData) { + // data from SQL, should be fine +} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because eregi("^(f|ht)tp\://", '.$phpThumb->src.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} elseif (!@is_file($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_file('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} elseif (!@is_readable($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_readable('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} +foreach ($_GET as $key => $value) { + switch ($key) { + case 'src': + // allowed + break; + + case 'w': + case 'h': + // might be OK if exactly matches original + break; + + case 'phpThumbDebug': + // handled in direct-passthru code + break; + + default: + // all other parameters will cause some processing, + // therefore cannot pass through original image unmodified + $CanPassThroughDirectly = false; + $UnAllowedGET[] = $key; + break; + } +} +if (!empty($UnAllowedGET)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because $_GET['.implode(';', array_unique($UnAllowedGET)).'] are set', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[4]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '4') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +function SendSaveAsFileHeaderIfNeeded() { + if (headers_sent()) { + return false; + } + global $phpThumb; + if (@$_GET['down']) { + $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $_GET['down']); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) { + $downloadfilename = trim($downloadfilename, '.'); + } + if (@$downloadfilename) { + $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: attachment; filename="'.$downloadfilename.'"', __FILE__, __LINE__); + header('Content-Disposition: attachment; filename="'.$downloadfilename.'"'); + return true; + } + } + $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: inline', __FILE__, __LINE__); + header('Content-Disposition: inline'); + return true; +} + +$phpThumb->DebugMessage('$CanPassThroughDirectly="'.intval($CanPassThroughDirectly).'" && $phpThumb->src="'.$phpThumb->src.'"', __FILE__, __LINE__); +while ($CanPassThroughDirectly && $phpThumb->src) { + // no parameters set, passthru + $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($phpThumb->src); + + // security and size checks + if ($phpThumb->getimagesizeinfo = @GetImageSize($SourceFilename)) { + $phpThumb->DebugMessage('Direct passthru GetImageSize() returned [w='.$phpThumb->getimagesizeinfo[0].';h='.$phpThumb->getimagesizeinfo[1].';t='.$phpThumb->getimagesizeinfo[2].']', __FILE__, __LINE__); + + if (!@$_REQUEST['w'] && !@$_REQUEST['wp'] && !@$_REQUEST['wl'] && !@$_REQUEST['ws'] && !@$_REQUEST['h'] && !@$_REQUEST['hp'] && !@$_REQUEST['hl'] && !@$_REQUEST['hs']) { + // no resizing needed + $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'")', __FILE__, __LINE__); + } elseif (($phpThumb->getimagesizeinfo[0] <= @$_REQUEST['w']) && ($phpThumb->getimagesizeinfo[1] <= @$_REQUEST['h']) && ((@$_REQUEST['w'] == $phpThumb->getimagesizeinfo[0]) || (@$_REQUEST['h'] == $phpThumb->getimagesizeinfo[1]))) { + // image fits into 'w'x'h' box, and at least one dimension matches exactly, therefore no resizing needed + $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" fits inside "'.@$_REQUEST['w'].'"x"'.@$_REQUEST['h'].'")', __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because resizing required (from "'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" to "'.@$_REQUEST['w'].'"x"'.@$_REQUEST['h'].'")', __FILE__, __LINE__); + break; + } + switch ($phpThumb->getimagesizeinfo[2]) { + case 1: // GIF + case 2: // JPG + case 3: // PNG + // great, let it through + break; + default: + // browser probably can't handle format, remangle it to JPEG/PNG/GIF + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because $phpThumb->getimagesizeinfo[2] = "'.$phpThumb->getimagesizeinfo[2].'"', __FILE__, __LINE__); + break 2; + } + + $ImageCreateFunctions = array(1=>'ImageCreateFromGIF', 2=>'ImageCreateFromJPEG', 3=>'ImageCreateFromPNG'); + $theImageCreateFunction = @$ImageCreateFunctions[$phpThumb->getimagesizeinfo[2]]; + if ($phpThumb->config_disable_onlycreateable_passthru || (function_exists($theImageCreateFunction) && ($dummyImage = @$theImageCreateFunction($SourceFilename)))) { + + // great + if (@is_resource($dummyImage)) { + unset($dummyImage); + } + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + if (@$_GET['phpThumbDebug']) { + $phpThumb->DebugTimingMessage('skipped direct $SourceFilename passthru', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have passed "'.$SourceFilename.'" through directly, but skipping due to phpThumbDebug', __FILE__, __LINE__); + break; + } + + SendSaveAsFileHeaderIfNeeded(); + header('Last-Modified: '.gmdate('D, d M Y H:i:s', @filemtime($SourceFilename)).' GMT'); + if ($contentType = phpthumb_functions::ImageTypeToMIMEtype(@$phpThumb->getimagesizeinfo[2])) { + header('Content-Type: '.$contentType); + } + @readfile($SourceFilename); + exit; + + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because ($phpThumb->config_disable_onlycreateable_passthru = "'.$phpThumb->config_disable_onlycreateable_passthru.'") and '.$theImageCreateFunction.'() failed', __FILE__, __LINE__); + break; + } + + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because GetImageSize() failed', __FILE__, __LINE__); + break; + } + break; +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[5]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '5') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +function RedirectToCachedFile() { + global $phpThumb, $PHPTHUMB_CONFIG; + + $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $phpThumb->cache_filename); + $nice_docroot = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($PHPTHUMB_CONFIG['document_root'], '/\\')); + + $parsed_url = @parse_url(@$_SERVER['HTTP_REFERER']); + + $nModified = filemtime($phpThumb->cache_filename); + + if ($phpThumb->config_nooffsitelink_enabled && @$_SERVER['HTTP_REFERER'] && !in_array(@$parsed_url['host'], $phpThumb->config_nooffsitelink_valid_domains)) { + + $phpThumb->DebugMessage('Would have used cached (image/'.$phpThumb->thumbnailFormat.') file "'.$phpThumb->cache_filename.'" (Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT), but skipping because $_SERVER[HTTP_REFERER] ('.@$_SERVER['HTTP_REFERER'].') is not in $phpThumb->config_nooffsitelink_valid_domains ('.implode(';', $phpThumb->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + + } elseif ($phpThumb->phpThumbDebug) { + + $phpThumb->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__); + $phpThumb->DebugMessage('* Would have sent headers (1): Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT', __FILE__, __LINE__); + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + $phpThumb->DebugMessage('* Would have sent headers (2): Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__); + } + if (ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { + $phpThumb->DebugMessage('* Would have sent headers (3): Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])), __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('* Would have sent data: readfile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + SendSaveAsFileHeaderIfNeeded(); + + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT'); + if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && @$_SERVER['SERVER_PROTOCOL']) { + header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); + exit; + } + + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2])); + } elseif (eregi('\.ico$', $phpThumb->cache_filename)) { + header('Content-Type: image/x-icon'); + } + if (!@$PHPTHUMB_CONFIG['cache_force_passthru'] && ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { + header('Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1]))); + } else { + @readfile($phpThumb->cache_filename); + } + exit; + + } + return true; +} + +// check to see if file already exists in cache, and output it with no processing if it does +$phpThumb->SetCacheFilename(); +if (@is_file($phpThumb->cache_filename)) { + RedirectToCachedFile(); +} else { + $phpThumb->DebugMessage('Cached file "'.$phpThumb->cache_filename.'" does not exist, processing as normal', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[6]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '6') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if ($phpThumb->rawImageData) { + + // great + +} elseif (@$_GET['new']) { + + // generate a blank image resource of the specified size/background color/opacity + if (($phpThumb->w <= 0) || ($phpThumb->h <= 0)) { + $phpThumb->ErrorImage('"w" and "h" parameters required for "new"'); + } + @list($bghexcolor, $opacity) = explode('|', $_GET['new']); + if (!phpthumb_functions::IsHexColor($bghexcolor)) { + $phpThumb->ErrorImage('BGcolor parameter for "new" is not valid'); + } + $opacity = (strlen($opacity) ? $opacity : 100); + if ($phpThumb->gdimg_source = phpthumb_functions::ImageCreateFunction($phpThumb->w, $phpThumb->h)) { + $alpha = (100 - min(100, max(0, $opacity))) * 1.27; + if ($alpha) { + $phpThumb->setParameter('is_alpha', true); + ImageAlphaBlending($phpThumb->gdimg_source, false); + phpthumb_functions::gd_ImageSaveAlpha($phpThumb->gdimg_source, true); + } + $new_background_color = phpthumb_functions::ImageHexColorAllocate($phpThumb->gdimg_source, $bghexcolor, false, $alpha); + ImageFilledRectangle($phpThumb->gdimg_source, 0, 0, $phpThumb->w, $phpThumb->h, $new_background_color); + } else { + $phpThumb->ErrorImage('failed to create "new" image ('.$phpThumb->w.'x'.$phpThumb->h.')'); + } + +} elseif (!$phpThumb->src) { + + $phpThumb->ErrorImage('Usage: '.$_SERVER['PHP_SELF'].'?src=/path/and/filename.jpg'."\n".'read Usage comments for details'); + +} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { + + if ($phpThumb->config_http_user_agent) { + ini_set('user_agent', $phpThumb->config_http_user_agent); + } + $basename = preg_quote(basename($phpThumb->src)); + $encoded = rawurlencode(basename($phpThumb->src)); + $HTTPurl = ereg_replace('(.*)'.$basename.'$', '\\1'.$encoded, $phpThumb->src); + if ($rawImageData = phpthumb_functions::SafeURLread($HTTPurl, $error)) { + $phpThumb->setSourceData($rawImageData, urlencode($phpThumb->src)); + } else { + $phpThumb->ErrorImage($error); + } + +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[7]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '7') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +$phpThumb->GenerateThumbnail(); + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[8]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '8') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if ($phpThumb->config_allow_parameter_file && $phpThumb->file) { + + $phpThumb->RenderToFile($phpThumb->ResolveFilenameToAbsolute($phpThumb->file)); + if ($phpThumb->config_allow_parameter_goto && $phpThumb->goto && eregi('^(f|ht)tps?://', $phpThumb->goto)) { + // redirect to another URL after image has been rendered to file + header('Location: '.$phpThumb->goto); + exit; + } + +} else { + + if ((file_exists($phpThumb->cache_filename) && is_writable($phpThumb->cache_filename)) || is_writable(dirname($phpThumb->cache_filename))) { + + $phpThumb->CleanUpCacheDirectory(); + if ($phpThumb->RenderToFile($phpThumb->cache_filename) && is_readable($phpThumb->cache_filename)) { + chmod($phpThumb->cache_filename, 0644); + RedirectToCachedFile(); + } else { + $phpThumb->DebugMessage('Failed: RenderToFile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + $phpThumb->DebugMessage('Cannot write to $phpThumb->cache_filename ('.$phpThumb->cache_filename.') because that directory ('.dirname($phpThumb->cache_filename).') is not writable', __FILE__, __LINE__); + + } + +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[9]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '9') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if (!$phpThumb->OutputThumbnail()) { + $phpThumb->ErrorImage('Error in OutputThumbnail():'."\n".$phpThumb->debugmessages[(count($phpThumb->debugmessages) - 1)]); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[10]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '10') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/phpthumb.bmp.php b/site/racecalendar/phpthumb/phpthumb.bmp.php new file mode 100644 index 0000000..4946226 --- /dev/null +++ b/site/racecalendar/phpthumb/phpthumb.bmp.php @@ -0,0 +1,874 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.graphic.bmp.php // +// module for analyzing BMP Image files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// +// // +// Modified for use in phpThumb() - James Heinrich 2004.07.27 // +// // +///////////////////////////////////////////////////////////////// + + +class phpthumb_bmp { + + function phpthumb_bmp() { + return true; + } + + function phpthumb_bmp2gd(&$BMPdata, $truecolor=true) { + $ThisFileInfo = array(); + if ($this->getid3_bmp($BMPdata, $ThisFileInfo, true, true)) { + $gd = $this->PlotPixelsGD($ThisFileInfo['bmp'], $truecolor); + return $gd; + } + return false; + } + + function phpthumb_bmpfile2gd($filename, $truecolor=true) { + if ($fp = @fopen($filename, 'rb')) { + $BMPdata = fread($fp, filesize($filename)); + fclose($fp); + return $this->phpthumb_bmp2gd($BMPdata, $truecolor); + } + return false; + } + + function GD2BMPstring(&$gd_image) { + $imageX = ImageSX($gd_image); + $imageY = ImageSY($gd_image); + + $BMP = ''; + for ($y = ($imageY - 1); $y >= 0; $y--) { + $thisline = ''; + for ($x = 0; $x < $imageX; $x++) { + $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); + $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']); + } + while (strlen($thisline) % 4) { + $thisline .= "\x00"; + } + $BMP .= $thisline; + } + + $bmpSize = strlen($BMP) + 14 + 40; + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + $BITMAPFILEHEADER = 'BM'; // WORD bfType; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String($bmpSize, 4); // DWORD bfSize; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved1; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved2; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 54, 4); // DWORD bfOffBits; + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + $BITMAPINFOHEADER = phpthumb_functions::LittleEndian2String( 40, 4); // DWORD biSize; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageX, 4); // LONG biWidth; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageY, 4); // LONG biHeight; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 1, 2); // WORD biPlanes; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 24, 2); // WORD biBitCount; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biCompression; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biSizeImage; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biXPelsPerMeter; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biYPelsPerMeter; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrUsed; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrImportant; + + return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP; + } + + function getid3_bmp(&$BMPdata, &$ThisFileInfo, $ExtractPalette=false, $ExtractData=false) { + + // shortcuts + $ThisFileInfo['bmp']['header']['raw'] = array(); + $thisfile_bmp = &$ThisFileInfo['bmp']; + $thisfile_bmp_header = &$thisfile_bmp['header']; + $thisfile_bmp_header_raw = &$thisfile_bmp_header['raw']; + + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + // all versions + // WORD bfType; + // DWORD bfSize; + // WORD bfReserved1; + // WORD bfReserved2; + // DWORD bfOffBits; + + $offset = 0; + $overalloffset = 0; + $BMPheader = substr($BMPdata, $overalloffset, 14 + 40); + $overalloffset += (14 + 40); + + $thisfile_bmp_header_raw['identifier'] = substr($BMPheader, $offset, 2); + $offset += 2; + + if ($thisfile_bmp_header_raw['identifier'] != 'BM') { + $ThisFileInfo['error'][] = 'Expecting "BM" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$thisfile_bmp_header_raw['identifier'].'"'; + unset($ThisFileInfo['fileformat']); + unset($ThisFileInfo['bmp']); + return false; + } + + $thisfile_bmp_header_raw['filesize'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['reserved2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['header_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + + // check if the hardcoded-to-1 "planes" is at offset 22 or 26 + $planes22 = $this->LittleEndian2Int(substr($BMPheader, 22, 2)); + $planes26 = $this->LittleEndian2Int(substr($BMPheader, 26, 2)); + if (($planes22 == 1) && ($planes26 != 1)) { + $thisfile_bmp['type_os'] = 'OS/2'; + $thisfile_bmp['type_version'] = 1; + } elseif (($planes26 == 1) && ($planes22 != 1)) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 12) { + $thisfile_bmp['type_os'] = 'OS/2'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 40) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 84) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 4; + } elseif ($thisfile_bmp_header_raw['header_size'] == 100) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 5; + } else { + $ThisFileInfo['error'][] = 'Unknown BMP subtype (or not a BMP file)'; + unset($ThisFileInfo['fileformat']); + unset($ThisFileInfo['bmp']); + return false; + } + + $ThisFileInfo['fileformat'] = 'bmp'; + $ThisFileInfo['video']['dataformat'] = 'bmp'; + $ThisFileInfo['video']['lossless'] = true; + $ThisFileInfo['video']['pixel_aspect_ratio'] = (float) 1; + + if ($thisfile_bmp['type_os'] == 'OS/2') { + + // OS/2-format BMP + // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm + + // DWORD Size; /* Size of this structure in bytes */ + // DWORD Width; /* Bitmap width in pixels */ + // DWORD Height; /* Bitmap height in pixel */ + // WORD NumPlanes; /* Number of bit planes (color depth) */ + // WORD BitsPerPixel; /* Number of bits per pixel per plane */ + + $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + + $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; + $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; + $ThisFileInfo['video']['codec'] = 'BI_RGB '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; + + if ($thisfile_bmp['type_version'] >= 2) { + // DWORD Compression; /* Bitmap compression scheme */ + // DWORD ImageDataSize; /* Size of bitmap data in bytes */ + // DWORD XResolution; /* X resolution of display device */ + // DWORD YResolution; /* Y resolution of display device */ + // DWORD ColorsUsed; /* Number of color table indices used */ + // DWORD ColorsImportant; /* Number of important color indices */ + // WORD Units; /* Type of units used to measure resolution */ + // WORD Reserved; /* Pad structure to 4-byte boundary */ + // WORD Recording; /* Recording algorithm */ + // WORD Rendering; /* Halftoning algorithm used */ + // DWORD Size1; /* Reserved for halftoning algorithm use */ + // DWORD Size2; /* Reserved for halftoning algorithm use */ + // DWORD ColorEncoding; /* Color model used in bitmap */ + // DWORD Identifier; /* Reserved for application use */ + + $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_units'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['recording'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['rendering'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['size1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['size2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['color_encoding'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['identifier'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['compression'] = $this->BMPcompressionOS2Lookup($thisfile_bmp_header_raw['compression']); + + $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + } + + } elseif ($thisfile_bmp['type_os'] == 'Windows') { + + // Windows-format BMP + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + // all versions + // DWORD biSize; + // LONG biWidth; + // LONG biHeight; + // WORD biPlanes; + // WORD biBitCount; + // DWORD biCompression; + // DWORD biSizeImage; + // LONG biXPelsPerMeter; + // LONG biYPelsPerMeter; + // DWORD biClrUsed; + // DWORD biClrImportant; + + $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['compression'] = $this->BMPcompressionWindowsLookup($thisfile_bmp_header_raw['compression']); + $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; + $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; + $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; + + if (($thisfile_bmp['type_version'] >= 4) || ($thisfile_bmp_header_raw['compression'] == 3)) { + // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen + $BMPheader .= substr($BMPdata, $overalloffset, 44); + $overalloffset += 44; + + // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp + // Win95+, WinNT4.0+ + // DWORD bV4RedMask; + // DWORD bV4GreenMask; + // DWORD bV4BlueMask; + // DWORD bV4AlphaMask; + // DWORD bV4CSType; + // CIEXYZTRIPLE bV4Endpoints; + // DWORD bV4GammaRed; + // DWORD bV4GammaGreen; + // DWORD bV4GammaBlue; + $thisfile_bmp_header_raw['red_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['green_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['blue_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['alpha_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['cs_type'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_red'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_green'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_blue'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['gamma_red'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['gamma_green'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['gamma_blue'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['ciexyz_red'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_red'])); + $thisfile_bmp_header['ciexyz_green'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_green'])); + $thisfile_bmp_header['ciexyz_blue'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_blue'])); + } + + if ($thisfile_bmp['type_version'] >= 5) { + $BMPheader .= substr($BMPdata, $overalloffset, 16); + $overalloffset += 16; + + // BITMAPV5HEADER - [16 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_7c36.asp + // Win98+, Win2000+ + // DWORD bV5Intent; + // DWORD bV5ProfileData; + // DWORD bV5ProfileSize; + // DWORD bV5Reserved; + $thisfile_bmp_header_raw['intent'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['profile_data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['profile_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['reserved3'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + } + + } else { + + $ThisFileInfo['error'][] = 'Unknown BMP format in header.'; + return false; + + } + + if ($ExtractPalette || $ExtractData) { + $PaletteEntries = 0; + if ($thisfile_bmp_header_raw['bits_per_pixel'] < 16) { + $PaletteEntries = pow(2, $thisfile_bmp_header_raw['bits_per_pixel']); + } elseif (isset($thisfile_bmp_header_raw['colors_used']) && ($thisfile_bmp_header_raw['colors_used'] > 0) && ($thisfile_bmp_header_raw['colors_used'] <= 256)) { + $PaletteEntries = $thisfile_bmp_header_raw['colors_used']; + } + if ($PaletteEntries > 0) { + $BMPpalette = substr($BMPdata, $overalloffset, 4 * $PaletteEntries); + $overalloffset += 4 * $PaletteEntries; + + $paletteoffset = 0; + for ($i = 0; $i < $PaletteEntries; $i++) { + // RGBQUAD - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_5f8y.asp + // BYTE rgbBlue; + // BYTE rgbGreen; + // BYTE rgbRed; + // BYTE rgbReserved; + $blue = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + $green = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + $red = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + if (($thisfile_bmp['type_os'] == 'OS/2') && ($thisfile_bmp['type_version'] == 1)) { + // no padding byte + } else { + $paletteoffset++; // padding byte + } + $thisfile_bmp['palette'][$i] = (($red << 16) | ($green << 8) | ($blue)); + } + } + } + + if ($ExtractData) { + $RowByteLength = ceil(($thisfile_bmp_header_raw['width'] * ($thisfile_bmp_header_raw['bits_per_pixel'] / 8)) / 4) * 4; // round up to nearest DWORD boundry + + $BMPpixelData = substr($BMPdata, $thisfile_bmp_header_raw['data_offset'], $thisfile_bmp_header_raw['height'] * $RowByteLength); + $overalloffset = $thisfile_bmp_header_raw['data_offset'] + ($thisfile_bmp_header_raw['height'] * $RowByteLength); + + $pixeldataoffset = 0; + switch (@$thisfile_bmp_header_raw['compression']) { + + case 0: // BI_RGB + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 1: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { + $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); + for ($i = 7; $i >= 0; $i--) { + $paletteindex = ($paletteindexbyte & (0x01 << $i)) >> $i; + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $col++; + } + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 4: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { + $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); + for ($i = 1; $i >= 0; $i--) { + $paletteindex = ($paletteindexbyte & (0x0F << (4 * $i))) >> (4 * $i); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $col++; + } + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 8: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $paletteindex = ord($BMPpixelData{$pixeldataoffset++}); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 24: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); + $pixeldataoffset += 3; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 32: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+3}) << 24) | (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); + $pixeldataoffset += 4; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 16: + // ? + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + case 1: // BI_RLE8 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 8: + $pixelcounter = 0; + while ($pixeldataoffset < strlen($BMPpixelData)) { + $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + if ($firstbyte == 0) { + + // escaped/absolute mode - the first byte of the pair can be set to zero to + // indicate an escape character that denotes the end of a line, the end of + // a bitmap, or a delta, depending on the value of the second byte. + switch ($secondbyte) { + case 0: + // end of line + // no need for special processing, just ignore + break; + + case 1: + // end of bitmap + $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case + break; + + case 2: + // delta - The 2 bytes following the escape contain unsigned values + // indicating the horizontal and vertical offsets of the next pixel + // from the current position. + $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; + $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; + $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; + break; + + default: + // In absolute mode, the first byte is zero and the second byte is a + // value in the range 03H through FFH. The second byte represents the + // number of bytes that follow, each of which contains the color index + // of a single pixel. Each run must be aligned on a word boundary. + for ($i = 0; $i < $secondbyte; $i++) { + $paletteindex = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $pixelcounter++; + } + while (($pixeldataoffset % 2) != 0) { + // Each run must be aligned on a word boundary. + $pixeldataoffset++; + } + break; + } + + } else { + + // encoded mode - the first byte specifies the number of consecutive pixels + // to be drawn using the color index contained in the second byte. + for ($i = 0; $i < $firstbyte; $i++) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$secondbyte]; + $pixelcounter++; + } + + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + + case 2: // BI_RLE4 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 4: + $pixelcounter = 0; + while ($pixeldataoffset < strlen($BMPpixelData)) { + $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + if ($firstbyte == 0) { + + // escaped/absolute mode - the first byte of the pair can be set to zero to + // indicate an escape character that denotes the end of a line, the end of + // a bitmap, or a delta, depending on the value of the second byte. + switch ($secondbyte) { + case 0: + // end of line + // no need for special processing, just ignore + break; + + case 1: + // end of bitmap + $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case + break; + + case 2: + // delta - The 2 bytes following the escape contain unsigned values + // indicating the horizontal and vertical offsets of the next pixel + // from the current position. + $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; + $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; + $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; + break; + + default: + // In absolute mode, the first byte is zero. The second byte contains the number + // of color indexes that follow. Subsequent bytes contain color indexes in their + // high- and low-order 4 bits, one color index for each pixel. In absolute mode, + // each run must be aligned on a word boundary. + unset($paletteindexes); + for ($i = 0; $i < ceil($secondbyte / 2); $i++) { + $paletteindexbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $paletteindexes[] = ($paletteindexbyte & 0xF0) >> 4; + $paletteindexes[] = ($paletteindexbyte & 0x0F); + } + while (($pixeldataoffset % 2) != 0) { + // Each run must be aligned on a word boundary. + $pixeldataoffset++; + } + + foreach ($paletteindexes as $dummy => $paletteindex) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $pixelcounter++; + } + break; + } + + } else { + + // encoded mode - the first byte of the pair contains the number of pixels to be + // drawn using the color indexes in the second byte. The second byte contains two + // color indexes, one in its high-order 4 bits and one in its low-order 4 bits. + // The first of the pixels is drawn using the color specified by the high-order + // 4 bits, the second is drawn using the color in the low-order 4 bits, the third + // is drawn using the color in the high-order 4 bits, and so on, until all the + // pixels specified by the first byte have been drawn. + $paletteindexes[0] = ($secondbyte & 0xF0) >> 4; + $paletteindexes[1] = ($secondbyte & 0x0F); + for ($i = 0; $i < $firstbyte; $i++) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindexes[($i % 2)]]; + $pixelcounter++; + } + + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + case 3: // BI_BITFIELDS + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 16: + case 32: + $redshift = 0; + $greenshift = 0; + $blueshift = 0; + if (!$thisfile_bmp_header_raw['red_mask'] || !$thisfile_bmp_header_raw['green_mask'] || !$thisfile_bmp_header_raw['blue_mask']) { + $ThisFileInfo['error'][] = 'missing $thisfile_bmp_header_raw[(red|green|blue)_mask]'; + return false; + } + while ((($thisfile_bmp_header_raw['red_mask'] >> $redshift) & 0x01) == 0) { + $redshift++; + } + while ((($thisfile_bmp_header_raw['green_mask'] >> $greenshift) & 0x01) == 0) { + $greenshift++; + } + while ((($thisfile_bmp_header_raw['blue_mask'] >> $blueshift) & 0x01) == 0) { + $blueshift++; + } + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $pixelvalue = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset, $thisfile_bmp_header_raw['bits_per_pixel'] / 8)); + $pixeldataoffset += $thisfile_bmp_header_raw['bits_per_pixel'] / 8; + + $red = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['red_mask']) >> $redshift) / ($thisfile_bmp_header_raw['red_mask'] >> $redshift)) * 255)); + $green = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['green_mask']) >> $greenshift) / ($thisfile_bmp_header_raw['green_mask'] >> $greenshift)) * 255)); + $blue = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['blue_mask']) >> $blueshift) / ($thisfile_bmp_header_raw['blue_mask'] >> $blueshift)) * 255)); + $thisfile_bmp['data'][$row][$col] = (($red << 16) | ($green << 8) | ($blue)); + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + default: // unhandled compression type + $ThisFileInfo['error'][] = 'Unknown/unhandled compression type value ('.$thisfile_bmp_header_raw['compression'].') - cannot decompress pixel data'; + break; + } + } + + return true; + } + + function IntColor2RGB($color) { + $red = ($color & 0x00FF0000) >> 16; + $green = ($color & 0x0000FF00) >> 8; + $blue = ($color & 0x000000FF); + return array($red, $green, $blue); + } + + function PlotPixelsGD(&$BMPdata, $truecolor=true) { + $imagewidth = $BMPdata['header']['raw']['width']; + $imageheight = $BMPdata['header']['raw']['height']; + + if ($truecolor) { + + $gd = @ImageCreateTrueColor($imagewidth, $imageheight); + + } else { + + $gd = @ImageCreate($imagewidth, $imageheight); + if (!empty($BMPdata['palette'])) { + // create GD palette from BMP palette + foreach ($BMPdata['palette'] as $dummy => $color) { + list($r, $g, $b) = $this->IntColor2RGB($color); + ImageColorAllocate($gd, $r, $g, $b); + } + } else { + // create 216-color websafe palette + for ($r = 0x00; $r <= 0xFF; $r += 0x33) { + for ($g = 0x00; $g <= 0xFF; $g += 0x33) { + for ($b = 0x00; $b <= 0xFF; $b += 0x33) { + ImageColorAllocate($gd, $r, $g, $b); + } + } + } + } + + } + if (!is_resource($gd)) { + return false; + } + + foreach ($BMPdata['data'] as $row => $colarray) { + @set_time_limit(30); + foreach ($colarray as $col => $color) { + list($red, $green, $blue) = $this->IntColor2RGB($color); + if ($truecolor) { + $pixelcolor = ImageColorAllocate($gd, $red, $green, $blue); + } else { + $pixelcolor = ImageColorClosest($gd, $red, $green, $blue); + } + ImageSetPixel($gd, $col, $row, $pixelcolor); + } + } + return $gd; + } + + function PlotBMP(&$BMPinfo) { + $starttime = time(); + if (!isset($BMPinfo['bmp']['data']) || !is_array($BMPinfo['bmp']['data'])) { + echo 'ERROR: no pixel data
    '; + return false; + } + set_time_limit(intval(round($BMPinfo['resolution_x'] * $BMPinfo['resolution_y'] / 10000))); + $im = $this->PlotPixelsGD($BMPinfo['bmp']); + if (headers_sent()) { + echo 'plotted '.($BMPinfo['resolution_x'] * $BMPinfo['resolution_y']).' pixels in '.(time() - $starttime).' seconds
    '; + ImageDestroy($im); + exit; + } else { + header('Content-Type: image/png'); + ImagePNG($im); + ImageDestroy($im); + return true; + } + return false; + } + + function BMPcompressionWindowsLookup($compressionid) { + static $BMPcompressionWindowsLookup = array( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'BI_BITFIELDS', + 4 => 'BI_JPEG', + 5 => 'BI_PNG' + ); + return (isset($BMPcompressionWindowsLookup[$compressionid]) ? $BMPcompressionWindowsLookup[$compressionid] : 'invalid'); + } + + function BMPcompressionOS2Lookup($compressionid) { + static $BMPcompressionOS2Lookup = array( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'Huffman 1D', + 4 => 'BI_RLE24', + ); + return (isset($BMPcompressionOS2Lookup[$compressionid]) ? $BMPcompressionOS2Lookup[$compressionid] : 'invalid'); + } + + + // from getid3.lib.php + + function trunc($floatnumber) { + // truncates a floating-point number at the decimal point + // returns int (if possible, otherwise float) + if ($floatnumber >= 1) { + $truncatednumber = floor($floatnumber); + } elseif ($floatnumber <= -1) { + $truncatednumber = ceil($floatnumber); + } else { + $truncatednumber = 0; + } + if ($truncatednumber <= 1073741824) { // 2^30 + $truncatednumber = (int) $truncatednumber; + } + return $truncatednumber; + } + + function LittleEndian2Int($byteword) { + $intvalue = 0; + $byteword = strrev($byteword); + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i)); + } + return $intvalue; + } + + function BigEndian2Int($byteword) { + return $this->LittleEndian2Int(strrev($byteword)); + } + + function BigEndian2Bin($byteword) { + $binvalue = ''; + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT); + } + return $binvalue; + } + + function FixedPoint2_30($rawdata) { + $binarystring = $this->BigEndian2Bin($rawdata); + return $this->Bin2Dec(substr($binarystring, 0, 2)) + (float) ($this->Bin2Dec(substr($binarystring, 2, 30)) / 1073741824); + } + + function Bin2Dec($binstring, $signed=false) { + $signmult = 1; + if ($signed) { + if ($binstring{0} == '1') { + $signmult = -1; + } + $binstring = substr($binstring, 1); + } + $decvalue = 0; + for ($i = 0; $i < strlen($binstring); $i++) { + $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i); + } + return $this->CastAsInt($decvalue * $signmult); + } + + function CastAsInt($floatnum) { + // convert to float if not already + $floatnum = (float) $floatnum; + + // convert a float to type int, only if possible + if ($this->trunc($floatnum) == $floatnum) { + // it's not floating point + if ($floatnum <= 1073741824) { // 2^30 + // it's within int range + $floatnum = (int) $floatnum; + } + } + return $floatnum; + } + +} + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/phpthumb.class.php b/site/racecalendar/phpthumb/phpthumb.class.php new file mode 100644 index 0000000..14865fd --- /dev/null +++ b/site/racecalendar/phpthumb/phpthumb.class.php @@ -0,0 +1,3170 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'")'); +} +ob_end_clean(); + +class phpthumb { + + // public: + // START PARAMETERS (for object mode and phpThumb.php) + // See phpthumb.readme.txt for descriptions of what each of these values are + var $src = null; // SouRCe filename + var $new = null; // NEW image (phpThumb.php only) + var $w = null; // Width + var $h = null; // Height + var $wp = null; // Width (Portrait Images Only) + var $hp = null; // Height (Portrait Images Only) + var $wl = null; // Width (Landscape Images Only) + var $hl = null; // Height (Landscape Images Only) + var $ws = null; // Width (Square Images Only) + var $hs = null; // Height (Square Images Only) + var $f = null; // Format + var $q = 75; // jpeg output Quality + var $sx = null; // Source crop top-left X position + var $sy = null; // Source crop top-left Y position + var $sw = null; // Source crop Width + var $sh = null; // Source crop Height + var $zc = null; // Zoom Crop + var $bc = null; // Border Color + var $bg = null; // BackGround color + var $fltr = array(); // FiLTeRs + var $goto = null; // GO TO url after processing + var $err = null; // default ERRor image filename + var $xto = null; // extract eXif Thumbnail Only + var $ra = null; // Rotate by Angle + var $ar = null; // Auto Rotate + var $aoe = null; // Allow Output Enlargement + var $far = null; // Fixed Aspect Ratio + var $iar = null; // Ignore Aspect Ratio + var $maxb = null; // MAXimum Bytes + var $down = null; // DOWNload thumbnail filename + var $md5s = null; // MD5 hash of Source image + var $file = null; // >>deprecated, do not use<< + + var $phpThumbDebug = null; + // END PARAMETERS + + + // public: + // START CONFIGURATION OPTIONS (for object mode only) + // See phpThumb.config.php for descriptions of what each of these settings do + + // * Directory Configuration + var $config_cache_directory = null; + var $config_cache_disable_warning = true; + var $config_cache_source_enabled = false; + var $config_cache_source_directory = null; + var $config_temp_directory = null; + var $config_document_root = null; + + // * Default output configuration: + var $config_output_format = 'jpeg'; + var $config_output_maxwidth = 0; + var $config_output_maxheight = 0; + var $config_output_interlace = true; + + // * Error message configuration + var $config_error_image_width = 400; + var $config_error_image_height = 100; + var $config_error_message_image_default = ''; + var $config_error_bgcolor = 'CCCCFF'; + var $config_error_textcolor = 'FF0000'; + var $config_error_fontsize = 1; + var $config_error_die_on_error = true; + var $config_error_silent_die_on_error = false; + var $config_error_die_on_source_failure = true; + + // * Anti-Hotlink Configuration: + var $config_nohotlink_enabled = true; + var $config_nohotlink_valid_domains = array(); + var $config_nohotlink_erase_image = true; + var $config_nohotlink_text_message = 'Off-server thumbnailing is not allowed'; + // * Off-server Linking Configuration: + var $config_nooffsitelink_enabled = false; + var $config_nooffsitelink_valid_domains = array(); + var $config_nooffsitelink_require_refer = false; + var $config_nooffsitelink_erase_image = true; + var $config_nooffsitelink_text_message = 'Off-server linking is not allowed'; + + // * Border & Background default colors + var $config_border_hexcolor = '000000'; + var $config_background_hexcolor = 'FFFFFF'; + + // * TrueType Fonts + var $config_ttf_directory = '.'; + + var $config_max_source_pixels = null; + var $config_use_exif_thumbnail_for_speed = false; + + var $config_imagemagick_path = null; + var $config_prefer_imagemagick = true; + + var $config_cache_maxage = null; + var $config_cache_maxsize = null; + var $config_cache_maxfiles = null; + var $config_cache_source_filemtime_ignore_local = false; + var $config_cache_source_filemtime_ignore_remote = true; + var $config_cache_default_only_suffix = false; + var $config_cache_force_passthru = true; + var $config_cache_prefix = ''; // default value set in the constructor below + + // * MySQL + var $config_mysql_query = null; + var $config_mysql_hostname = null; + var $config_mysql_username = null; + var $config_mysql_password = null; + var $config_mysql_database = null; + + // * Security + var $config_high_security_enabled = false; + var $config_config_high_security_password = null; + var $config_disable_debug = false; + var $config_allow_src_above_docroot = false; + var $config_allow_src_above_phpthumb = true; + var $config_allow_parameter_file = false; + var $config_allow_parameter_goto = false; + + // * Compatability + var $config_disable_pathinfo_parsing = false; + var $config_disable_imagecopyresampled = false; + var $config_disable_onlycreateable_passthru = false; + + var $config_http_user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; + + // END CONFIGURATION OPTIONS + + + // public: error messages (read-only) + var $debugmessages = array(); + var $debugtiming = array(); + var $fatalerror = null; + + + // private: (should not be modified directly) + var $thumbnailQuality = 75; + var $thumbnailFormat = null; + + var $sourceFilename = null; + var $rawImageData = null; + var $IMresizedData = null; + + var $useRawIMoutput = false; + + var $gdimg_output = null; + var $gdimg_source = null; + + var $getimagesizeinfo = null; + + var $source_width = null; + var $source_height = null; + + var $thumbnailCropX = null; + var $thumbnailCropY = null; + var $thumbnailCropW = null; + var $thumbnailCropH = null; + + var $exif_thumbnail_width = null; + var $exif_thumbnail_height = null; + var $exif_thumbnail_type = null; + var $exif_thumbnail_data = null; + + var $thumbnail_width = null; + var $thumbnail_height = null; + var $thumbnail_image_width = null; + var $thumbnail_image_height = null; + + var $cache_filename = null; + + var $AlphaCapableFormats = array('png', 'ico', 'gif'); + var $is_alpha = false; + + var $iswindows = null; + + var $phpthumb_version = '1.7.0-200602150817'; + + ////////////////////////////////////////////////////////////////////// + + // public: constructor + function phpThumb() { + $this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__); + $this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__); + $this->config_max_source_pixels = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); // 20% of memory_limit + + //if (phpthumb_functions::gd_version() < 1) { + // die('No GD support detected'); + //} + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + $this->iswindows = true; + } else { + $this->iswindows = false; + } + if (@$_SERVER['DOCUMENT_ROOT']) { + $this->config_document_root = $_SERVER['DOCUMENT_ROOT']; + } + $this->config_cache_prefix = 'phpThumb_cache_'.@$_SERVER['SERVER_NAME']; + } + + // public: + function setSourceFilename($sourceFilename) { + $this->rawImageData = null; + $this->sourceFilename = $sourceFilename; + $this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->sourceFilename to "'.$this->sourceFilename.'"', __FILE__, __LINE__); + return true; + } + + // public: + function setSourceData($rawImageData, $sourceFilename='') { + $this->sourceFilename = null; + $this->rawImageData = $rawImageData; + $this->DebugMessage('setSourceData() setting $this->rawImageData ('.strlen($this->rawImageData).' bytes)', __FILE__, __LINE__); + if ($this->config_cache_source_enabled) { + $sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData)); + if (!is_dir($this->config_cache_source_directory)) { + $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory'); + } elseif (!is_writable($this->config_cache_source_directory)) { + $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable'); + } + $this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).'"', __FILE__, __LINE__); + if ($fp = @fopen($this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename), 'wb')) { + fwrite($fp, $rawImageData); + fclose($fp); + } elseif (!$this->phpThumbDebug) { + $this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).')'); + } + } + return true; + } + + // public: + function setSourceImageResource($gdimg) { + $this->gdimg_source = $gdimg; + return true; + } + + // public: + function setParameter($param, $value) { + switch ($param) { + case 'src': + $this->setSourceFilename($this->ResolveFilenameToAbsolute($value)); + break; + + default: + $this->$param = $value; + break; + } + $this->$param = $value; + return true; + } + + // public: + function getParameter($param) { + //if (property_exists('phpThumb', $param)) { + return $this->$param; + //} + //$this->DebugMessage('setParameter() attempting to set non-existant parameter "'.$param.'"', __FILE__, __LINE__); + //return false; + } + + + // public: + function GenerateThumbnail() { + + $this->setOutputFormat(); + $this->ResolveSource(); + $this->SetCacheFilename(); + $this->ExtractEXIFgetImageSize(); + if ($this->useRawIMoutput) { + $this->DebugMessage('Skipping rest of GenerateThumbnail() because $this->useRawIMoutput', __FILE__, __LINE__); + return true; + } + if (!$this->SourceImageToGD()) { + $this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__); + return false; + } + $this->Rotate(); + $this->CreateGDoutput(); + + switch ($this->far) { + case 'L': + case 'TL': + case 'BL': + $destination_offset_x = 0; + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + break; + case 'R': + case 'TR': + case 'BR': + $destination_offset_x = round($this->thumbnail_width - $this->thumbnail_image_width); + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + break; + case 'T': + case 'TL': + case 'TR': + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = 0; + break; + case 'B': + case 'BL': + case 'BR': + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = round($this->thumbnail_height - $this->thumbnail_image_height); + break; + case 'C': + default: + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + } + + // copy/resize image to appropriate dimensions + $this->DebugMessage('ImageResizeFunction($o, $s, '.$destination_offset_x.', '.$destination_offset_y.', '.$this->thumbnailCropX.', '.$this->thumbnailCropY.', '.$this->thumbnail_image_width.', '.$this->thumbnail_image_height.', '.$this->thumbnailCropW.', '.$this->thumbnailCropH.')', __FILE__, __LINE__); + $this->ImageResizeFunction( + $this->gdimg_output, + $this->gdimg_source, + $destination_offset_x, + $destination_offset_y, + $this->thumbnailCropX, + $this->thumbnailCropY, + $this->thumbnail_image_width, + $this->thumbnail_image_height, + $this->thumbnailCropW, + $this->thumbnailCropH + ); + + $this->DebugMessage('memory_get_usage() after copy-resize = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); + ImageDestroy($this->gdimg_source); + $this->DebugMessage('memory_get_usage() after ImageDestroy = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); + + $this->AntiOffsiteLinking(); + $this->ApplyFilters(); + $this->AlphaChannelFlatten(); + $this->MaxFileSize(); + + $this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__); + return true; + } + + + // public: + function RenderToFile($filename) { + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { + $this->DebugMessage('RenderToFile('.$filename.') failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); + return false; + } + if (!$this->thumbnailFormat) { + $this->DebugMessage('RenderToFile() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__); + return false; + } + // render thumbnail to this file only, do not cache, do not output to browser + //$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename); + $renderfilename = $filename; + if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) { + $renderfilename = $this->ResolveFilenameToAbsolute($renderfilename); + } + if (!is_writable(dirname($renderfilename))) { + $this->DebugMessage('RenderToFile() failed because "'.dirname($renderfilename).'/" is not writable', __FILE__, __LINE__); + return false; + } + if (is_file($renderfilename) && !is_writable($renderfilename)) { + $this->DebugMessage('RenderToFile() failed because "'.$renderfilename.'" is not writable', __FILE__, __LINE__); + return false; + } + + if ($this->useRawIMoutput) { + + $this->DebugMessage('RenderToFile copying $this->IMresizedData ('.strlen($this->IMresizedData).' bytes) to "'.$renderfilename.'"', __FILE__, __LINE__); + return file_put_contents($renderfilename, $this->IMresizedData); + + } else { + + $this->DebugMessage('RenderToFile('.$filename.') attempting Image'.strtoupper(@$this->thumbnailFormat).'($this->gdimg_output, '.$renderfilename.')', __FILE__, __LINE__); + ob_start(); + switch ($this->thumbnailFormat) { + case 'jpeg': + $ImageOutFunction = 'image'.$this->thumbnailFormat; + $ImageOutFunction($this->gdimg_output, $renderfilename, $this->thumbnailQuality); + break; + + case 'png': + case 'gif': + $ImageOutFunction = 'image'.$this->thumbnailFormat; + $ImageOutFunction($this->gdimg_output, $renderfilename); + break; + + case 'bmp': + $ImageOutFunction = '"builtin BMP output"'; + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $phpthumb_bmp = new phpthumb_bmp(); + $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); + unset($phpthumb_bmp); + if (!$bmp_data) { + $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + if (!file_put_contents($renderfilename, $bmp_data)) { + $this->DebugMessage('file_put_contents('.$renderfilename.', ['.strlen($bmp_data).' bytes]) failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + break; + + case 'ico': + $ImageOutFunction = '"builtin ICO output"'; + if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $phpthumb_ico = new phpthumb_ico(); + $arrayOfOutputImages = array($this->gdimg_output); + $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); + unset($phpthumb_ico); + if (!$ico_data) { + $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + if (!file_put_contents($renderfilename, $ico_data)) { + $this->DebugMessage('file_put_contents('.$renderfilename.', ['.strlen($ico_data).' bytes]) failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + break; + + default: + $this->DebugMessage('RenderToFile failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $errormessage = strip_tags(ob_get_contents()); + ob_end_clean(); + if ($errormessage) { + $this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] failed with message "'.$errormessage.'"', __FILE__, __LINE__); + return false; + } elseif (!file_exists($renderfilename)) { + $this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__); + } + + } + return true; + } + + + // public: + function OutputThumbnail() { + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { + $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); + return false; + } + if (headers_sent()) { + return $this->ErrorImage('OutputThumbnail() failed - headers already sent'); + exit; + } + + if ($this->down) { + $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $this->down); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) { + $downloadfilename = trim($downloadfilename, '.'); + } + if ($downloadfilename != $this->down) { + $this->DebugMessage('renaming output file for "down" from "'.$this->down.'" to "'.$downloadfilename.'"', __FILE__, __LINE__); + } + if ($downloadfilename) { + header('Content-Disposition: attachment; filename="'.$downloadfilename.'"'); + } else { + $this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__); + } + } + + if ($this->useRawIMoutput) { + + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $this->IMresizedData; + + } else { + + $this->DebugMessage('ImageInterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__); + ImageInterlace($this->gdimg_output, intval($this->config_output_interlace)); + switch ($this->thumbnailFormat) { + case 'jpeg': + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + $ImageOutFunction = 'image'.$this->thumbnailFormat; + @$ImageOutFunction($this->gdimg_output, '', $this->thumbnailQuality); + break; + + case 'png': + case 'gif': + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + $ImageOutFunction = 'image'.$this->thumbnailFormat; + @$ImageOutFunction($this->gdimg_output); + break; + + case 'bmp': + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); + return false; + } + $phpthumb_bmp = new phpthumb_bmp(); + if (is_object($phpthumb_bmp)) { + $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); + unset($phpthumb_bmp); + if (!$bmp_data) { + $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); + return false; + } + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $bmp_data; + } else { + $this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__); + return false; + } + break; + + case 'ico': + if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); + return false; + } + $phpthumb_ico = new phpthumb_ico(); + if (is_object($phpthumb_ico)) { + $arrayOfOutputImages = array($this->gdimg_output); + $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); + unset($phpthumb_ico); + if (!$ico_data) { + $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); + return false; + } + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $ico_data; + } else { + $this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__); + return false; + } + break; + + default: + $this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); + return false; + break; + } + + } + return true; + } + + + // public: + function CleanUpCacheDirectory() { + if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) { + $CacheDirOldFilesAge = array(); + $CacheDirOldFilesSize = array(); + if ($dirhandle = opendir($this->config_cache_directory)) { + while ($oldcachefile = readdir($dirhandle)) { + if (eregi('^phpThumb_cache_', $oldcachefile)) { + $CacheDirOldFilesAge[$oldcachefile] = fileatime($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + if ($CacheDirOldFilesAge[$oldcachefile] == 0) { + $CacheDirOldFilesAge[$oldcachefile] = filemtime($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + } + + $CacheDirOldFilesSize[$oldcachefile] = filesize($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + } + } + } + asort($CacheDirOldFilesAge); + + if ($this->config_cache_maxfiles > 0) { + $TotalCachedFiles = count($CacheDirOldFilesAge); + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($TotalCachedFiles > $this->config_cache_maxfiles) { + $TotalCachedFiles--; + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // there are few enough files to keep the rest + break; + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + if ($this->config_cache_maxage > 0) { + $mindate = time() - $this->config_cache_maxage; + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($filedate > 0) { + if ($filedate < $mindate) { + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // the rest of the files are new enough to keep + break; + } + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + if ($this->config_cache_maxsize > 0) { + $TotalCachedFileSize = array_sum($CacheDirOldFilesSize); + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($TotalCachedFileSize > $this->config_cache_maxsize) { + $TotalCachedFileSize -= $CacheDirOldFilesSize[$oldcachefile]; + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // the total filesizes are small enough to keep the rest of the files + break; + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + } + return true; + } + + ////////////////////////////////////////////////////////////////////// + + function ResolveSource() { + if (is_resource($this->gdimg_source)) { + $this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__); + return true; + } + if ($this->rawImageData) { + $this->sourceFilename = null; + $this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set', __FILE__, __LINE__); + return true; + } + if ($this->sourceFilename) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename); + $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'"', __FILE__, __LINE__); + } else { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); + $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'" from $this->src ('.$this->src.')', __FILE__, __LINE__); + } + if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) { + // Windows \\share\filename.ext + } elseif (eregi('^(f|ht)tps?://', $this->sourceFilename)) { + // URL + if ($this->config_http_user_agent) { + ini_set('user_agent', $this->config_http_user_agent); + } + } elseif (!file_exists($this->sourceFilename)) { + return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist'); + } elseif (!is_file($this->sourceFilename)) { + return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file'); + } + return true; + } + + function setOutputFormat() { + static $alreadyCalled = false; + if ($this->thumbnailFormat && $alreadyCalled) { + return true; + } + $alreadyCalled = true; + + $AvailableImageOutputFormats = array(); + $AvailableImageOutputFormats[] = 'text'; + if (is_readable(dirname(__FILE__).'/phpthumb.ico.php')) { + $AvailableImageOutputFormats[] = 'ico'; + } + if (is_readable(dirname(__FILE__).'/phpthumb.bmp.php')) { + $AvailableImageOutputFormats[] = 'bmp'; + } + + $this->thumbnailFormat = 'ico'; + + // Set default output format based on what image types are available + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_WBMP) { + $this->thumbnailFormat = 'wbmp'; + $AvailableImageOutputFormats[] = 'wbmp'; + } + if ($imagetypes & IMG_GIF) { + $this->thumbnailFormat = 'gif'; + $AvailableImageOutputFormats[] = 'gif'; + } + if ($imagetypes & IMG_PNG) { + $this->thumbnailFormat = 'png'; + $AvailableImageOutputFormats[] = 'png'; + } + if ($imagetypes & IMG_JPG) { + $this->thumbnailFormat = 'jpeg'; + $AvailableImageOutputFormats[] = 'jpeg'; + } + } else { + //return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?'); + $this->DebugMessage('ImageTypes() does not exist - GD support might not be enabled?', __FILE__, __LINE__); + } + if ($this->ImageMagickVersion()) { + $IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico'); + $this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats ('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); + foreach ($IMformats as $key => $format) { + $AvailableImageOutputFormats[] = $format; + } + } + $AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats); + $this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); + + if (strtolower($this->config_output_format) == 'jpg') { + $this->config_output_format = 'jpeg'; + } + if (strtolower($this->f) == 'jpg') { + $this->f = 'jpeg'; + } + if (in_array(strtolower($this->config_output_format), $AvailableImageOutputFormats)) { + // set output format to config default if that format is available + $this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__); + $this->thumbnailFormat = strtolower($this->config_output_format); + } elseif ($this->config_output_format) { + $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->config_output_format ('.strtolower($this->config_output_format).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); + } + if ($this->f && (in_array(strtolower($this->f), $AvailableImageOutputFormats))) { + // override output format if $this->f is set and that format is available + $this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__); + $this->thumbnailFormat = strtolower($this->f); + } elseif ($this->f) { + $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->f ('.strtolower($this->f).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); + } + + // for JPEG images, quality 1 (worst) to 99 (best) + // quality < 25 is nasty, with not much size savings - not recommended + // problems with 100 - invalid JPEG? + $this->thumbnailQuality = max(1, min(99, ($this->q ? $this->q : 75))); + $this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__); + + return true; + } + + function setCacheDirectory() { + // resolve cache directory to absolute pathname + $this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__); + if (substr($this->config_cache_directory, 0, 1) == '.') { + if (eregi('^(f|ht)tps?://', $this->src)) { + if (!$this->config_cache_disable_warning) { + $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); + } + } elseif ($this->src) { + // resolve relative cache directory to source image + $this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory; + } else { + // $this->new is probably set + } + } + if (substr($this->config_cache_directory, -1) == '/') { + $this->config_cache_directory = substr($this->config_cache_directory, 0, -1); + } + if ($this->iswindows) { + $this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory); + } + if ($this->config_cache_directory) { + $real_cache_path = realpath($this->config_cache_directory); + if (!$real_cache_path) { + $this->DebugMessage('realpath($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__); + if (!is_dir($this->config_cache_directory)) { + $this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__); + } + } + if ($real_cache_path) { + $this->DebugMessage('setting config_cache_directory to realpath('.$this->config_cache_directory.') = "'.$real_cache_path.'"', __FILE__, __LINE__); + $this->config_cache_directory = $real_cache_path; + } + } + if (!is_dir($this->config_cache_directory)) { + if (!$this->config_cache_disable_warning) { + $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); + } + $this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__); + $this->config_cache_directory = null; + } elseif (!is_writable($this->config_cache_directory)) { + $this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__); + } + return true; + } + + + function ResolveFilenameToAbsolute($filename) { + if (eregi('^(f|ht)tps?://', $filename)) { + + // URL + //$AbsoluteFilename = $filename; + return $filename; + + } elseif ($this->iswindows && ($filename{1} == ':')) { + + // absolute pathname (Windows) + $AbsoluteFilename = $filename; + + } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) { + + // absolute pathname (Windows) + $AbsoluteFilename = $filename; + + } elseif ($filename{0} == '/') { + + if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) { + + // absolute filename (*nix) + $AbsoluteFilename = $filename; + + } elseif ($filename{1} == '~') { + + // /~user/path + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) { + $AbsoluteFilename = $ApacheLookupURIarray['filename']; + } else { + $AbsoluteFilename = realpath($filename); + if (@is_readable($AbsoluteFilename)) { + $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__); + } else { + return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image'); + } + } + + } else { + + // relative filename (any OS) + if (ereg('^'.preg_quote($this->config_document_root), $filename)) { + $AbsoluteFilename = $filename; + $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); + } else { + $AbsoluteFilename = $this->config_document_root.$filename; + $this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); + } + + } + + } else { + + // relative to current directory (any OS) + $AbsoluteFilename = $this->config_document_root.dirname(@$_SERVER['PHP_SELF']).DIRECTORY_SEPARATOR.$filename; + //if (!file_exists($AbsoluteFilename) && file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) { + // $AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename)); + //} + + if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') { + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { + $AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename; + } else { + $AbsoluteFilename = realpath('.').DIRECTORY_SEPARATOR.$filename; + if (@is_readable($AbsoluteFilename)) { + $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__); + } else { + return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image'); + } + } + } + + } + if (is_link($AbsoluteFilename)) { + $this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__); + $AbsoluteFilename = readlink($AbsoluteFilename); + } + if (realpath($AbsoluteFilename)) { + $AbsoluteFilename = realpath($AbsoluteFilename); + } + if ($this->iswindows) { + $AbsoluteFilename = eregi_replace('^'.preg_quote(realpath($this->config_document_root)), realpath($this->config_document_root), $AbsoluteFilename); + $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename); + } + if (!$this->config_allow_src_above_docroot && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))), $AbsoluteFilename)) { + $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.realpath($this->config_document_root).'") to null', __FILE__, __LINE__); + return false; + } + if (!$this->config_allow_src_above_phpthumb && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))), $AbsoluteFilename)) { + $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__); + return false; + } + return $AbsoluteFilename; + } + + function ImageMagickWhichConvert() { + static $WhichConvert = null; + if (is_null($WhichConvert)) { + if ($this->iswindows) { + $WhichConvert = false; + } else { + $WhichConvert = trim(phpthumb_functions::SafeExec('which convert')); + } + } + return $WhichConvert; + } + + function ImageMagickCommandlineBase() { + static $commandline = null; + if (is_null($commandline)) { + $commandline = $this->config_imagemagick_path; + $commandline = (!is_null($commandline) ? $commandline : ''); + + $which_convert = $this->ImageMagickWhichConvert(); + $IMversion = $this->ImageMagickVersion(); + + if ($this->config_imagemagick_path && ($this->config_imagemagick_path != realpath($this->config_imagemagick_path))) { + if (@is_executable(realpath($this->config_imagemagick_path))) { + $this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to realpath($this->config_imagemagick_path) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); + $this->config_imagemagick_path = realpath($this->config_imagemagick_path); + } else { + $this->DebugMessage('Leaving $this->config_imagemagick_path as ('.$this->config_imagemagick_path.') because !is_execuatable(realpath($this->config_imagemagick_path)) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); + } + } + $this->DebugMessage(' file_exists('.$this->config_imagemagick_path.') = '.intval( @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__); + $this->DebugMessage('is_executable('.$this->config_imagemagick_path.') = '.intval(@is_executable($this->config_imagemagick_path)), __FILE__, __LINE__); + if (@file_exists($this->config_imagemagick_path)) { + + $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__); + if ($this->iswindows) { + $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.substr(dirname($this->config_imagemagick_path), 2).'" && '.basename($this->config_imagemagick_path); + } else { + $commandline = '"'.$this->config_imagemagick_path.'"'; + } + + } elseif ($which_convert && ($which_convert{0} == '/') && @file_exists($which_convert)) { + + // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't + // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin" + // so only do this if the value returned exists as a file + $this->DebugMessage('using ImageMagick path from `which convert` ('.$which_convert.')', __FILE__, __LINE__); + $commandline = 'convert'; + + } elseif ($IMversion) { + + $this->DebugMessage('setting ImageMagick path to $this->config_imagemagick_path ('.$this->config_imagemagick_path.') ['.$IMversion.']', __FILE__, __LINE__); + $commandline = $this->config_imagemagick_path; + + } else { + + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path ('.$this->config_imagemagick_path.'), and `which convert` returned ('.$which_convert.')', __FILE__, __LINE__); + $commandline = ''; + + } + } + return $commandline; + } + + function ImageMagickVersion() { + static $versionstring = null; + if (is_null($versionstring)) { + $commandline = $this->ImageMagickCommandlineBase(); + $commandline = (!is_null($commandline) ? $commandline : ''); + + if ($commandline) { + $commandline .= ' -version'; + $versionstring = phpthumb_functions::SafeExec($commandline); + if (eregi('^Version: (.*) http', $versionstring, $matches)) { + $versionstring = $matches[1]; + } else { + $versionstring = false; + $this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring.')', __FILE__, __LINE__); + } + } + } + return $versionstring; + } + + function ImageMagickThumbnailToGD() { + // http://www.imagemagick.org/script/command-line-options.php + + $this->useRawIMoutput = true; + if (phpthumb_functions::gd_version()) { + //$UnAllowedParameters = array('sx', 'sy', 'sw', 'sh', 'xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); + $UnAllowedParameters = array('xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); + foreach ($UnAllowedParameters as $dummy => $parameter) { + if ($this->$parameter) { + $this->DebugMessage('$this->useRawIMoutput=false because "'.$parameter.'" is set', __FILE__, __LINE__); + $this->useRawIMoutput = false; + break; + } + } + } + $outputFormat = $this->thumbnailFormat; + if (phpthumb_functions::gd_version()) { + if ($this->useRawIMoutput) { + switch ($this->thumbnailFormat) { + case 'gif': + $ImageCreateFunction = 'ImageCreateFromGIF'; + $this->is_alpha = true; + break; + case 'png': + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + break; + case 'jpg': + case 'jpeg': + $ImageCreateFunction = 'ImageCreateFromJPEG'; + break; + default: + $outputFormat = 'png'; + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + $this->useRawIMoutput = false; + break; + } + if (!function_exists(@$ImageCreateFunction)) { + // ImageMagickThumbnailToGD() depends on ImageCreateFromPNG/ImageCreateFromGIF + //$this->DebugMessage('ImageMagickThumbnailToGD() aborting because '.@$ImageCreateFunction.'() is not available', __FILE__, __LINE__); + $this->useRawIMoutput = true; + //return false; + } + } else { + $outputFormat = 'png'; + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + $this->useRawIMoutput = false; + } + } + + // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html + if (!$this->sourceFilename) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } + if (ini_get('safe_mode')) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } + + $commandline = $this->ImageMagickCommandlineBase(); + if ($commandline) { + if ($IMtempfilename = $this->phpThumb_tempnam()) { + + if (!eregi('('.implode('|', $this->AlphaCapableFormats).')', $outputFormat)) { + // not a transparency-capable format + $commandline .= ' -background "#'.($this->bg ? $this->bg : 'FFFFFF').'"'; + $commandline .= ' -flatten'; + } + $IMtempfilename = realpath($IMtempfilename); + if ($getimagesize = GetImageSize($this->sourceFilename)) { + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') returned [w='.$getimagesize[0].';h='.$getimagesize[1].';f='.$getimagesize[2].']', __FILE__, __LINE__); + $this->source_width = $getimagesize[0]; + $this->source_height = $getimagesize[1]; + $this->DebugMessage('source dimensions set to '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__); + $this->SetOrientationDependantWidthHeight(); + + $commandline .= ' -coalesce'; // may be needed for animated GIFs + if ($this->source_width || $this->source_height) { + if ($this->zc) { + + $side = min($this->source_width, $this->source_height, max($this->w, $this->wp, $this->wl, $this->ws, $this->h, $this->hp, $this->hl, $this->hs)); + if ($getimagesize[0] > $getimagesize[1]) { + $commandline .= ' -thumbnail x'.$side; + } else { + $commandline .= ' -thumbnail '.$side.'x'; + } + $commandline .= ' -gravity center'; + $commandline .= ' -crop '.$side.'x'.$side.'+0+0'; + $commandline .= ' +repage'; + + } elseif ($this->sw || $this->sh || $this->sx || $this->sy) { + + $commandline .= ' -crop '.($this->sw ? $this->sw : $this->source_width).'x'.($this->sh ? $this->sh : $this->source_height).'+'.$this->sx.'+'.$this->sy; + // this is broken for aoe=1, but unsure how to fix. Send advice to info@silisoftware.com + + } else { + + $this->w = (($this->aoe && $this->w) ? max($this->w, $getimagesize[0]) : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : '')); + $this->h = (($this->aoe && $this->h) ? max($this->h, $getimagesize[1]) : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : '')); + if ($this->w || $this->h) { + $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; + if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { + $commandline .= '!'; + } + } + } + } + + } else { + + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') failed', __FILE__, __LINE__); + $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; + if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { + $commandline .= '!'; + } + + } + foreach ($this->fltr as $filterkey => $filtercommand) { + @list($command, $parameter) = explode('|', $filtercommand, 2); + switch ($command) { + case 'brit': + $commandline .= ' -modulate '.(100 + $parameter).',100,100'; + unset($this->fltr[$filterkey]); + break; + + case 'cont': + $contDiv10 = round($parameter / 10); + if ($contDiv10 > 0) { + for ($i = 0; $i < $contDiv10; $i++) { + $commandline .= ' -contrast'; // increase contrast by 10% + } + } elseif ($contDiv10 < 0) { + for ($i = $contDiv10; $i < 0; $i++) { + $commandline .= ' +contrast'; // decrease contrast by 10% + } + } else { + // do nothing + } + unset($this->fltr[$filterkey]); + break; + + case 'ds': + if ($parameter == 100) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + } else { + $commandline .= ' -modulate 100,'.(100 - $parameter).',100'; + } + unset($this->fltr[$filterkey]); + break; + + case 'sat': + if ($parameter == -100) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + } else { + $commandline .= ' -modulate 100,'.(100 + $parameter).',100'; + } + unset($this->fltr[$filterkey]); + break; + + case 'gray': + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + //$commandline .= ' -colorspace GRAY'; + unset($this->fltr[$filterkey]); + break; + + case 'clr': + @list($amount, $color) = explode('|', $parameter); + $commandline .= ' -fill #'.$color.' -colorize '.$amount; + break; + + case 'sep': + @list($amount, $color) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + if (!$color) { + $commandline .= ' -sepia-tone '.$amount.'%'; + unset($this->fltr[$filterkey]); + } + break; + + case 'gam': + $commandline .= ' -gamma '.$parameter; + unset($this->fltr[$filterkey]); + break; + + case 'neg': + $commandline .= ' -negate'; + unset($this->fltr[$filterkey]); + break; + + case 'th': + $commandline .= ' -threshold '.round($parameter / 2.55).'% -dither -monochrome'; + unset($this->fltr[$filterkey]); + break; + + case 'rcd': + @list($colors, $dither) = explode('|', $parameter); + $colors = ($colors ? (int) $colors : 256); + $dither = ((strlen($dither) > 0) ? (bool) $dither : true); + $commandline .= ' -colors '.max($colors, 8); // ImageMagick will otherwise fail with "cannot quantize to fewer than 8 colors" + $commandline .= ($dither ? ' -dither' : ' +dither'); + unset($this->fltr[$filterkey]); + break; + + case 'flip': + if (strpos(strtolower($parameter), 'x') !== false) { + $commandline .= ' -flop'; + } + if (strpos(strtolower($parameter), 'y') !== false) { + $commandline .= ' -flip'; + } + unset($this->fltr[$filterkey]); + break; + + case 'edge': + $parameter = ($parameter ? $parameter : 2); + $commandline .= ' -edge '.($parameter ? $parameter : 1); + unset($this->fltr[$filterkey]); + break; + + case 'emb': + $parameter = ($parameter ? $parameter : 2); + $commandline .= ' -emboss '.$parameter; + if ($parameter < 2) { + $commandline .= ' -negate'; // ImageMagick negates the image for some reason with '-emboss 1'; + } + unset($this->fltr[$filterkey]); + break; + + case 'lvl': + @list($band, $min, $max) = explode('|', $parameter); + $band = ($band ? $band : '*'); + $min = ((strlen($min) > 0) ? $min : '-1'); + $max = ((strlen($max) > 0) ? $max : '-1'); + if ($band == '*') { + if (($min == -1) && ($max == -1)) { + $commandline .= ' -normalize'; + unset($this->fltr[$filterkey]); + } elseif (($min == -1) || ($max == -1)) { + // + } else { + $commandline .= ' -level '.$min.'%,'.$max.'%'; + unset($this->fltr[$filterkey]); + } + } + break; + + case 'blur': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + $commandline .= ' -blur '.$radius; + unset($this->fltr[$filterkey]); + break; + + case 'gblr': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + $commandline .= ' -gaussian '.$radius; + unset($this->fltr[$filterkey]); + break; + + case 'usm': + @list($amount, $radius, $threshold) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + $radius = ($radius ? $radius : 0.5); + $threshold = (strlen($threshold) ? $threshold : 3); + $commandline .= ' -unsharp '.number_format(($radius * 2) - 1, 2).'x1+'.number_format($amount / 100, 2).'+'.number_format($threshold / 100, 2); + unset($this->fltr[$filterkey]); + break; + + case 'sblr': + break; + + case 'mean': + break; + + case 'smth': + break; + + case 'bvl': + break; + + case 'wmi': + break; + + case 'wmt': + break; + + case 'over': + break; + + case 'wb': + break; + + case 'hist': + break; + + case 'fram': + break; + + case 'drop': + break; + + case 'mask': + break; + + case 'elip': + break; + + case 'ric': + break; + + case 'bord': + break; + + } + if (!isset($this->fltr[$filterkey])) { + $this->DebugMessage('Processed $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); + } else { + $this->DebugMessage('Skipping $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); + } + } + $this->DebugMessage('Remaining $this->fltr after ImageMagick: ('.$this->phpThumbDebugVarDump($this->fltr).')', __FILE__, __LINE__); + + if (eregi('jpe?g', $outputFormat) && $this->q) { + $commandline .= ' -quality '.$this->thumbnailQuality; + if ($this->config_output_interlace) { + // causes weird things with animated GIF... leave for JPEG only + $commandline .= ' -interlace line '; // Use Line or Plane to create an interlaced PNG or GIF or progressive JPEG image + } + } + $commandline .= ' "'.str_replace('/', DIRECTORY_SEPARATOR, $this->sourceFilename).(($outputFormat == 'gif') ? '' : '[0]').'"'; // [0] means first frame of (GIF) animation, can be ignored + $commandline .= ' '.$outputFormat.':"'.$IMtempfilename.'"'; + $commandline .= ' 2>&1'; + $this->DebugMessage('ImageMagick called as ('.$commandline.')', __FILE__, __LINE__); + $IMresult = phpthumb_functions::SafeExec($commandline); +//var_Dump($commandline); +//var_dump($ImageCreateFunction); +//exit; + clearstatcache(); + if (!file_exists($IMtempfilename) || !filesize($IMtempfilename)) { + + $this->DebugMessage('ImageMagick failed with message ('.$IMresult.')', __FILE__, __LINE__); + + } else { + + $this->IMresizedData = file_get_contents($IMtempfilename); + if (function_exists(@$ImageCreateFunction) && ($this->gdimg_source = @$ImageCreateFunction($IMtempfilename))) { +//header('Content-Type: image/png'); +//phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_source, true); +//ImagePNG($this->gdimg_source); +//exit; + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $this->DebugMessage('ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() succeeded, $this->gdimg_source is now ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); + $this->DebugMessage('ImageMagickThumbnailToGD() returning $IMresizedData ('.strlen($this->IMresizedData).' bytes)', __FILE__, __LINE__); + } else { + $this->useRawIMoutput = true; + $this->DebugMessage('$this->useRawIMoutput set to TRUE because '.@$ImageCreateFunction.'('.$IMtempfilename.') failed', __FILE__, __LINE__); + } + @unlink($IMtempfilename); + return true; + + } + unlink($IMtempfilename); + + } else { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpThumb_tempnam() failed', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__); + } + $this->useRawIMoutput = false; + return false; + } + + + function Rotate() { + if ($this->ra || $this->ar) { + if (!function_exists('ImageRotate')) { + $this->DebugMessage('!function_exists(ImageRotate)', __FILE__, __LINE__); + return false; + } + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); + return false; + } + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + + $rotate_angle = 0; + if ($this->ra) { + + $rotate_angle = floatval($this->ra); + + } else { + + if ($this->ar == 'x') { + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=')) { + if ($this->sourceFilename) { + if (function_exists('exif_read_data')) { + if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) { + // http://sylvana.net/jpegcrop/exif_orientation.html + switch (@$exif_data['Orientation']) { + case 1: + $rotate_angle = 0; + break; + case 3: + $rotate_angle = 180; + break; + case 6: + $rotate_angle = 270; + break; + case 8: + $rotate_angle = 90; + break; + + default: + $this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "'.@$exif_data['Orientation'].'"', __FILE__, __LINE__); + return false; + break; + } + $this->DebugMessage('EXIF auto-rotate set to '.$rotate_angle.' degrees ($exif_data[Orientation] = "'.@$exif_data['Orientation'].'")', __FILE__, __LINE__); + } else { + $this->DebugMessage('failed: exif_read_data('.$this->sourceFilename.')', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 ('.phpversion().')', __FILE__, __LINE__); + return false; + } + } elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) { + $rotate_angle = 270; + } elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) { + $rotate_angle = 90; + } elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) { + $rotate_angle = 90; + } elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) { + $rotate_angle = 270; + } + + } + while ($rotate_angle < 0) { + $rotate_angle += 360; + } + $rotate_angle = $rotate_angle % 360; + if ($rotate_angle != 0) { + + if ($rotate_angle % 90) { + $this->is_alpha = true; + } + + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_source, $this->config_background_hexcolor); + + //if ((phpthumb_functions::gd_version() >= 2) && in_array($this->thumbnailFormat, $this->AlphaCapableFormats) && !$this->bg && ($rotate_angle % 90)) { + if ((phpthumb_functions::gd_version() >= 2) && !$this->bg && ($rotate_angle % 90)) { + + $this->DebugMessage('Using alpha rotate', __FILE__, __LINE__); + if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_source), ImageSY($this->gdimg_source))) { + + for ($i = 0; $i <= 255; $i++) { + $color_mask[$i] = ImageColorAllocate($gdimg_rotate_mask, $i, $i, $i); + } + ImageFilledRectangle($gdimg_rotate_mask, 0, 0, ImageSX($gdimg_rotate_mask), ImageSY($gdimg_rotate_mask), $color_mask[255]); + $imageX = ImageSX($this->gdimg_source); + $imageY = ImageSY($this->gdimg_source); + for ($x = 0; $x < $imageX; $x++) { + for ($y = 0; $y < $imageY; $y++) { + $pixelcolor = phpthumb_functions::GetPixelColor($this->gdimg_source, $x, $y); + ImageSetPixel($gdimg_rotate_mask, $x, $y, $color_mask[255 - round($pixelcolor['alpha'] * 255 / 127)]); + } + } + $gdimg_rotate_mask = ImageRotate($gdimg_rotate_mask, $rotate_angle, $color_mask[0]); + $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color); + + ImageAlphaBlending($this->gdimg_source, false); + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_source, true); + $this->is_alpha = true; + $phpThumbFilters = new phpthumb_filters(); + $phpThumbFilters->phpThumbObject = $this; + $phpThumbFilters->ApplyMask($gdimg_rotate_mask, $this->gdimg_source); + + ImageDestroy($gdimg_rotate_mask); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + + } else { + + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + } elseif ($this->bg) { + $this->DebugMessage('Using non-alpha rotate because $this->bg is "'.$this->bg.'"', __FILE__, __LINE__); + } elseif ($this->bg) { + $this->DebugMessage('Using non-alpha rotate because ($rotate_angle % 90) = "'.($rotate_angle % 90).'"', __FILE__, __LINE__); + } else { + $this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); + } + + if (ImageColorTransparent($this->gdimg_source) >= 0) { + // ImageRotate() forgets all about an image's transparency and sets the transparent color to black + // To compensate, flood-fill the transparent color of the source image with the specified background color first + // then rotate and the colors should match + + if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($this->gdimg_source)) { + // convert paletted image to true-color before rotating to prevent nasty aliasing artifacts + + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $gdimg_newsrc = phpthumb_functions::ImageCreateFunction($this->source_width, $this->source_height); + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor); + ImageFilledRectangle($gdimg_newsrc, 0, 0, $this->source_width, $this->source_height, phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor)); + ImageCopy($gdimg_newsrc, $this->gdimg_source, 0, 0, 0, 0, $this->source_width, $this->source_height); + ImageDestroy($this->gdimg_source); + unset($this->gdimg_source); + $this->gdimg_source = $gdimg_newsrc; + unset($gdimg_newsrc); + + } else { + + ImageColorSet( + $this->gdimg_source, + ImageColorTransparent($this->gdimg_source), + hexdec(substr($this->config_background_hexcolor, 0, 2)), + hexdec(substr($this->config_background_hexcolor, 2, 2)), + hexdec(substr($this->config_background_hexcolor, 4, 2))); + + ImageColorTransparent($this->gdimg_source, -1); + + } + } + + $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + } + } + } + return true; + } + + + function FixedAspectRatio() { + // optional fixed-dimension images (regardless of aspect ratio) + + if (!$this->far) { + // do nothing + return true; + } + + if (!$this->w || !$this->h) { + return false; + } + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->is_alpha = true; + if ($this->thumbnail_image_width >= $this->thumbnail_width) { + + if ($this->w) { + $aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width; + $this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio); + if (!$this->h) { + $this->thumbnail_height = $this->thumbnail_image_height; + } + } elseif ($this->thumbnail_image_height < $this->thumbnail_height) { + $this->thumbnail_image_height = $this->thumbnail_height; + $this->thumbnail_image_width = round($this->thumbnail_image_height / $aspectratio); + } + + } else { + + if ($this->h) { + $aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height; + $this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio); + } elseif ($this->thumbnail_image_width < $this->thumbnail_width) { + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = round($this->thumbnail_image_width / $aspectratio); + } + + } + return true; + } + + + function AntiOffsiteLinking() { + // Optional anti-offsite hijacking of the thumbnail script + $allow = true; + if ($allow && $this->config_nooffsitelink_enabled && (@$_SERVER['HTTP_REFERER'] || $this->config_nooffsitelink_require_refer)) { + $this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "'.@$_SERVER['HTTP_REFERER'].'"', __FILE__, __LINE__); + $parsed_url = parse_url(@$_SERVER['HTTP_REFERER']); + if (!in_array(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) { + $allow = false; + $erase = $this->config_nooffsitelink_erase_image; + $message = $this->config_nooffsitelink_text_message; + $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + } else { + $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + } + } + + if ($allow && $this->config_nohotlink_enabled && eregi('^(f|ht)tps?://', $this->src)) { + $parsed_url = parse_url($this->src); + if (!in_array(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) { + // This domain is not allowed + $allow = false; + $erase = $this->config_nohotlink_erase_image; + $message = $this->config_nohotlink_text_message; + $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is NOT in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); + } else { + $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); + } + } + + if ($allow) { + $this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__); + return true; + } + + if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_error_bgcolor.'" for $this->config_error_bgcolor'); + } + if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_error_textcolor.'" for $this->config_error_textcolor'); + } + if ($erase) { + + return $this->ErrorImage($message, $this->thumbnail_width, $this->thumbnail_height, $this->config_error_bgcolor, $this->config_error_textcolor, $this->config_error_fontsize); + + } else { + + $nohotlink_text_array = explode("\n", wordwrap($message, floor($this->thumbnail_width / ImageFontWidth($this->config_error_fontsize)), "\n")); + $nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor); + + $topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * ImageFontHeight($this->config_error_fontsize))) / 2); + + $rowcounter = 0; + $this->DebugMessage('AntiOffsiteLinking() writing '.count($nohotlink_text_array).' lines of text "'.$message.'" (in #'.$this->config_error_textcolor.') on top of image', __FILE__, __LINE__); + foreach ($nohotlink_text_array as $dummy => $textline) { + $leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * ImageFontWidth($this->config_error_fontsize))) / 2)); + ImageString($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * ImageFontHeight($this->config_error_fontsize)), $textline, $nohotlink_text_color); + } + + } + return true; + } + + + function AlphaChannelFlatten() { + if (!$this->is_alpha) { + // image doesn't have alpha transparency, no need to flatten + $this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__); + return false; + } + switch ($this->thumbnailFormat) { + case 'png': + case 'ico': + // image has alpha transparency, but output as PNG or ICO which can handle it + $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'")', __FILE__, __LINE__); + return false; + break; + + case 'gif': + // image has alpha transparency, but output as GIF which can handle only single-color transparency + $CurrentImageColorTransparent = ImageColorTransparent($this->gdimg_output); + if ($CurrentImageColorTransparent == -1) { + // no transparent color defined + + if (phpthumb_functions::gd_version() < 2.0) { + $this->DebugMessage('AlphaChannelFlatten() failed because GD version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + + if ($img_alpha_mixdown_dither = @ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { + + for ($i = 0; $i <= 255; $i++) { + $dither_color[$i] = ImageColorAllocate($img_alpha_mixdown_dither, $i, $i, $i); + } + + // scan through current truecolor image copy alpha channel to temp image as grayscale + for ($x = 0; $x < $this->thumbnail_width; $x++) { + for ($y = 0; $y < $this->thumbnail_height; $y++) { + $PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y); + ImageSetPixel($img_alpha_mixdown_dither, $x, $y, $dither_color[($PixelColor['alpha'] * 2)]); + } + } + + // dither alpha channel grayscale version down to 2 colors + ImageTrueColorToPalette($img_alpha_mixdown_dither, true, 2); + + // reduce color palette to 256-1 colors (leave one palette position for transparent color) + ImageTrueColorToPalette($this->gdimg_output, true, 255); + + // allocate a new color for transparent color index + $TransparentColor = ImageColorAllocate($this->gdimg_output, 1, 254, 253); + ImageColorTransparent($this->gdimg_output, $TransparentColor); + + // scan through alpha channel image and note pixels with >50% transparency + $TransparentPixels = array(); + for ($x = 0; $x < $this->thumbnail_width; $x++) { + for ($y = 0; $y < $this->thumbnail_height; $y++) { + $AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y); + if ($AlphaChannelPixel['red'] > 127) { + ImageSetPixel($this->gdimg_output, $x, $y, $TransparentColor); + } + } + } + ImageDestroy($img_alpha_mixdown_dither); + + $this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__); + return true; + + } else { + $this->DebugMessage('AlphaChannelFlatten() failed ImageCreate('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); + return false; + } + + } else { + // a single transparent color already defined, leave as-is + $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'") and ImageColorTransparent returned "'.$CurrentImageColorTransparent.'"', __FILE__, __LINE__); + return true; + } + break; + } + $this->DebugMessage('continuing AlphaChannelFlatten() for output format "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); + + // image has alpha transparency, and is being output in a format that doesn't support it -- flatten + if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) { + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); + ImageFilledRectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); + ImageCopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); + + ImageAlphaBlending($this->gdimg_output, true); + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_output, false); + ImageColorTransparent($this->gdimg_output, -1); + ImageCopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); + + ImageDestroy($gdimg_flatten_temp); + return true; + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + return false; + } + + + function ApplyFilters() { + if ($this->fltr && is_array($this->fltr)) { + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); + return false; + } + $phpthumbFilters = new phpthumb_filters(); + $phpthumbFilters->phpThumbObject = $this; + foreach ($this->fltr as $dummy => $filtercommand) { + @list($command, $parameter) = explode('|', $filtercommand, 2); + $this->DebugMessage('Attempting to process filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__); + switch ($command) { + case 'brit': + $phpthumbFilters->Brightness($this->gdimg_output, $parameter); + break; + + case 'cont': + $phpthumbFilters->Contrast($this->gdimg_output, $parameter); + break; + + case 'ds': + $phpthumbFilters->Desaturate($this->gdimg_output, $parameter, ''); + break; + + case 'sat': + $phpthumbFilters->Saturation($this->gdimg_output, $parameter, ''); + break; + + case 'gray': + $phpthumbFilters->Grayscale($this->gdimg_output); + break; + + case 'clr': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Colorize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($amount, $color) = explode('|', $parameter); + $phpthumbFilters->Colorize($this->gdimg_output, $amount, $color); + break; + + case 'sep': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Sepia() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($amount, $color) = explode('|', $parameter); + $phpthumbFilters->Sepia($this->gdimg_output, $amount, $color); + break; + + case 'gam': + $phpthumbFilters->Gamma($this->gdimg_output, $parameter); + break; + + case 'neg': + $phpthumbFilters->Negative($this->gdimg_output); + break; + + case 'th': + $phpthumbFilters->Threshold($this->gdimg_output, $parameter); + break; + + case 'rcd': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping ReduceColorDepth() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($colors, $dither) = explode('|', $parameter); + $colors = ($colors ? (int) $colors : 256); + $dither = ((strlen($dither) > 0) ? (bool) $dither : true); + $phpthumbFilters->ReduceColorDepth($this->gdimg_output, $colors, $dither); + break; + + case 'flip': + $phpthumbFilters->Flip($this->gdimg_output, (strpos(strtolower($parameter), 'x') !== false), (strpos(strtolower($parameter), 'y') !== false)); + break; + + case 'edge': + $phpthumbFilters->EdgeDetect($this->gdimg_output); + break; + + case 'emb': + $phpthumbFilters->Emboss($this->gdimg_output); + break; + + case 'bvl': + @list($width, $color1, $color2) = explode('|', $parameter); + $phpthumbFilters->Bevel($this->gdimg_output, $width, $color1, $color2); + break; + + case 'lvl': + @list($band, $min, $max) = explode('|', $parameter); + $band = ($band ? $band : '*'); + $min = ((strlen($min) > 0) ? $min : '-1'); + $max = ((strlen($max) > 0) ? $max : '-1'); + $phpthumbFilters->HistogramStretch($this->gdimg_output, $band, $min, $max); + break; + + case 'wb': + $phpthumbFilters->WhiteBalance($this->gdimg_output, $parameter); + break; + + case 'hist': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping HistogramOverlay() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($bands, $colors, $width, $height, $alignment, $opacity, $margin) = explode('|', $parameter); + $bands = ($bands ? $bands : '*'); + $colors = ($colors ? $colors : ''); + $width = ($width ? $width : 0.25); + $height = ($height ? $height : 0.25); + $alignment = ($alignment ? $alignment : 'BR'); + $opacity = ($opacity ? $opacity : 50); + $margin = ($margin ? $margin : 5); + $phpthumbFilters->HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin); + break; + + case 'fram': + @list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter); + $phpthumbFilters->Frame($this->gdimg_output, $frame_width, $edge_width, $color_frame, $color1, $color2); + break; + + case 'drop': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping DropShadow() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $this->is_alpha = true; + @list($distance, $width, $color, $angle, $fade) = explode('|', $parameter); + $phpthumbFilters->DropShadow($this->gdimg_output, $distance, $width, $color, $angle, $fade); + break; + + case 'mask': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Mask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $mask_filename = $this->ResolveFilenameToAbsolute($parameter); + if (@is_readable($mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) { + $MaskImageData = fread($fp_mask, filesize($mask_filename)); + fclose($fp_mask); + if ($gdimg_mask = $this->ImageCreateFromStringReplacement($MaskImageData)) { + $this->is_alpha = true; + $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output); + ImageDestroy($gdimg_mask); + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$mask_filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('Cannot open mask file "'.$mask_filename.'"', __FILE__, __LINE__); + } + break; + + case 'elip': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Elipse() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $this->is_alpha = true; + $phpthumbFilters->Elipse($this->gdimg_output); + break; + + case 'ric': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping RoundedImageCorners() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + @list($radius_x, $radius_y) = explode('|', $parameter); + if (($radius_x < 1) || ($radius_y < 1)) { + $this->DebugMessage('Skipping RoundedImageCorners('.$radius_x.', '.$radius_y.') because x/y radius is less than 1', __FILE__, __LINE__); + break; + } + $this->is_alpha = true; + $phpthumbFilters->RoundedImageCorners($this->gdimg_output, $radius_x, $radius_y); + break; + + case 'bord': + @list($border_width, $radius_x, $radius_y, $hexcolor_border) = explode('|', $parameter); + $this->is_alpha = true; + $phpthumbFilters->ImageBorder($this->gdimg_output, $border_width, $radius_x, $radius_y, $hexcolor_border); + break; + + case 'over': + @list($filename, $underlay, $margin, $opacity) = explode('|', $parameter); + $underlay = (bool) ($underlay ? $underlay : false); + $margin = ((strlen($margin) > 0) ? $margin : ($underlay ? 0.1 : 0.0)); + $opacity = ((strlen($opacity) > 0) ? $opacity : 100); + if (($margin > 0) && ($margin < 1)) { + $margin = min(0.499, $margin); + } elseif (($margin > -1) && ($margin < 0)) { + $margin = max(-0.499, $margin); + } + + $filename = $this->ResolveFilenameToAbsolute($filename); + if (@is_readable($filename) && ($fp_watermark = @fopen($filename, 'rb'))) { + $WatermarkImageData = fread($fp_watermark, filesize($filename)); + fclose($fp_watermark); + if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) { + if ($margin < 1) { + $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * (ImageSX($this->gdimg_output) * $margin))); + $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * (ImageSY($this->gdimg_output) * $margin))); + } else { + $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * $margin)); + $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * $margin)); + } + + if ($underlay) { + + if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { + ImageAlphaBlending($img_watermark_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark_resized, true); + $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); + if ($img_source_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { + ImageAlphaBlending($img_source_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_source_resized, true); + $this->ImageResizeFunction($img_source_resized, $this->gdimg_output, 0, 0, 0, 0, ImageSX($img_source_resized), ImageSY($img_source_resized), ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + $phpthumbFilters->WatermarkOverlay($img_watermark_resized, $img_source_resized, 'C', $opacity, $margin); + ImageCopy($this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); + } + ImageDestroy($img_watermark_resized); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); + } + + } else { // overlay + + if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { + ImageAlphaBlending($img_watermark_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark_resized, true); + $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark_resized, 'C', $opacity, $margin); + ImageDestroy($img_watermark_resized); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); + } + + } + ImageDestroy($img_watermark); + + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('Cannot open overlay file "'.$filename.'"', __FILE__, __LINE__); + } + break; + + case 'wmi': + @list($filename, $alignment, $opacity, $margin) = explode('|', $parameter); + $alignment = ($alignment ? $alignment : 'BR'); + $opacity = (strlen($opacity) ? $opacity : 50); + $margin = (strlen($margin) ? $margin : 5); + + $filename = $this->ResolveFilenameToAbsolute($filename); + if (@is_readable($filename)) { + if ($img_watermark = $this->ImageCreateFromFilename($filename, $rawImageData)) { + // great + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark, $alignment, $opacity, $margin); + ImageDestroy($img_watermark); + } else { + $this->DebugMessage('ImageCreateFromFilename() failed for "'.$filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('!is_readable('.$filename.')', __FILE__, __LINE__); + } + break; + + case 'wmt': + @list($text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend) = explode('|', $parameter); + $text = ($text ? $text : ''); + $size = ($size ? $size : 3); + $alignment = ($alignment ? $alignment : 'BR'); + $hex_color = ($hex_color ? $hex_color : '000000'); + $ttffont = ($ttffont ? $ttffont : ''); + $opacity = (strlen($opacity) ? $opacity : 50); + $margin = (strlen($margin) ? $margin : 5); + $angle = (strlen($angle) ? $angle : 0); + $bg_color = ($bg_color ? $bg_color : false); + $bg_opacity = ($bg_opacity ? $bg_opacity : 0); + $fillextend = ($fillextend ? $fillextend : ''); + + if (basename($ttffont) == $ttffont) { + $ttffont = realpath($this->config_ttf_directory.DIRECTORY_SEPARATOR.$ttffont); + } else { + $ttffont = $this->ResolveFilenameToAbsolute($ttffont); + } + $phpthumbFilters->WatermarkText($this->gdimg_output, $text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend); + break; + + case 'blur': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Blur() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $phpthumbFilters->Blur($this->gdimg_output, $radius); + break; + + case 'gblr': + $phpthumbFilters->BlurGaussian($this->gdimg_output); + break; + + case 'sblr': + $phpthumbFilters->BlurSelective($this->gdimg_output); + break; + + case 'mean': + $phpthumbFilters->MeanRemoval($this->gdimg_output); + break; + + case 'smth': + $phpthumbFilters->Smooth($this->gdimg_output, $parameter); + break; + + case 'usm': + @list($amount, $radius, $threshold) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + $radius = ($radius ? $radius : 0.5); + $threshold = (strlen($threshold) ? $threshold : 3); + if (phpthumb_functions::gd_version() >= 2.0) { + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.unsharp.php')) { + $include_error = ob_get_contents(); + if ($include_error) { + $this->DebugMessage('include_once("'.dirname(__FILE__).'/phpthumb.unsharp.php") generated message: "'.$include_error.'"', __FILE__, __LINE__); + } + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.unsharp.php" which is required for unsharp masking', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ob_end_clean(); + phpUnsharpMask::applyUnsharpMask($this->gdimg_output, $amount, $radius, $threshold); + } else { + $this->DebugMessage('Skipping unsharp mask because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + break; + } + } + } + return true; + } + + + function MaxFileSize() { + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping MaxFileSize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + if ($this->maxb > 0) { + switch ($this->thumbnailFormat) { + case 'png': + case 'gif': + $imgRenderFunction = 'image'.$this->thumbnailFormat; + + ob_start(); + $imgRenderFunction($this->gdimg_output); + $imgdata = ob_get_contents(); + ob_end_clean(); + + if (strlen($imgdata) > $this->maxb) { + for ($i = 8; $i >= 1; $i--) { + $tempIMG = ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + ImageCopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + ImageTrueColorToPalette($tempIMG, true, pow(2, $i)); + ob_start(); + $imgRenderFunction($tempIMG); + $imgdata = ob_get_contents(); + ob_end_clean(); + + if (strlen($imgdata) <= $this->maxb) { + ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); + break; + } + } + } + if (strlen($imgdata) > $this->maxb) { + ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); + return false; + } + break; + + case 'jpeg': + ob_start(); + ImageJPEG($this->gdimg_output); + $imgdata = ob_get_contents(); + ob_end_clean(); + + $OriginalJPEGquality = $this->thumbnailQuality; + if (strlen($imgdata) > $this->maxb) { + for ($i = 3; $i < 20; $i++) { + $q = round(100 * (1 - log10($i / 2))); + ob_start(); + ImageJPEG($this->gdimg_output, '', $q); + $imgdata = ob_get_contents(); + ob_end_clean(); + + $this->thumbnailQuality = $q; + if (strlen($imgdata) <= $this->maxb) { + break; + } + } + } + if (strlen($imgdata) > $this->maxb) { + return false; + } + break; + + default: + return false; + break; + } + } + return true; + } + + + function CalculateThumbnailDimensions() { + $this->thumbnailCropX = ($this->sx ? (($this->sx >= 1) ? $this->sx : round($this->sx * $this->source_width)) : 0); + $this->thumbnailCropY = ($this->sy ? (($this->sy >= 1) ? $this->sy : round($this->sy * $this->source_height)) : 0); + $this->thumbnailCropW = ($this->sw ? (($this->sw >= 1) ? $this->sw : round($this->sw * $this->source_width)) : $this->source_width); + $this->thumbnailCropH = ($this->sh ? (($this->sh >= 1) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height); + + // limit source area to original image area + $this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width - $this->thumbnailCropX)); + $this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY)); + + $this->DebugMessage('CalculateThumbnailDimensions() [x,y,w,h] initially set to ['.$this->thumbnailCropX.','.$this->thumbnailCropY.','.$this->thumbnailCropW.','.$this->thumbnailCropH.']', __FILE__, __LINE__); + + + if ($this->zc && $this->w && $this->h) { + // Zoom Crop + // retain proportional resizing we did above, but crop off larger dimension so smaller + // dimension fully fits available space + + $scaling_X = $this->source_width / $this->w; + $scaling_Y = $this->source_height / $this->h; + if ($scaling_X > $scaling_Y) { + // some of the width will need to be cropped + $allowable_width = $this->source_width / $scaling_X * $scaling_Y; + $this->thumbnailCropW = round($allowable_width); + $this->thumbnailCropX = round(($this->source_width - $allowable_width) / 2); + + } elseif ($scaling_Y > $scaling_X) { + // some of the height will need to be cropped + $allowable_height = $this->source_height / $scaling_Y * $scaling_X; + $this->thumbnailCropH = round($allowable_height); + $this->thumbnailCropY = round(($this->source_height - $allowable_height) / 2); + + } else { + // image fits perfectly, no cropping needed + } + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = $this->thumbnail_height; + + } elseif ($this->iar && $this->w && $this->h) { + + // Ignore Aspect Ratio + // stretch image to fit exactly 'w' x 'h' + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = $this->thumbnail_height; + + } else { + + $original_aspect_ratio = $this->thumbnailCropW / $this->thumbnailCropH; + if ($this->aoe) { + $maxwidth = max($this->w, $this->thumbnailCropW); + $maxheight = max($this->h, $this->thumbnailCropH); + $maxwidth = max($maxwidth, $maxheight * $original_aspect_ratio); + $maxheight = max($maxheight, $maxwidth / $original_aspect_ratio); + } else { + $maxwidth = phpthumb_functions::nonempty_min($this->w, $this->thumbnailCropW, $this->config_output_maxwidth); + $maxheight = phpthumb_functions::nonempty_min($this->h, $this->thumbnailCropH, $this->config_output_maxheight); + $maxwidth = min($maxwidth, $maxheight * $original_aspect_ratio); + $maxheight = min($maxheight, $maxwidth / $original_aspect_ratio); + } + + $this->thumbnail_image_width = $maxwidth; + $this->thumbnail_image_height = $maxheight; + $this->thumbnail_width = $maxwidth; + $this->thumbnail_height = $maxheight; + + $this->FixedAspectRatio(); + } + + $this->thumbnail_width = max(1, floor($this->thumbnail_width)); + $this->thumbnail_height = max(1, floor($this->thumbnail_height)); + return true; + } + + + function CreateGDoutput() { + + $this->CalculateThumbnailDimensions(); + + // Create the GD image (either true-color or 256-color, depending on GD version) + $this->gdimg_output = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height); + + // Images that have transparency must have the background filled with the configured 'bg' color + // otherwise the transparent color will appear as black + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_output, true); + if ($this->is_alpha && phpthumb_functions::gd_version() >= 2) { + + ImageAlphaBlending($this->gdimg_output, false); + $output_full_alpha = phpthumb_functions::ImageColorAllocateAlphaSafe($this->gdimg_output, 255, 255, 255, 127); + ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha); + + } else { + + $current_transparent_color = ImageColorTransparent($this->gdimg_source); + if ($this->bg || (@$current_transparent_color >= 0)) { + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); + ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); + + } + + } + return true; + } + + function SetOrientationDependantWidthHeight() { + $this->DebugMessage('SetOrientationDependantWidthHeight() starting with "'.$this->source_width.'"x"'.$this->source_height.'"', __FILE__, __LINE__); + if ($this->source_height > $this->source_width) { + // portrait + $this->w = phpthumb_functions::OneOfThese($this->wp, $this->w, $this->ws, $this->wl); + $this->h = phpthumb_functions::OneOfThese($this->hp, $this->h, $this->hs, $this->hl); + } elseif ($this->source_height < $this->source_width) { + // landscape + $this->w = phpthumb_functions::OneOfThese($this->wl, $this->w, $this->ws, $this->wp); + $this->h = phpthumb_functions::OneOfThese($this->hl, $this->h, $this->hs, $this->hp); + } else { + // square + $this->w = phpthumb_functions::OneOfThese($this->ws, $this->w, $this->wl, $this->wp); + $this->h = phpthumb_functions::OneOfThese($this->hs, $this->h, $this->hl, $this->hp); + } + //$this->w = round($this->w ? $this->w : (($this->h && $this->source_height) ? $this->h * $this->source_width / $this->source_height : $this->w)); + //$this->h = round($this->h ? $this->h : (($this->w && $this->source_width) ? $this->w * $this->source_height / $this->source_width : $this->h)); + $this->DebugMessage('SetOrientationDependantWidthHeight() setting w="'.intval($this->w).'", h="'.intval($this->h).'"', __FILE__, __LINE__); + return true; + } + + function ExtractEXIFgetImageSize() { + $this->DebugMessage('starting ExtractEXIFgetImageSize()', __FILE__, __LINE__); + + if (is_resource($this->gdimg_source)) { + + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + $this->SetOrientationDependantWidthHeight(); + + } elseif ($this->rawImageData && !$this->sourceFilename) { + + $this->DebugMessage('bypassing EXIF and GetImageSize sections because $this->rawImageData is set and $this->sourceFilename is not set', __FILE__, __LINE__); + + } + + if (is_null($this->getimagesizeinfo)) { + $this->getimagesizeinfo = @GetImageSize($this->sourceFilename); + } + + if (!empty($this->getimagesizeinfo)) { + // great + $this->getimagesizeinfo['filesize'] = @filesize($this->sourceFilename); + } elseif (!$this->rawImageData) { + $this->DebugMessage('GetImageSize("'.$this->sourceFilename.'") failed', __FILE__, __LINE__); + } + + if ($this->config_prefer_imagemagick) { + if ($this->ImageMagickThumbnailToGD()) { + return true; + } + $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); + } + + $this->source_width = $this->getimagesizeinfo[0]; + $this->source_height = $this->getimagesizeinfo[1]; + + $this->SetOrientationDependantWidthHeight(); + + if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == 2)) { + // Extract EXIF info from JPEGs + + $this->exif_thumbnail_width = ''; + $this->exif_thumbnail_height = ''; + $this->exif_thumbnail_type = ''; + + // The parameters width, height and imagetype are available since PHP v4.3.0 + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + + $this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type); + + } else { + + // older versions of exif_thumbnail output an error message but NOT return false on failure + ob_start(); + $this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename); + $exit_thumbnail_error = ob_get_contents(); + ob_end_clean(); + if (!$exit_thumbnail_error && $this->exif_thumbnail_data) { + + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + $this->exif_thumbnail_width = ImageSX($gdimg_exif_temp); + $this->exif_thumbnail_height = ImageSY($gdimg_exif_temp); + $this->exif_thumbnail_type = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned + unset($gdimg_exif_temp); + } else { + return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in '.__FILE__.' on line '.__LINE__); + } + + } + + } + + } elseif (!function_exists('exif_thumbnail')) { + + $this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__); + return false; + + } + + $this->DebugMessage('EXIF thumbnail extraction: (size='.strlen($this->exif_thumbnail_data).'; type="'.$this->exif_thumbnail_type.'"; '.intval($this->exif_thumbnail_width).'x'.intval($this->exif_thumbnail_height).')', __FILE__, __LINE__); + + // see if EXIF thumbnail can be used directly with no processing + if ($this->config_use_exif_thumbnail_for_speed && $this->exif_thumbnail_data) { + while (true) { + if (!$this->xto) { + $source_ar = $this->source_width / $this->source_height; + $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; + if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { + $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); + break; + } + if ($this->w && ($this->w != $this->exif_thumbnail_width)) { + $this->DebugMessage('not using EXIF thumbnail because $this->w != $this->exif_thumbnail_width ('.$this->w.' != '.$this->exif_thumbnail_width.')', __FILE__, __LINE__); + break; + } + if ($this->h && ($this->h != $this->exif_thumbnail_height)) { + $this->DebugMessage('not using EXIF thumbnail because $this->h != $this->exif_thumbnail_height ('.$this->h.' != '.$this->exif_thumbnail_height.')', __FILE__, __LINE__); + break; + } + $CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'far', 'bg', 'bc', 'fltr', 'phpThumbDebug'); + foreach ($CannotBeSetParameters as $dummy => $parameter) { + if ($this->$parameter) { + break 2; + } + } + } + + $this->DebugMessage('setting $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data)', __FILE__, __LINE__); + $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + return true; + } + } + + if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) { + + // Source image is larger than would fit in available PHP memory. + // If ImageMagick is installed, use it to generate the thumbnail. + // Else, if an EXIF thumbnail is available, use that as the source image. + // Otherwise, no choice but to fail with an error message + $this->DebugMessage('image is '.$this->source_width.'x'.$this->source_height.' and therefore contains more pixels ('.($this->source_width * $this->source_height).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); + if (!$this->config_prefer_imagemagick && $this->ImageMagickThumbnailToGD()) { + // excellent, we have a thumbnailed source image + return true; + } + + } + return true; + } + + + function SetCacheFilename() { + if (!is_null($this->cache_filename)) { + $this->DebugMessage('$this->cache_filename already set, skipping SetCacheFilename()', __FILE__, __LINE__); + return true; + } + $this->setOutputFormat(); + $this->setCacheDirectory(); + if (!$this->config_cache_directory) { + $this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__); + return false; + } + + if (!$this->sourceFilename && !$this->rawImageData && $this->src) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); + } + + if ($this->config_cache_default_only_suffix && $this->sourceFilename) { + // simplified cache filenames: + // only use default parameters in phpThumb.config.php + // substitute source filename into * in $this->config_cache_default_only_suffix + // (eg: '*_thumb' becomes 'picture_thumb.jpg') + if (strpos($this->config_cache_default_only_suffix, '*') === false) { + $this->DebugMessage('aborting simplified caching filename because no * in "'.$this->config_cache_default_only_suffix.'"', __FILE__, __LINE__); + } else { + preg_match('/(.+)(\.[a-z0-9]+)?$/iU', basename($this->sourceFilename), $matches); + $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.str_replace('*', $matches[1], $this->config_cache_default_only_suffix).'.'.strtolower($this->thumbnailFormat); + return true; + } + } + + $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.$this->config_cache_prefix; + if ($this->new) { + $this->cache_filename .= '_new'.strtolower(md5($this->new)); + } elseif ($this->md5s) { + // source image MD5 hash provided + $this->DebugMessage('SetCacheFilename() _raw set from $this->md5s = "'.$this->md5s.'"', __FILE__, __LINE__); + $this->cache_filename .= '_raw'.$this->md5s; + } elseif (!$this->src && $this->rawImageData) { + $this->DebugMessage('SetCacheFilename() _raw set from md5($this->rawImageData) = "'.md5($this->rawImageData).'"', __FILE__, __LINE__); + $this->cache_filename .= '_raw'.strtolower(md5($this->rawImageData)); + } else { + $this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "'.$this->sourceFilename.'" = "'.md5($this->sourceFilename).'"', __FILE__, __LINE__); + $this->cache_filename .= '_src'.strtolower(md5($this->sourceFilename)); + } + if (@$_SERVER['HTTP_REFERER'] && $this->config_nooffsitelink_enabled) { + $parsed_url1 = @parse_url(@$_SERVER['HTTP_REFERER']); + $parsed_url2 = @parse_url('http://'.@$_SERVER['HTTP_HOST']); + if (@$parsed_url1['host'] && @$parsed_url2['host'] && ($parsed_url1['host'] != $parsed_url2['host'])) { + // include "_offsite" only if nooffsitelink_enabled and if referrer doesn't match the domain of the current server + $this->cache_filename .= '_offsite'; + } + } + + $ParametersString = ''; + if ($this->fltr && is_array($this->fltr)) { + $ParametersString .= '_fltr'.implode('_fltr', $this->fltr); + } + $FilenameParameters1 = array('ar', 'bg', 'bc', 'far'); + foreach ($FilenameParameters1 as $dummy => $key) { + if ($this->$key) { + $ParametersString .= '_'.$key.$this->$key; + } + } + $FilenameParameters2 = array('h', 'w', 'wl', 'wp', 'ws', 'hp', 'hs', 'sx', 'sy', 'sw', 'sh', 'xto', 'ra', 'iar', 'aoe', 'maxb'); + foreach ($FilenameParameters2 as $dummy => $key) { + if ($this->$key) { + $ParametersString .= '_'.$key.intval($this->$key); + } + } + if ($this->thumbnailFormat == 'jpeg') { + // only JPEG output has variable quality option + $ParametersString .= '_q'.intval($this->thumbnailQuality); + } + $this->DebugMessage('SetCacheFilename() _par set from md5('.$ParametersString.')', __FILE__, __LINE__); + $this->cache_filename .= '_par'.strtolower(md5($ParametersString)); + + if ($this->md5s) { + // source image MD5 hash provided + // do not source image modification date -- + // cached image will be used even if file was modified or removed + } elseif (!$this->config_cache_source_filemtime_ignore_remote && eregi('^(f|ht)tps?://', $this->src)) { + $this->cache_filename .= '_dat'.intval(phpthumb_functions::filedate_remote($this->src)); + } elseif (!$this->config_cache_source_filemtime_ignore_local && $this->src && !$this->rawImageData) { + $this->cache_filename .= '_dat'.intval(@filemtime($this->sourceFilename)); + } + + $this->cache_filename .= '.'.strtolower($this->thumbnailFormat); + + return true; + } + + + function ImageCreateFromFilename($filename, &$rawimagedata) { + // try to create GD image source directly via GD, if possible, + // rather than buffering to memory and creating with ImageCreateFromString + $ImageCreateWasAttempted = false; + $gd_image = false; + + $this->DebugMessage('starting ImageCreateFromFilename('.$filename.', ['.strlen($rawimagedata).' bytes])', __FILE__, __LINE__); + + if ($filename && ($getimagesizeinfo = @GetImageSize($filename))) { + if (($this->config_max_source_pixels > 0) && (($getimagesizeinfo[0] * $getimagesizeinfo[1]) > $this->config_max_source_pixels)) { + $ImageCreateFromFunction = array( + 1 => 'ImageCreateFromGIF', + 2 => 'ImageCreateFromJPEG', + 3 => 'ImageCreateFromPNG', + 15 => 'ImageCreateFromWBMP', + ); + $this->DebugMessage('ImageCreateFromFilename found ($getimagesizeinfo[2]=='.@$getimagesizeinfo[2].')', __FILE__, __LINE__); + switch (@$getimagesizeinfo[2]) { + case 1: // GIF + case 2: // JPEG + case 3: // PNG + case 15: // WBMP + $ImageCreateFromFunctionName = $ImageCreateFromFunction[$getimagesizeinfo[2]]; + if (function_exists($ImageCreateFromFunctionName)) { + $this->DebugMessage('Calling '.$ImageCreateFromFunctionName.'('.$filename.')', __FILE__, __LINE__); + $ImageCreateWasAttempted = true; + $gd_image = @$ImageCreateFromFunctionName($filename); + } else { + $this->DebugMessage('NOT calling '.$ImageCreateFromFunctionName.'('.$filename.') because !function_exists('.$ImageCreateFromFunctionName.')', __FILE__, __LINE__); + } + break; + + case 4: // SWF + case 5: // PSD + case 6: // BMP + case 7: // TIFF (LE) + case 8: // TIFF (BE) + case 9: // JPC + case 10: // JP2 + case 11: // JPX + case 12: // JB2 + case 13: // SWC + case 14: // IFF + case 16: // XBM + $this->DebugMessage('No built-in image creation function for image type "'.@$getimagesizeinfo[2].'" ($getimagesizeinfo[2])', __FILE__, __LINE__); + break; + + default: + $this->DebugMessage('Unknown value for $getimagesizeinfo[2]: "'.@$getimagesizeinfo[2].'"', __FILE__, __LINE__); + break; + } + } else { + $this->DebugMessage('image is '.$getimagesizeinfo[0].'x'.$getimagesizeinfo[1].' and therefore contains more pixels ('.($getimagesizeinfo[0] * $getimagesizeinfo[1]).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('empty $filename or GetImageSize('.$filename.') failed', __FILE__, __LINE__); + } + + if (!$gd_image) { + // cannot create from filename, attempt to create source image with ImageCreateFromString, if possible + if ($ImageCreateWasAttempted) { + $this->DebugMessage(@$ImageCreateFromFunctionName.'() was attempted but FAILED', __FILE__, __LINE__); + } + if (!$rawimagedata) { + $this->DebugMessage('Populating $rawimagedata', __FILE__, __LINE__); + if ($fp = @fopen($filename, 'rb')) { + + $rawimagedata = ''; + $filesize = filesize($filename); + $blocksize = 32768; + $blockreads = ceil($filesize / $blocksize); + for ($i = 0; $i < $blockreads; $i++) { + $rawimagedata .= fread($fp, $blocksize); + } + fclose($fp); + + } else { + $this->DebugMessage('cannot fopen('.$filename.')', __FILE__, __LINE__); + } + } + if ($rawimagedata) { + $this->DebugMessage('attempting ImageCreateFromStringReplacement($rawimagedata ('.strlen($rawimagedata).' bytes), true)', __FILE__, __LINE__); + $gd_image = $this->ImageCreateFromStringReplacement($rawimagedata, true); + } + } + return $gd_image; + } + + function SourceImageToGD() { + if (is_resource($this->gdimg_source)) { + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $this->DebugMessage('skipping SourceImageToGD() because $this->gdimg_source is already a resource ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); + return true; + } + $this->DebugMessage('starting SourceImageToGD()', __FILE__, __LINE__); + while (true) { + if (!$this->config_use_exif_thumbnail_for_speed) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__); + break; + } + if (!$this->exif_thumbnail_data) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty', __FILE__, __LINE__); + break; + } + if (($this->thumbnailCropX != 0) || ($this->thumbnailCropY != 0)) { + $this->DebugMessage('Not using EXIF thumbnail data because source cropping is enabled ('.$this->thumbnailCropX.','.$this->thumbnailCropY.')', __FILE__, __LINE__); + break; + } + if (($this->w > $this->exif_thumbnail_width) || ($this->h > $this->exif_thumbnail_height)) { + $this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small ('.$this->exif_thumbnail_width.'x'.$this->exif_thumbnail_height.' vs '.$this->w.'x'.$this->h.')', __FILE__, __LINE__); + break; + } + $source_ar = $this->source_width / $this->source_height; + $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; + if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { + $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); + } + + // EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image + $this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__); + + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + + $this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__); + $this->gdimg_source = $gdimg_exif_temp; + $this->source_width = $this->exif_thumbnail_width; + $this->source_height = $this->exif_thumbnail_height; + $this->thumbnailCropW = $this->source_width; + $this->thumbnailCropH = $this->source_height; + return true; + + } else { + $this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__); + } + + break; + } + if (!$this->gdimg_source) { + + if ($this->md5s && ($this->md5s != phpthumb_functions::md5_file_safe($this->sourceFilename))) { + return $this->ErrorImage('$this->md5s != md5($rawimagedata)'."\n".'"'.$this->md5s.'" != '."\n".'"'.phpthumb_functions::md5_file_safe($this->sourceFilename).'"'); + } + switch (@$this->getimagesizeinfo[2]) { + case 1: + case 3: + // GIF or PNG input file may have transparency + $this->is_alpha = true; + break; + } + + $this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename, $this->rawImageData); + + if ($this->md5s && ($this->md5s != md5($this->rawImageData))) { + return $this->ErrorImage('$this->md5s != md5($this->rawImageData)'."\n".'"'.$this->md5s.'" != '."\n".'"'.md5($this->rawImageData).'"'); + } + + if (!$this->gdimg_source) { + $this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__); + + if ($this->ImageMagickThumbnailToGD()) { + + // excellent, we have a thumbnailed source image + $this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__); + + } else { + + $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); + + $imageHeader = ''; + $gd_info = gd_info(); + $GDreadSupport = false; + switch (substr($this->rawImageData, 0, 3)) { + case 'GIF': + $imageHeader = 'Content-Type: image/gif'; + $GDreadSupport = (bool) @$gd_info['GIF Read Support']; + break; + case "\xFF\xD8\xFF": + $imageHeader = 'Content-Type: image/jpeg'; + $GDreadSupport = (bool) @$gd_info['JPG Support']; + break; + case "\x89".'PN': + $imageHeader = 'Content-Type: image/png'; + $GDreadSupport = (bool) @$gd_info['PNG Support']; + break; + } + if ($imageHeader) { + // cannot create image for whatever reason (maybe ImageCreateFromJPEG et al are not available?) + // and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit + if ($this->config_error_die_on_source_failure) { + $this->ErrorImage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), cannot generate thumbnail'); + } else { + //$this->DebugMessage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), outputing raw image', __FILE__, __LINE__); + //if (!$this->phpThumbDebug) { + // header($imageHeader); + // echo $this->rawImageData; + // exit; + //} + return false; + } + } + + switch (substr($this->rawImageData, 0, 2)) { + case 'BM': + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + ob_end_clean(); + return $this->ErrorImage('include_once('.dirname(__FILE__).'/phpthumb.bmp.php) failed'); + } + ob_end_clean(); + $phpthumb_bmp = new phpthumb_bmp(); + if ($this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, (phpthumb_functions::gd_version() >= 2.0))) { + $this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__); + break; + } + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on BMP source conversion' : 'phpthumb_bmp2gd() failed'); + break; + } + + + switch (substr($this->rawImageData, 0, 4)) { + case 'II'."\x2A\x00": + case 'MM'."\x00\x2A": + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on TIFF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support TIFF source images without it'); + break; + + case "\xD7\xCD\xC6\x9A": + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); + break; + } + + if (!$this->gdimg_source) { + return $this->ErrorImage('Unknown image type identified by "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()'); + } + + } + } + } + if (!$this->gdimg_source) { + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + $this->DebugMessage('All other attempts failed, but successfully using EXIF thumbnail as source image', __FILE__, __LINE__); + $this->gdimg_source = $gdimg_exif_temp; + // override allow-enlarging setting if EXIF thumbnail is the only source available + // otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size + $this->aoe = true; + return true; + } + return false; + } + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + return true; + } + + + function phpThumbDebugVarDump($var) { + if (is_null($var)) { + return 'NULL'; + } elseif (is_bool($var)) { + return ($var ? 'TRUE' : 'FALSE'); + } elseif (is_string($var)) { + return 'string('.strlen($var).')'.str_repeat(' ', max(0, 3 - strlen(strlen($var)))).' "'.$var.'"'; + } elseif (is_int($var)) { + return 'integer '.$var; + } elseif (is_float($var)) { + return 'float '.$var; + } elseif (is_array($var)) { + ob_start(); + var_dump($var); + $vardumpoutput = ob_get_contents(); + ob_end_clean(); + return strtr($vardumpoutput, "\n\r\t", ' '); + } + return gettype($var); + } + + function phpThumbDebug() { + if ($this->config_disable_debug) { + return $this->ErrorImage('phpThumbDebug disabled'); + } + + $FunctionsExistance = array('exif_thumbnail', 'gd_info', 'image_type_to_mime_type', 'ImageCopyResampled', 'ImageCopyResized', 'ImageCreate', 'ImageCreateFromString', 'ImageCreateTrueColor', 'ImageIsTrueColor', 'ImageRotate', 'ImageTypes', 'version_compare', 'ImageCreateFromGIF', 'ImageCreateFromJPEG', 'ImageCreateFromPNG', 'ImageCreateFromWBMP', 'ImageCreateFromXBM', 'ImageCreateFromXPM', 'ImageCreateFromString', 'ImageCreateFromGD', 'ImageCreateFromGD2', 'ImageCreateFromGD2Part', 'ImageJPEG', 'ImageGIF', 'ImagePNG', 'ImageWBMP'); + $ParameterNames = array('src', 'new', 'w', 'h', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'far', 'bg', 'bc', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'iar', 'maxb'); + $ConfigVariableNames = array('document_root', 'temp_directory', 'output_format', 'output_maxwidth', 'output_maxheight', 'error_message_image_default', 'error_bgcolor', 'error_textcolor', 'error_fontsize', 'error_die_on_error', 'error_silent_die_on_error', 'error_die_on_source_failure', 'nohotlink_enabled', 'nohotlink_valid_domains', 'nohotlink_erase_image', 'nohotlink_text_message', 'nooffsitelink_enabled', 'nooffsitelink_valid_domains', 'nooffsitelink_require_refer', 'nooffsitelink_erase_image', 'nooffsitelink_text_message', 'high_security_enabled', 'allow_src_above_docroot', 'allow_src_above_phpthumb', 'allow_parameter_file', 'allow_parameter_goto', 'max_source_pixels', 'use_exif_thumbnail_for_speed', 'border_hexcolor', 'background_hexcolor', 'ttf_directory', 'disable_pathinfo_parsing', 'disable_imagecopyresampled'); + $OtherVariableNames = array('phpThumbDebug', 'thumbnailQuality', 'thumbnailFormat', 'gdimg_output', 'gdimg_source', 'sourceFilename', 'source_width', 'source_height', 'thumbnailCropX', 'thumbnailCropY', 'thumbnailCropW', 'thumbnailCropH', 'exif_thumbnail_width', 'exif_thumbnail_height', 'exif_thumbnail_type', 'thumbnail_width', 'thumbnail_height', 'thumbnail_image_width', 'thumbnail_image_height'); + + $DebugOutput = array(); + $DebugOutput[] = 'phpThumb() version = '.$this->phpthumb_version; + $DebugOutput[] = 'phpversion() = '.@phpversion(); + $DebugOutput[] = 'PHP_OS = '.PHP_OS; + $DebugOutput[] = '__FILE__ = '.__FILE__; + $DebugOutput[] = 'realpath(.) = '.@realpath('.'); + $DebugOutput[] = '$_SERVER[PHP_SELF] = '.@$_SERVER['PHP_SELF']; + $DebugOutput[] = '$_SERVER[HTTP_REFERER] = '.@$_SERVER['HTTP_REFERER']; + $DebugOutput[] = '$_SERVER[QUERY_STRING] = '.@$_SERVER['QUERY_STRING']; + $DebugOutput[] = '$_SERVER[PATH_INFO] = '.@$_SERVER['PATH_INFO']; + $DebugOutput[] = '$_SERVER[DOCUMENT_ROOT] = '.@$_SERVER['DOCUMENT_ROOT']; + $DebugOutput[] = 'getenv(DOCUMENT_ROOT) = '.@getenv('DOCUMENT_ROOT'); + $DebugOutput[] = ''; + + $DebugOutput[] = 'get_magic_quotes_gpc() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_gpc()); + $DebugOutput[] = 'get_magic_quotes_runtime() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_runtime()); + $DebugOutput[] = 'error_reporting() = '.$this->phpThumbDebugVarDump(error_reporting()); + $DebugOutput[] = 'ini_get(error_reporting) = '.$this->phpThumbDebugVarDump(@ini_get('error_reporting')); + $DebugOutput[] = 'ini_get(display_errors) = '.$this->phpThumbDebugVarDump(@ini_get('display_errors')); + $DebugOutput[] = 'ini_get(allow_url_fopen) = '.$this->phpThumbDebugVarDump(@ini_get('allow_url_fopen')); + $DebugOutput[] = 'ini_get(disable_functions) = '.$this->phpThumbDebugVarDump(@ini_get('disable_functions')); + $DebugOutput[] = 'ini_get(safe_mode) = '.$this->phpThumbDebugVarDump(@ini_get('safe_mode')); + $DebugOutput[] = 'ini_get(open_basedir) = '.$this->phpThumbDebugVarDump(@ini_get('open_basedir')); + $DebugOutput[] = 'ini_get(memory_limit) = '.$this->phpThumbDebugVarDump(@ini_get('memory_limit')); + $DebugOutput[] = 'ini_get(max_execution_time) = '.$this->phpThumbDebugVarDump(@ini_get('max_execution_time')); + $DebugOutput[] = 'get_cfg_var(memory_limit) = '.$this->phpThumbDebugVarDump(@get_cfg_var('memory_limit')); + $DebugOutput[] = 'memory_get_usage() = '.(function_exists('memory_get_usage') ? $this->phpThumbDebugVarDump(@memory_get_usage()) : 'n/a'); + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->config_prefer_imagemagick = '.$this->phpThumbDebugVarDump($this->config_prefer_imagemagick); + $DebugOutput[] = '$this->config_imagemagick_path = '.$this->phpThumbDebugVarDump($this->config_imagemagick_path); + $DebugOutput[] = '$this->ImageMagickWhichConvert() = '.$this->ImageMagickWhichConvert(); + $IMpathUsed = ($this->config_imagemagick_path ? $this->config_imagemagick_path : $this->ImageMagickWhichConvert()); + $DebugOutput[] = '[actual ImageMagick path used] = '.$this->phpThumbDebugVarDump($IMpathUsed); + $DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(@file_exists($IMpathUsed)); + $DebugOutput[] = 'ImageMagickVersion() = '.$this->ImageMagickVersion(); + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->config_cache_directory = '.$this->phpThumbDebugVarDump($this->config_cache_directory); + $DebugOutput[] = '$this->config_cache_disable_warning = '.$this->phpThumbDebugVarDump($this->config_cache_disable_warning); + $DebugOutput[] = '$this->config_cache_maxage = '.$this->phpThumbDebugVarDump($this->config_cache_maxage); + $DebugOutput[] = '$this->config_cache_maxsize = '.$this->phpThumbDebugVarDump($this->config_cache_maxsize); + $DebugOutput[] = '$this->config_cache_maxfiles = '.$this->phpThumbDebugVarDump($this->config_cache_maxfiles); + $DebugOutput[] = '$this->config_cache_force_passthru = '.$this->phpThumbDebugVarDump($this->config_cache_force_passthru); + $DebugOutput[] = '$this->cache_filename = '.$this->phpThumbDebugVarDump($this->cache_filename); + $DebugOutput[] = 'is_readable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(is_readable($this->config_cache_directory)); + $DebugOutput[] = 'is_writable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(is_writable($this->config_cache_directory)); + $DebugOutput[] = 'is_readable($this->cache_filename) = '.$this->phpThumbDebugVarDump(is_readable($this->cache_filename)); + $DebugOutput[] = 'is_writable($this->cache_filename) = '.(file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(is_writable($this->cache_filename)) : 'n/a'); + $DebugOutput[] = ''; + + foreach ($ConfigVariableNames as $dummy => $varname) { + $varname = 'config_'.$varname; + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 37, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + foreach ($OtherVariableNames as $dummy => $varname) { + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 27, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = 'strlen($this->rawImageData) = '.strlen(@$this->rawImageData); + $DebugOutput[] = 'strlen($this->exif_thumbnail_data) = '.strlen(@$this->exif_thumbnail_data); + $DebugOutput[] = ''; + + foreach ($ParameterNames as $dummy => $varname) { + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 4, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + foreach ($FunctionsExistance as $dummy => $functionname) { + $DebugOutput[] = 'builtin_function_exists('.$functionname.')'.str_repeat(' ', 23 - strlen($functionname)).' = '.$this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname)); + } + $DebugOutput[] = ''; + + $gd_info = gd_info(); + foreach ($gd_info as $key => $value) { + $DebugOutput[] = 'gd_info.'.str_pad($key, 34, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + $exif_info = phpthumb_functions::exif_info(); + foreach ($exif_info as $key => $value) { + $DebugOutput[] = 'exif_info.'.str_pad($key, 26, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { + foreach ($ApacheLookupURIarray as $key => $value) { + $DebugOutput[] = 'ApacheLookupURIarray.'.str_pad($key, 15, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + } else { + $DebugOutput[] = 'ApacheLookupURIarray() -- FAILED'; + } + $DebugOutput[] = ''; + + if (isset($_GET) && is_array($_GET)) { + foreach ($_GET as $key => $value) { + $DebugOutput[] = '$_GET['.$key.']'.str_repeat(' ', 30 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); + } + } + if (isset($_POST) && is_array($_POST)) { + foreach ($_POST as $key => $value) { + $DebugOutput[] = '$_POST['.$key.']'.str_repeat(' ', 29 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); + } + } + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->debugmessages:'; + foreach ($this->debugmessages as $dummy => $errorstring) { + $DebugOutput[] = ' * '.$errorstring; + } + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->debugtiming:'; + foreach ($this->debugtiming as $timestamp => $timingstring) { + $DebugOutput[] = ' * '.$timestamp.' '.$timingstring; + } + $DebugOutput[] = ' * Total processing time: '.number_format(max(array_keys($this->debugtiming)) - min(array_keys($this->debugtiming)), 6); + + return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500, true); + } + + function ErrorImage($text, $width=0, $height=0, $forcedisplay=false) { + $width = ($width ? $width : $this->config_error_image_width); + $height = ($height ? $height : $this->config_error_image_height); + + $text = 'phpThumb() v'.$this->phpthumb_version."\n\n".$text; + if ($this->config_disable_debug) { + $text = 'Error messages disabled'; + } + + $this->DebugMessage($text, __FILE__, __LINE__); + if ($this->phpThumbDebug && !$forcedisplay) { + return false; + } + if (!$this->config_error_die_on_error && !$forcedisplay) { + $this->fatalerror = $text; + return false; + } + if ($this->config_error_silent_die_on_error) { + exit; + } + if ($this->err || $this->config_error_message_image_default) { + // Show generic custom error image instead of error message + // for use on production sites where you don't want debug messages + if ($this->err == 'showerror') { + // fall through and actually show error message even if default error image is set + } else { + header('Location: '.($this->err ? $this->err : $this->config_error_message_image_default)); + exit; + } + } + if (!$this->thumbnailFormat || (phpthumb_functions::gd_version() < 1)) { + $this->thumbnailFormat = 'text'; + } + if (@$this->thumbnailFormat == 'text') { + // bypass all GD functions and output text error message + die('
    '.$text.'
    '); + } + + $FontWidth = ImageFontWidth($this->config_error_fontsize); + $FontHeight = ImageFontHeight($this->config_error_fontsize); + + $LinesOfText = explode("\n", @wordwrap($text, floor($width / $FontWidth), "\n", true)); + $height = max($height, count($LinesOfText) * $FontHeight); + + $headers_file = ''; + $headers_line = ''; + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=') && headers_sent($headers_file, $headers_line)) { + + echo "\n".'**Headers already sent in file "'.$headers_file.'" on line "'.$headers_line.'", dumping error message as text:**
    '."\n\n".$text."\n".'
    '; + + } elseif (headers_sent()) { + + echo "\n".'**Headers already sent, dumping error message as text:**
    '."\n\n".$text."\n".'
    '; + + } elseif ($gdimg_error = ImageCreate($width, $height)) { + + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor, true); + $text_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true); + ImageFilledRectangle($gdimg_error, 0, 0, $width, $height, $background_color); + $lineYoffset = 0; + foreach ($LinesOfText as $dummy => $line) { + ImageString($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color); + $lineYoffset += $FontHeight; + } + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_PNG) { + header('Content-Type: image/png'); + ImagePNG($gdimg_error); + } elseif ($imagetypes & IMG_GIF) { + header('Content-Type: image/gif'); + ImageGIF($gdimg_error); + } elseif ($imagetypes & IMG_JPG) { + header('Content-Type: image/jpeg'); + ImageJPEG($gdimg_error); + } elseif ($imagetypes & IMG_WBMP) { + header('Content-Type: image/wbmp'); + ImageWBMP($gdimg_error); + } + } + ImageDestroy($gdimg_error); + + } + if (!headers_sent()) { + echo "\n".'**Failed to send graphical error image, dumping error message as text:**
    '."\n\n".$text; + } + exit; + return true; + } + + function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors=false) { + // there are serious bugs in the non-bundled versions of GD which may cause + // PHP to segfault when calling ImageCreateFromString() - avoid if at all possible + // when not using a bundled version of GD2 + if (phpthumb_functions::gd_is_bundled()) { + return @ImageCreateFromString($RawImageData); + } + if (ini_get('safe_mode')) { + $this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__); + return false; + } + + switch (substr($RawImageData, 0, 3)) { + case 'GIF': + $ICFSreplacementFunctionName = 'ImageCreateFromGIF'; + break; + case "\xFF\xD8\xFF": + $ICFSreplacementFunctionName = 'ImageCreateFromJPEG'; + break; + case "\x89".'PN': + $ICFSreplacementFunctionName = 'ImageCreateFromPNG'; + break; + default: + $this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "'.phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)).'"', __FILE__, __LINE__); + return false; + break; + } + if ($tempnam = $this->phpThumb_tempnam()) { + if ($fp_tempnam = @fopen($tempnam, 'wb')) { + fwrite($fp_tempnam, $RawImageData); + fclose($fp_tempnam); + if (($ICFSreplacementFunctionName == 'ImageCreateFromGIF') && !function_exists($ICFSreplacementFunctionName)) { + + // Need to create from GIF file, but ImageCreateFromGIF does not exist + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.gif.php')) { + $ErrorMessage = 'Failed to include required file "'.dirname(__FILE__).'/phpthumb.gif.php" in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + ob_end_clean(); + // gif_loadFileToGDimageResource() cannot read from raw data, write to file first + if ($tempfilename = $this->phpThumb_tempnam()) { + if ($fp_tempfile = @fopen($tempfilename, 'wb')) { + fwrite($fp_tempfile, $RawImageData); + fclose($fp_tempfile); + $gdimg_source = gif_loadFileToGDimageResource($tempfilename); + unlink($tempfilename); + return $gdimg_source; + break; + } else { + $ErrorMessage = 'Failed to open tempfile in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + } else { + $ErrorMessage = 'Failed to open generate tempfile name in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + + } elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam))) { + + // great + unlink($tempnam); + return $gdimg_source; + + } else { // GD functions not available + + if (!headers_sent()) { + // base64-encoded error image in GIF format + $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; + header('Content-Type: image/gif'); + echo base64_decode($ERROR_NOGD); + } else { + echo '*** ERROR: No PHP-GD support available ***'; + } + exit; + + } + } else { + $ErrorMessage = 'Failed to fopen('.$tempnam.', "wb") in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + @unlink($tempnam); + } else { + $ErrorMessage = 'Failed to generate phpThumb_tempnam() in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; + } + if ($DieOnErrors && $ErrorMessage) { + return $this->ErrorImage($ErrorMessage); + } + return false; + } + + function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) { + if (phpthumb_functions::gd_version() >= 2.0) { + if ($this->config_disable_imagecopyresampled) { + return phpthumb_functions::ImageCopyResampleBicubic($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + return ImageCopyResampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + return ImageCopyResized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + + function phpThumb_tempnam() { + if (!$this->config_temp_directory) { + $this->config_temp_directory = (getenv('TMPDIR') ? getenv('TMPDIR') : getenv('TMP')); + } + $tempnam = realpath(tempnam($this->config_temp_directory, 'pThumb')); + $this->DebugMessage('phpThumb_tempnam() returning "'.$tempnam.'"', __FILE__, __LINE__); + return $tempnam; + } + + function DebugMessage($message, $file='', $line='') { + $this->debugmessages[] = $message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); + return true; + } + + function DebugTimingMessage($message, $file='', $line='', $timestamp=0) { + if (!$timestamp) { + $timestamp = array_sum(explode(' ', microtime())); + } + $this->debugtiming[number_format($timestamp, 6, '.', '')] = ': '.$message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); + return true; + } + +} + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/phpthumb.filters.php b/site/racecalendar/phpthumb/phpthumb.filters.php new file mode 100644 index 0000000..ac058cb --- /dev/null +++ b/site/racecalendar/phpthumb/phpthumb.filters.php @@ -0,0 +1,1235 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.filters.php - image processing filter functions // +// /// +////////////////////////////////////////////////////////////// + +class phpthumb_filters { + + var $phpThumbObject = null; + + function phpthumb_filters() { + return true; + } + + function ApplyMask(&$gdimg_mask, &$gdimg_image) { + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping ApplyMask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=')) { + + $this->DebugMessage('Using alpha ApplyMask() technique', __FILE__, __LINE__); + if ($gdimg_mask_resized = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { + + ImageCopyResampled($gdimg_mask_resized, $gdimg_mask, 0, 0, 0, 0, ImageSX($gdimg_image), ImageSY($gdimg_image), ImageSX($gdimg_mask), ImageSY($gdimg_mask)); + if ($gdimg_mask_blendtemp = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { + + $color_background = ImageColorAllocate($gdimg_mask_blendtemp, 0, 0, 0); + ImageFilledRectangle($gdimg_mask_blendtemp, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp), $color_background); + ImageAlphaBlending($gdimg_mask_blendtemp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_mask_blendtemp, true); + for ($x = 0; $x < ImageSX($gdimg_image); $x++) { + for ($y = 0; $y < ImageSY($gdimg_image); $y++) { + //$RealPixel = phpthumb_functions::GetPixelColor($gdimg_mask_blendtemp, $x, $y); + $RealPixel = phpthumb_functions::GetPixelColor($gdimg_image, $x, $y); + $MaskPixel = phpthumb_functions::GrayscalePixel(phpthumb_functions::GetPixelColor($gdimg_mask_resized, $x, $y)); + $MaskAlpha = 127 - (floor($MaskPixel['red'] / 2) * (1 - ($RealPixel['alpha'] / 127))); + $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_mask_blendtemp, $RealPixel['red'], $RealPixel['green'], $RealPixel['blue'], $MaskAlpha); + ImageSetPixel($gdimg_mask_blendtemp, $x, $y, $newcolor); + } + } + ImageAlphaBlending($gdimg_image, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_image, true); + ImageCopy($gdimg_image, $gdimg_mask_blendtemp, 0, 0, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp)); + ImageDestroy($gdimg_mask_blendtemp); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + ImageDestroy($gdimg_mask_resized); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + + } else { + // alpha merging requires PHP v4.3.2+ + $this->DebugMessage('Skipping ApplyMask() technique because PHP is v"'.phpversion().'"', __FILE__, __LINE__); + } + return true; + } + + + function Bevel(&$gdimg, $width, $hexcolor1, $hexcolor2) { + $width = ($width ? $width : 5); + $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); + $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); + + ImageAlphaBlending($gdimg, true); + for ($i = 0; $i < $width; $i++) { + $alpha = round(($i / $width) * 127); + $color1[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1, false, $alpha); + $color2[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2, false, $alpha); + + ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1[$i]); // left + ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1[$i]); // top + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2[$i]); // right + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2[$i]); // bottom + } + return true; + } + + + function Blur(&$gdimg, $radius=0.5) { + // Taken from Torstein Hønsi's phpUnsharpMask (see phpthumb.unsharp.php) + + $radius = round(max(0, min($radius, 50)) * 2); + if (!$radius) { + return false; + } + + $w = ImageSX($gdimg); + $h = ImageSY($gdimg); + if ($imgBlur = ImageCreateTrueColor($w, $h)) { + // Gaussian blur matrix: + // 1 2 1 + // 2 4 2 + // 1 2 1 + + // Move copies of the image around one pixel at the time and merge them with weight + // according to the matrix. The same matrix is simply repeated for higher radii. + for ($i = 0; $i < $radius; $i++) { + ImageCopy ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1); // up left + ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w, $h, 50.00000); // down right + ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left + ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w, $h - 1, 25.00000); // up right + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left + ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w, $h, 25.00000); // right + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w, $h - 1, 20.00000); // up + ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w, $h, 16.666667); // down + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w, $h, 50.000000); // center + ImageCopy ($gdimg, $imgBlur, 0, 0, 0, 0, $w, $h); + } + return true; + } + return false; + } + + + function BlurGaussian(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)', __FILE__, __LINE__); + // fall through and try it the hard way + } + $this->DebugMessage('FAILED: phpthumb_filters::BlurGaussian($gdimg) [using phpthumb_filters::Blur() instead]', __FILE__, __LINE__); + return phpthumb_filters::Blur($gdimg, 0.5); + } + + + function BlurSelective(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::BlurSelective($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Brightness(&$gdimg, $amount=0) { + if ($amount == 0) { + return true; + } + $amount = max(-255, min(255, $amount)); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + + $scaling = (255 - abs($amount)) / 255; + $baseamount = (($amount > 0) ? $amount : 0); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + foreach ($OriginalPixel as $key => $value) { + $NewPixel[$key] = round($baseamount + ($OriginalPixel[$key] * $scaling)); + } + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Contrast(&$gdimg, $amount=0) { + if ($amount == 0) { + return true; + } + $amount = max(-255, min(255, $amount)); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_CONTRAST, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_CONTRAST, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + + if ($amount > 0) { + $scaling = 1 + ($amount / 255); + } else { + $scaling = (255 - abs($amount)) / 255; + } + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + foreach ($OriginalPixel as $key => $value) { + $NewPixel[$key] = min(255, max(0, round($OriginalPixel[$key] * $scaling))); + } + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + } + + + function Colorize(&$gdimg, $amount, $targetColor) { + $amount = (is_numeric($amount) ? $amount : 25); + $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'gray'); + + if ($amount == 0) { + return true; + } + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if ($targetColor == 'gray') { + $targetColor = '808080'; + } + $r = substr($targetColor, 0, 2); + $g = substr($targetColor, 2, 2); + $b = substr($targetColor, 4, 2); + if (ImageFilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + + // overridden below for grayscale + if ($targetColor != 'gray') { + $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); + $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); + $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); + } + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + if ($targetColor == 'gray') { + $TargetPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + } + foreach ($TargetPixel as $key => $value) { + $NewPixel[$key] = round(max(0, min(255, ($OriginalPixel[$key] * ((100 - $amount) / 100)) + ($TargetPixel[$key] * ($amount / 100))))); + } + //$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Desaturate(&$gdimg, $amount, $color='') { + if ($amount == 0) { + return true; + } + return phpthumb_filters::Colorize($gdimg, $amount, (phpthumb_functions::IsHexColor($color) ? $color : 'gray')); + } + + + function DropShadow(&$gdimg, $distance, $width, $hexcolor, $angle, $fade) { + if (phpthumb_functions::gd_version() < 2) { + return false; + } + $distance = ($distance ? $distance : 10); + $width = ($width ? $width : 10); + $hexcolor = ($hexcolor ? $hexcolor : '000000'); + $angle = ($angle ? $angle : 225); + $fade = ($fade ? $fade : 1); + + $width_shadow = cos(deg2rad($angle)) * ($distance + $width); + $height_shadow = sin(deg2rad($angle)) * ($distance + $width); + + $scaling = min(ImageSX($gdimg) / (ImageSX($gdimg) + abs($width_shadow)), ImageSY($gdimg) / (ImageSY($gdimg) + abs($height_shadow))); + + for ($i = 0; $i < $width; $i++) { + $WidthAlpha[$i] = (abs(($width / 2) - $i) / $width) * $fade; + $Offset['x'] = cos(deg2rad($angle)) * ($distance + $i); + $Offset['y'] = sin(deg2rad($angle)) * ($distance + $i); + } + + $tempImageWidth = ImageSX($gdimg) + abs($Offset['x']); + $tempImageHeight = ImageSY($gdimg) + abs($Offset['y']); + + if ($gdimg_dropshadow_temp = phpthumb_functions::ImageCreateFunction($tempImageWidth, $tempImageHeight)) { + + ImageAlphaBlending($gdimg_dropshadow_temp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_dropshadow_temp, true); + $transparent1 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, 0, 0, 0, 127); + ImageFill($gdimg_dropshadow_temp, 0, 0, $transparent1); + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $PixelMap[$x][$y] = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + } + } + for ($x = 0; $x < $tempImageWidth; $x++) { + for ($y = 0; $y < $tempImageHeight; $y++) { + //for ($i = 0; $i < $width; $i++) { + for ($i = 0; $i < 1; $i++) { + if (!isset($PixelMap[$x][$y]['alpha']) || ($PixelMap[$x][$y]['alpha'] > 0)) { + if (isset($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']) && ($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha'] < 127)) { + $thisColor = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor, false, $PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']); + ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); + } + } + } + } + } + + ImageAlphaBlending($gdimg_dropshadow_temp, true); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + if ($PixelMap[$x][$y]['alpha'] < 127) { + $thisColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, $PixelMap[$x][$y]['red'], $PixelMap[$x][$y]['green'], $PixelMap[$x][$y]['blue'], $PixelMap[$x][$y]['alpha']); + ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); + } + } + } + + phpthumb_functions::gd_ImageSaveAlpha($gdimg, true); + ImageAlphaBlending($gdimg, false); + //$this->is_alpha = true; + $transparent2 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0, 0, 0, 127); + ImageFilledRectangle($gdimg, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $transparent2); + ImageCopyResampled($gdimg, $gdimg_dropshadow_temp, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg_dropshadow_temp), ImageSY($gdimg_dropshadow_temp)); + + ImageDestroy($gdimg_dropshadow_temp); + } + return true; + } + + + function EdgeDetect(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::EdgeDetect($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Elipse($gdimg) { + if (phpthumb_functions::gd_version() < 2) { + return false; + } + // generate mask at twice desired resolution and downsample afterwards for easy antialiasing + if ($gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg) * 2, ImageSY($gdimg) * 2)) { + if ($gdimg_elipsemask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + + $color_transparent = ImageColorAllocate($gdimg_elipsemask_double, 255, 255, 255); + ImageFilledEllipse($gdimg_elipsemask_double, ImageSX($gdimg), ImageSY($gdimg), (ImageSX($gdimg) - 1) * 2, (ImageSY($gdimg) - 1) * 2, $color_transparent); + ImageCopyResampled($gdimg_elipsemask, $gdimg_elipsemask_double, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg) * 2, ImageSY($gdimg) * 2); + + phpthumb_filters::ApplyMask($gdimg_elipsemask, $gdimg); + ImageDestroy($gdimg_elipsemask); + return true; + + } else { + $this->DebugMessage('$gdimg_elipsemask = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); + } + ImageDestroy($gdimg_elipsemask_double); + } else { + $this->DebugMessage('$gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); + } + return false; + } + + + function Emboss(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_EMBOSS)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EMBOSS)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::Emboss($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Flip(&$gdimg, $x=false, $y=false) { + if (!$x && !$y) { + return false; + } + if ($tempImage = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + if ($x) { + ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + ImageCopy($gdimg, $tempImage, ImageSX($gdimg) - 1 - $x, 0, $x, 0, 1, ImageSY($gdimg)); + } + } + if ($y) { + ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); + for ($y = 0; $y < ImageSY($gdimg); $y++) { + ImageCopy($gdimg, $tempImage, 0, ImageSY($gdimg) - 1 - $y, 0, $y, ImageSX($gdimg), 1); + } + } + ImageDestroy($tempImage); + } + return true; + } + + + function Frame(&$gdimg, $frame_width, $edge_width, $hexcolor_frame, $hexcolor1, $hexcolor2) { + $frame_width = ($frame_width ? $frame_width : 5); + $edge_width = ($edge_width ? $edge_width : 1); + $hexcolor_frame = ($hexcolor_frame ? $hexcolor_frame : 'CCCCCC'); + $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); + $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); + + $color_frame = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor_frame); + $color1 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1); + $color2 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2); + for ($i = 0; $i < $edge_width; $i++) { + // outer bevel + ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1); // left + ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1); // top + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2); // right + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2); // bottom + } + for ($i = 0; $i < $frame_width; $i++) { + // actual frame + ImageRectangle($gdimg, $edge_width + $i, $edge_width + $i, ImageSX($gdimg) - $edge_width - $i, ImageSY($gdimg) - $edge_width - $i, $color_frame); + } + for ($i = 0; $i < $edge_width; $i++) { + // inner bevel + ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color2); // left + ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color2); // top + ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color1); // right + ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color1); // bottom + } + return true; + } + + + function Gamma(&$gdimg, $amount) { + if (number_format($amount, 4) == '1.0000') { + return true; + } + return ImageGammaCorrect($gdimg, 1.0, $amount); + } + + + function Grayscale(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + return phpthumb_filters::Colorize($gdimg, 100, 'gray'); + } + + + function HistogramAnalysis(&$gdimg, $calculateGray=false) { + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + @$Analysis['red'][$OriginalPixel['red']]++; + @$Analysis['green'][$OriginalPixel['green']]++; + @$Analysis['blue'][$OriginalPixel['blue']]++; + @$Analysis['alpha'][$OriginalPixel['alpha']]++; + if ($calculateGray) { + $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + @$Analysis['gray'][$GrayPixel['red']]++; + } + } + } + $keys = array('red', 'green', 'blue', 'alpha'); + if ($calculateGray) { + $keys[] = 'gray'; + } + foreach ($keys as $dummy => $key) { + ksort($Analysis[$key]); + } + return $Analysis; + } + + + function HistogramStretch(&$gdimg, $band='*', $min=-1, $max=-1) { + // equivalent of "Auto Contrast" in Adobe Photoshop + + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); + $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); + if (!isset($keys[$band])) { + return false; + } + $key = $keys[$band]; + + // If the absolute brightest and darkest pixels are used then one random + // pixel in the image could throw off the whole system. Instead, count up/down + // from the limit and allow 0.1% of brightest/darkest pixels to be clipped to min/max + $clip_threshold = ImageSX($gdimg) * ImageSX($gdimg) * 0.001; + if ($min >= 0) { + $range_min = min($min, 255); + } else { + $countsum = 0; + for ($i = 0; $i <= 255; $i++) { + $countsum += @$Analysis[$key][$i]; + if ($countsum >= $clip_threshold) { + $range_min = $i - 1; + break; + } + } + $range_min = max($range_min, 0); + } + if ($max >= 0) { + $range_max = max($max, 255); + } else { + $countsum = 0; + $threshold = ImageSX($gdimg) * ImageSX($gdimg) * 0.001; // 0.1% of brightest and darkest pixels can be clipped + for ($i = 255; $i >= 0; $i--) { + $countsum += @$Analysis[$key][$i]; + if ($countsum >= $clip_threshold) { + $range_max = $i + 1; + break; + } + } + $range_max = min($range_max, 255); + } + $range_scale = (($range_max == $range_min) ? 1 : (255 / ($range_max - $range_min))); + if (($range_min == 0) && ($range_max == 255)) { + // no adjustment neccesary - don't waste CPU time! + return true; + } + + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + if ($band == '*') { + $new['red'] = min(255, max(0, ($OriginalPixel['red'] - $range_min) * $range_scale)); + $new['green'] = min(255, max(0, ($OriginalPixel['green'] - $range_min) * $range_scale)); + $new['blue'] = min(255, max(0, ($OriginalPixel['blue'] - $range_min) * $range_scale)); + $new['alpha'] = min(255, max(0, ($OriginalPixel['alpha'] - $range_min) * $range_scale)); + } else { + $new = $OriginalPixel; + $new[$key] = min(255, max(0, ($OriginalPixel[$key] - $range_min) * $range_scale)); + } + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $new['red'], $new['green'], $new['blue'], $new['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + + return true; + } + + + function HistogramOverlay(&$gdimg, $bands='*', $colors='', $width=0.25, $height=0.25, $alignment='BR', $opacity=50, $margin=5) { + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); + + $histW = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); + $histH = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); + if ($gdHist = ImageCreateTrueColor($histW, $histH)) { + $color_back = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHist, 0, 0, 0, 127); + ImageFilledRectangle($gdHist, 0, 0, $histW, $histH, $color_back); + ImageAlphaBlending($gdHist, false); + phpthumb_functions::gd_ImageSaveAlpha($gdHist, true); + + if ($gdHistTemp = ImageCreateTrueColor(256, 100)) { + $color_back_temp = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHistTemp, 255, 0, 255, 127); + ImageAlphaBlending($gdHistTemp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdHistTemp, true); + ImageFilledRectangle($gdHistTemp, 0, 0, ImageSX($gdHistTemp), ImageSY($gdHistTemp), $color_back_temp); + + $DefaultColors = array('r'=>'FF0000', 'g'=>'00FF00', 'b'=>'0000FF', 'a'=>'999999', '*'=>'FFFFFF'); + $Colors = explode(';', $colors); + $BandsToGraph = array_unique(preg_split('//', $bands)); + $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); + foreach ($BandsToGraph as $key => $band) { + if (!isset($keys[$band])) { + continue; + } + $PeakValue = max($Analysis[$keys[$band]]); + $thisColor = phpthumb_functions::ImageHexColorAllocate($gdHistTemp, phpthumb_functions::IsHexColor(@$Colors[$key]) ? $Colors[$key] : $DefaultColors[$band]); + $tempHeight = ImageSY($gdHistTemp); + for ($x = 0; $x <= 255; $x++) { + ImageLine($gdHistTemp, $x, $tempHeight - 1, $x, $tempHeight - 1 - round(@$Analysis[$keys[$band]][$x] / $PeakValue * $tempHeight), $thisColor); + } + ImageLine($gdHistTemp, 0, $tempHeight - 1, 255, $tempHeight - 1, $thisColor); + ImageLine($gdHistTemp, 0, $tempHeight - 2, 255, $tempHeight - 2, $thisColor); + } + ImageCopyResampled($gdHist, $gdHistTemp, 0, 0, 0, 0, ImageSX($gdHist), ImageSY($gdHist), ImageSX($gdHistTemp), ImageSY($gdHistTemp)); + ImageDestroy($gdHistTemp); + } else { + return false; + } + + phpthumb_filters::WatermarkOverlay($gdimg, $gdHist, $alignment, $opacity, $margin); + ImageDestroy($gdHist); + return true; + } + return false; + } + + + function ImageBorder(&$gdimg, $border_width, $radius_x, $radius_y, $hexcolor_border) { + $border_width = ($border_width ? $border_width : 1); + $radius_x = ($radius_x ? $radius_x : 0); + $radius_y = ($radius_y ? $radius_y : 0); + + $output_width = ImageSX($gdimg); + $output_height = ImageSY($gdimg); + + list($new_width, $new_height) = phpthumb_functions::ProportionalResize($output_width, $output_height, $output_width - max($border_width * 2, $radius_x), $output_height - max($border_width * 2, $radius_y)); + $offset_x = ($radius_x ? $output_width - $new_width - $radius_x : 0); + $offset_y = ($radius_y ? $output_height - $new_height - $radius_y : 0); + + if ($gd_border_canvas = phpthumb_functions::ImageCreateFunction($output_width, $output_height)) { + + phpthumb_functions::gd_ImageSaveAlpha($gd_border_canvas, true); + ImageAlphaBlending($gd_border_canvas, false); + $color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gd_border_canvas, 255, 255, 255, 127); + ImageFilledRectangle($gd_border_canvas, 0, 0, $output_width, $output_height, $color_background); + + $color_border = phpthumb_functions::ImageHexColorAllocate($gd_border_canvas, (phpthumb_functions::IsHexColor($hexcolor_border) ? $hexcolor_border : '000000')); + + for ($i = 0; $i < $border_width; $i++) { + ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $i, $output_width - $radius_x - ceil($offset_x / 2), $i, $color_border); // top + ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $output_height - 1 - $i, $output_width - $radius_x - ceil($offset_x / 2), $output_height - 1 - $i, $color_border); // bottom + ImageLine($gd_border_canvas, floor($offset_x / 2) + $i, $radius_y, floor($offset_x / 2) + $i, $output_height - $radius_y, $color_border); // left + ImageLine($gd_border_canvas, $output_width - 1 - $i - ceil($offset_x / 2), $radius_y, $output_width - 1 - $i - ceil($offset_x / 2), $output_height - $radius_y, $color_border); // right + } + + if ($radius_x && $radius_y) { + + // PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results + // Solution: Draw multiple 1px arcs side-by-side. + + // Problem: parallel arcs give strange/ugly antialiasing problems + // Solution: draw non-parallel arcs, from one side of the line thickness at the start angle + // to the opposite edge of the line thickness at the terminating angle + for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { + ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left + ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right + ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right + ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left + } + if ($border_width > 1) { + for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { + ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left + ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right + ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right + ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left + } + } + + } + $this->phpThumbObject->ImageResizeFunction($gd_border_canvas, $gdimg, floor(($output_width - $new_width) / 2), round(($output_height - $new_height) / 2), 0, 0, $new_width, $new_height, $output_width, $output_height); + + ImageDestroy($gdimg); + $gdimg = phpthumb_functions::ImageCreateFunction($output_width, $output_height); + phpthumb_functions::gd_ImageSaveAlpha($gdimg, true); + ImageAlphaBlending($gdimg, false); + $gdimg_color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 255, 255, 255, 127); + ImageFilledRectangle($gdimg, 0, 0, $output_width, $output_height, $gdimg_color_background); + + ImageCopy($gdimg, $gd_border_canvas, 0, 0, 0, 0, $output_width, $output_height); + //$gdimg = $gd_border_canvas; + ImageDestroy($gd_border_canvas); + return true; + + + } else { + $this->DebugMessage('FAILED: $gd_border_canvas = phpthumb_functions::ImageCreateFunction('.$output_width.', '.$output_height.')', __FILE__, __LINE__); + } + return false; + } + + + function MeanRemoval(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::MeanRemoval($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Negative(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_NEGATE)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_NEGATE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, (~$currentPixel['red'] & 0xFF), (~$currentPixel['green'] & 0xFF), (~$currentPixel['blue'] & 0xFF), $currentPixel['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function RoundedImageCorners(&$gdimg, $radius_x, $radius_y) { + // generate mask at twice desired resolution and downsample afterwards for easy antialiasing + // mask is generated as a white double-size elipse on a triple-size black background and copy-paste-resampled + // onto a correct-size mask image as 4 corners due to errors when the entire mask is resampled at once (gray edges) + if ($gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction($radius_x * 6, $radius_y * 6)) { + if ($gdimg_cornermask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + + $color_transparent = ImageColorAllocate($gdimg_cornermask_triple, 255, 255, 255); + ImageFilledEllipse($gdimg_cornermask_triple, $radius_x * 3, $radius_y * 3, $radius_x * 4, $radius_y * 4, $color_transparent); + + ImageFilledRectangle($gdimg_cornermask, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $color_transparent); + + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, 0, $radius_x, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, ImageSY($gdimg) - $radius_y, $radius_x, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, ImageSY($gdimg) - $radius_y, $radius_x * 3, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, 0, $radius_x * 3, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + + phpthumb_filters::ApplyMask($gdimg_cornermask, $gdimg); + ImageDestroy($gdimg_cornermask); + $this->DebugMessage('RoundedImageCorners('.$radius_x.', '.$radius_y.') succeeded', __FILE__, __LINE__); + return true; + + } else { + $this->DebugMessage('FAILED: $gdimg_cornermask = phpthumb_functions::ImageCreateFunction('.ImageSX($gdimg).', '.ImageSY($gdimg).')', __FILE__, __LINE__); + } + ImageDestroy($gdimg_cornermask_triple); + + } else { + $this->DebugMessage('FAILED: $gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction('.($radius_x * 6).', '.($radius_y * 6).')', __FILE__, __LINE__); + } + return false; + } + + + function Saturation(&$gdimg, $amount, $color='') { + if ($amount == 0) { + return true; + } elseif ($amount > 0) { + $amount = 0 - $amount; + } else { + $amount = abs($amount); + } + return phpthumb_filters::Desaturate($gdimg, $amount, $color); + } + + + function Sepia(&$gdimg, $amount, $targetColor) { + $amount = (is_numeric($amount) ? max(0, min(100, $amount)) : 50); + $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'A28065'); + + if ($amount == 0) { + return true; + } + + $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); + $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); + $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); + + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + + // http://www.gimpguru.org/Tutorials/SepiaToning/ + // "In the traditional sepia toning process, the tinting occurs most in + // the mid-tones: the lighter and darker areas appear to be closer to B&W." + $SepiaAmount = ((128 - abs($GrayPixel['red'] - 128)) / 128) * ($amount / 100); + + foreach ($TargetPixel as $key => $value) { + $NewPixel[$key] = round(max(0, min(255, $GrayPixel[$key] * (1 - $SepiaAmount) + ($TargetPixel[$key] * $SepiaAmount)))); + } + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Smooth(&$gdimg, $amount=6) { + $amount = min(25, max(0, $amount)); + if ($amount == 0) { + return true; + } + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_SMOOTH, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SMOOTH, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, '.$amount.') [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Threshold(&$gdimg, $cutoff) { + $cutoff = min(255, max(0, ($cutoff ? $cutoff : 128))); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $grayPixel = phpthumb_functions::GrayscalePixel($currentPixel); + if ($grayPixel['red'] < $cutoff) { + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0x00, 0x00, 0x00, $currentPixel['alpha']); + } else { + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0xFF, 0xFF, 0xFF, $currentPixel['alpha']); + } + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function ImageTrueColorToPalette2(&$image, $dither, $ncolors) { + // http://www.php.net/manual/en/function.imagetruecolortopalette.php + // zmorris at zsculpt dot com (17-Aug-2004 06:58) + $width = ImageSX($image); + $height = ImageSY($image); + $image_copy = ImageCreateTrueColor($width, $height); + //ImageCopyMerge($image_copy, $image, 0, 0, 0, 0, $width, $height, 100); + ImageCopy($image_copy, $image, 0, 0, 0, 0, $width, $height); + ImageTrueColorToPalette($image, $dither, $ncolors); + ImageColorMatch($image_copy, $image); + ImageDestroy($image_copy); + return true; + } + + function ReduceColorDepth(&$gdimg, $colors=256, $dither=true) { + $colors = max(min($colors, 256), 2); + // ImageTrueColorToPalette usually makes ugly colors, the replacement is a bit better + //ImageTrueColorToPalette($gdimg, $dither, $colors); + phpthumb_filters::ImageTrueColorToPalette2($gdimg, $dither, $colors); + return true; + } + + + function WhiteBalance(&$gdimg, $targetColor='') { + if (phpthumb_functions::IsHexColor($targetColor)) { + $targetPixel = array( + 'red' => hexdec(substr($targetColor, 0, 2)), + 'green' => hexdec(substr($targetColor, 2, 2)), + 'blue' => hexdec(substr($targetColor, 4, 2)) + ); + } else { + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, false); + $targetPixel = array( + 'red' => max(array_keys($Analysis['red'])), + 'green' => max(array_keys($Analysis['green'])), + 'blue' => max(array_keys($Analysis['blue'])) + ); + } + $grayValue = phpthumb_functions::GrayscaleValue($targetPixel['red'], $targetPixel['green'], $targetPixel['blue']); + $scaleR = $grayValue / $targetPixel['red']; + $scaleG = $grayValue / $targetPixel['green']; + $scaleB = $grayValue / $targetPixel['blue']; + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe( + $gdimg, + max(0, min(255, round($currentPixel['red'] * $scaleR))), + max(0, min(255, round($currentPixel['green'] * $scaleG))), + max(0, min(255, round($currentPixel['blue'] * $scaleB))), + $currentPixel['alpha'] + ); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function WatermarkText(&$gdimg, $text, $size, $alignment, $hex_color='000000', $ttffont='', $opacity=100, $margin=5, $angle=0, $bg_color=false, $bg_opacity=0, $fillextend='') { + // text watermark requested + if (!$text) { + return false; + } + ImageAlphaBlending($gdimg, true); + + $metaTextArray = array( + '^Fb' => $this->phpThumbObject->getimagesizeinfo['filesize'], + '^Fk' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1024), + '^Fm' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1048576), + '^X' => $this->phpThumbObject->getimagesizeinfo[0], + '^Y' => $this->phpThumbObject->getimagesizeinfo[1], + '^x' => ImageSX($gdimg), + '^y' => ImageSY($gdimg), + '^^' => '^', + ); + $text = strtr($text, $metaTextArray); + + $text = str_replace("\r\n", "\n", $text); + $text = str_replace("\r", "\n", $text); + $textlines = explode("\n", $text); + + if (@is_readable($ttffont) && is_file($ttffont)) { + + $opacity = 100 - intval(max(min($opacity, 100), 0)); + + $this->DebugMessage('Using TTF font "'.$ttffont.'"', __FILE__, __LINE__); + + $TTFbox = ImageTTFbBox($size, $angle, $ttffont, $text); + + $min_x = min($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); + $max_x = max($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); + //$text_width = round($max_x - $min_x + ($size * 0.5)); + $text_width = round($max_x - $min_x); + + $min_y = min($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); + $max_y = max($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); + //$text_height = round($max_y - $min_y + ($size * 0.5)); + $text_height = round($max_y - $min_y); + + $TTFboxChar = ImageTTFbBox($size, $angle, $ttffont, 'jH'); + $char_min_y = min($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); + $char_max_y = max($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); + $char_height = round($char_max_y - $char_min_y); + + switch ($alignment) { + case 'T': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = $char_height + $margin; + break; + + case 'B': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + + case 'L': + $text_origin_x = $margin; + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'R': + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'C': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'TL': + $text_origin_x = $margin; + $text_origin_y = $char_height + $margin; + break; + + case 'TR': + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = $char_height + $margin; + break; + + case 'BL': + $text_origin_x = $margin; + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + + case 'BR': + default: + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + } + $letter_color_text = phpthumb_functions::ImageHexColorAllocate($gdimg, $hex_color, false, $opacity * 1.27); + + if ($alignment == '*') { + + $text_origin_y = $char_height + $margin; + while (($text_origin_y - $text_height) < ImageSY($gdimg)) { + $text_origin_x = $margin; + while ($text_origin_x < ImageSX($gdimg)) { + ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); + $text_origin_x += ($text_width + $margin); + } + $text_origin_y += ($text_height + $margin); + } + + } else { + + //ImageRectangle($gdimg, $text_origin_x + $min_x, $text_origin_y + $TTFbox[1], $text_origin_x + $min_x + $text_width, $text_origin_y + $TTFbox[1] - $text_height, $letter_color_text); + if (phpthumb_functions::IsHexColor($bg_color)) { + $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); + $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, $bg_color, false, $text_background_alpha); + } else { + $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, 'FFFFFF', false, 127); + } + $x1 = $text_origin_x + $min_x; + $y1 = $text_origin_y + $TTFbox[1]; + $x2 = $text_origin_x + $min_x + $text_width; + $y2 = $text_origin_y + $TTFbox[1] - $text_height; + $x_TL = eregi('x', $fillextend) ? 0 : min($x1, $x2); + $y_TL = eregi('y', $fillextend) ? 0 : min($y1, $y2); + $x_BR = eregi('x', $fillextend) ? ImageSX($gdimg) : max($x1, $x2); + $y_BR = eregi('y', $fillextend) ? ImageSY($gdimg) : max($y1, $y2); + //while ($y_BR > ImageSY($gdimg)) { + // $y_TL--; + // $y_BR--; + // $text_origin_y--; + //} + ImageFilledRectangle($gdimg, $x_TL, $y_TL, $x_BR, $y_BR, $text_color_background); + ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); + + } + return true; + + } else { + + $size = min(5, max(1, $size)); + $this->DebugMessage('Using built-in font (size='.$size.') for text watermark'.($ttffont ? ' because $ttffont !is_readable('.$ttffont.')' : ''), __FILE__, __LINE__); + + $text_width = 0; + $text_height = 0; + foreach ($textlines as $dummy => $line) { + $text_width = max($text_width, ImageFontWidth($size) * strlen($line)); + $text_height += ImageFontHeight($size); + } + if ($img_watermark = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { + ImageAlphaBlending($img_watermark, false); + if (phpthumb_functions::IsHexColor($bg_color)) { + $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); + $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, $bg_color, false, $text_background_alpha); + } else { + $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, 'FFFFFF', false, 127); + } + ImageFilledRectangle($img_watermark, 0, 0, ImageSX($img_watermark), ImageSY($img_watermark), $text_color_background); + + if ($angle && function_exists('ImageRotate')) { + // using $img_watermark_mask is pointless if ImageRotate function isn't available + if ($img_watermark_mask = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { + $mask_color_background = ImageColorAllocate($img_watermark_mask, 0, 0, 0); + ImageAlphaBlending($img_watermark_mask, false); + ImageFilledRectangle($img_watermark_mask, 0, 0, ImageSX($img_watermark_mask), ImageSY($img_watermark_mask), $mask_color_background); + $mask_color_watermark = ImageColorAllocate($img_watermark_mask, 255, 255, 255); + } + } + + $text_color_watermark = phpthumb_functions::ImageHexColorAllocate($img_watermark, $hex_color); + foreach ($textlines as $key => $line) { + switch ($alignment) { + case 'C': + case 'T': + case 'B': + $x_offset = round(($text_width - (ImageFontWidth($size) * strlen($line))) / 2); + break; + + case 'L': + case 'TL': + case 'BL': + $x_offset = 0; + break; + + case 'R': + case 'TR': + case 'BR': + default: + $x_offset = $text_width - (ImageFontWidth($size) * strlen($line)); + break; + } + ImageString($img_watermark, $size, $x_offset, $key * ImageFontHeight($size), $line, $text_color_watermark); + if ($angle && $img_watermark_mask) { + ImageString($img_watermark_mask, $size, $x_offset, $key * ImageFontHeight($size), $text, $mask_color_watermark); + } + } + if ($angle && $img_watermark_mask) { + $img_watermark = ImageRotate($img_watermark, $angle, $text_color_background); + $img_watermark_mask = ImageRotate($img_watermark_mask, $angle, $mask_color_background); + phpthumb_filters::ApplyMask($img_watermark_mask, $img_watermark); + } + phpthumb_filters::WatermarkOverlay($gdimg, $img_watermark, $alignment, $opacity, $margin); + ImageDestroy($img_watermark); + return true; + } + + } + return false; + } + + + function WatermarkOverlay(&$gdimg_dest, &$img_watermark, $alignment='*', $opacity=50, $margin=5) { + if (is_resource($gdimg_dest) && is_resource($img_watermark)) { + $watermark_source_x = 0; + $watermark_source_y = 0; + $img_source_width = ImageSX($gdimg_dest); + $img_source_height = ImageSY($gdimg_dest); + $watermark_source_width = ImageSX($img_watermark); + $watermark_source_height = ImageSY($img_watermark); + $watermark_opacity_percent = max(0, min(100, $opacity)); + if ($margin < 1) { + $watermark_margin_percent = 1 - $margin; + } else { + $watermark_margin_percent = (100 - max(0, min(100, $margin))) / 100; + } + $watermark_margin_x = round((1 - $watermark_margin_percent) * $img_source_width); + $watermark_margin_y = round((1 - $watermark_margin_percent) * $img_source_height); + switch ($alignment) { + case '*': + if ($gdimg_tiledwatermark = phpthumb_functions::ImageCreateFunction($img_source_width, $img_source_height)) { + + ImageAlphaBlending($gdimg_tiledwatermark, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_tiledwatermark, true); + $text_color_transparent = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_tiledwatermark, 255, 0, 255, 127); + ImageFill($gdimg_tiledwatermark, 0, 0, $text_color_transparent); + + // set the tiled image transparent color to whatever the untiled image transparency index is +// ImageColorTransparent($gdimg_tiledwatermark, ImageColorTransparent($img_watermark)); + + // a "cleaner" way of doing it, but can't handle the margin feature :( +// ImageSetTile($gdimg_tiledwatermark, $img_watermark); +// ImageFill($gdimg_tiledwatermark, 0, 0, IMG_COLOR_TILED); +// break; + +// ImageFill($gdimg_tiledwatermark, 0, 0, ImageColorTransparent($gdimg_tiledwatermark)); + // tile the image as many times as can fit + for ($x = $watermark_margin_x; $x < ($img_source_width + $watermark_source_width); $x += round($watermark_source_width + ((1 - $watermark_margin_percent) * $img_source_width))) { + for ($y = $watermark_margin_y; $y < ($img_source_height + $watermark_source_height); $y += round($watermark_source_height + ((1 - $watermark_margin_percent) * $img_source_height))) { + ImageCopy( + $gdimg_tiledwatermark, + $img_watermark, + $x, + $y, + 0, + 0, + min($watermark_source_width, $img_source_width - $x - ((1 - $watermark_margin_percent) * $img_source_width)), + min($watermark_source_height, $img_source_height - $y - ((1 - $watermark_margin_percent) * $img_source_height)) + ); + } + } + + $watermark_source_width = ImageSX($gdimg_tiledwatermark); + $watermark_source_height = ImageSY($gdimg_tiledwatermark); + $watermark_destination_x = 0; + $watermark_destination_y = 0; + + ImageDestroy($img_watermark); + $img_watermark = $gdimg_tiledwatermark; + } + break; + + case 'T': + $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); + $watermark_destination_y = $watermark_margin_y; + break; + + case 'B': + $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + + case 'L': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); + break; + + case 'R': + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); + break; + + case 'C': + $watermark_destination_x = round(($img_source_width / 2) - ($watermark_source_width / 2)); + $watermark_destination_y = round(($img_source_height / 2) - ($watermark_source_height / 2)); + break; + + case 'TL': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = $watermark_margin_y; + break; + + case 'TR': + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = $watermark_margin_y; + break; + + case 'BL': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + + case 'BR': + default: + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + } + ImageAlphaBlending($gdimg_dest, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_dest, true); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark, true); + phpthumb_functions::ImageCopyRespectAlpha($gdimg_dest, $img_watermark, $watermark_destination_x, $watermark_destination_y, 0, 0, $watermark_source_width, $watermark_source_height, $watermark_opacity_percent); + + return true; + } + return false; + } + + + function DebugMessage($message, $file='', $line='') { + if (is_object($this->phpThumbObject)) { + return $this->phpThumbObject->DebugMessage($message, $file, $line); + } + return false; + } +} + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/phpthumb.functions.php b/site/racecalendar/phpthumb/phpthumb.functions.php new file mode 100644 index 0000000..9e29609 --- /dev/null +++ b/site/racecalendar/phpthumb/phpthumb.functions.php @@ -0,0 +1,707 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.functions.php - general support functions // +// /// +////////////////////////////////////////////////////////////// + +class phpthumb_functions { + + function user_function_exists($functionname) { + if (function_exists('get_defined_functions')) { + static $get_defined_functions = array(); + if (empty($get_defined_functions)) { + $get_defined_functions = get_defined_functions(); + } + return in_array(strtolower($functionname), $get_defined_functions['user']); + } + return function_exists($functionname); + } + + + function builtin_function_exists($functionname) { + if (function_exists('get_defined_functions')) { + static $get_defined_functions = array(); + if (empty($get_defined_functions)) { + $get_defined_functions = get_defined_functions(); + } + return in_array(strtolower($functionname), $get_defined_functions['internal']); + } + return function_exists($functionname); + } + + + function version_compare_replacement_sub($version1, $version2, $operator='') { + // If you specify the third optional operator argument, you can test for a particular relationship. + // The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively. + // Using this argument, the function will return 1 if the relationship is the one specified by the operator, 0 otherwise. + + // If a part contains special version strings these are handled in the following order: dev < (alpha = a) < (beta = b) < RC < pl + static $versiontype_lookup = array(); + if (empty($versiontype_lookup)) { + $versiontype_lookup['dev'] = 10001; + $versiontype_lookup['a'] = 10002; + $versiontype_lookup['alpha'] = 10002; + $versiontype_lookup['b'] = 10003; + $versiontype_lookup['beta'] = 10003; + $versiontype_lookup['RC'] = 10004; + $versiontype_lookup['pl'] = 10005; + } + if (isset($versiontype_lookup[$version1])) { + $version1 = $versiontype_lookup[$version1]; + } + if (isset($versiontype_lookup[$version2])) { + $version2 = $versiontype_lookup[$version2]; + } + + switch ($operator) { + case '<': + case 'lt': + return intval($version1 < $version2); + break; + case '<=': + case 'le': + return intval($version1 <= $version2); + break; + case '>': + case 'gt': + return intval($version1 > $version2); + break; + case '>=': + case 'ge': + return intval($version1 >= $version2); + break; + case '==': + case '=': + case 'eq': + return intval($version1 == $version2); + break; + case '!=': + case '<>': + case 'ne': + return intval($version1 != $version2); + break; + } + if ($version1 == $version2) { + return 0; + } elseif ($version1 < $version2) { + return -1; + } + return 1; + } + + + function version_compare_replacement($version1, $version2, $operator='') { + if (function_exists('version_compare')) { + // built into PHP v4.1.0+ + return version_compare($version1, $version2, $operator); + } + + // The function first replaces _, - and + with a dot . in the version strings + $version1 = strtr($version1, '_-+', '...'); + $version2 = strtr($version2, '_-+', '...'); + + // and also inserts dots . before and after any non number so that for example '4.3.2RC1' becomes '4.3.2.RC.1'. + // Then it splits the results like if you were using explode('.',$ver). Then it compares the parts starting from left to right. + $version1 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version1); + $version2 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version2); + + $parts1 = explode('.', $version1); + $parts2 = explode('.', $version1); + $parts_count = max(count($parts1), count($parts2)); + for ($i = 0; $i < $parts_count; $i++) { + $comparison = phpthumb_functions::version_compare_replacement_sub($version1, $version2, $operator); + if ($comparison != 0) { + return $comparison; + } + } + return 0; + } + + + function phpinfo_array() { + static $phpinfo_array = array(); + if (empty($phpinfo_array)) { + ob_start(); + phpinfo(); + $phpinfo = ob_get_contents(); + ob_end_clean(); + $phpinfo_array = explode("\n", $phpinfo); + } + return $phpinfo_array; + } + + + function exif_info() { + static $exif_info = array(); + if (empty($exif_info)) { + // based on code by johnschaefer at gmx dot de + // from PHP help on gd_info() + $exif_info = array( + 'EXIF Support' => '', + 'EXIF Version' => '', + 'Supported EXIF Version' => '', + 'Supported filetypes' => '' + ); + $phpinfo_array = phpthumb_functions::phpinfo_array(); + foreach ($phpinfo_array as $dummy => $line) { + $line = trim(strip_tags($line)); + foreach ($exif_info as $key => $value) { + if (strpos($line, $key) === 0) { + $newvalue = trim(str_replace($key, '', $line)); + $exif_info[$key] = $newvalue; + } + } + } + } + return $exif_info; + } + + + function ImageTypeToMIMEtype($imagetype) { + if (function_exists('image_type_to_mime_type') && ($imagetype >= 1) && ($imagetype <= 16)) { + // PHP v4.3.0+ + return image_type_to_mime_type($imagetype); + } + static $image_type_to_mime_type = array( + 1 => 'image/gif', // IMAGETYPE_GIF + 2 => 'image/jpeg', // IMAGETYPE_JPEG + 3 => 'image/png', // IMAGETYPE_PNG + 4 => 'application/x-shockwave-flash', // IMAGETYPE_SWF + 5 => 'image/psd', // IMAGETYPE_PSD + 6 => 'image/bmp', // IMAGETYPE_BMP + 7 => 'image/tiff', // IMAGETYPE_TIFF_II (intel byte order) + 8 => 'image/tiff', // IMAGETYPE_TIFF_MM (motorola byte order) + 9 => 'application/octet-stream', // IMAGETYPE_JPC + 10 => 'image/jp2', // IMAGETYPE_JP2 + 11 => 'application/octet-stream', // IMAGETYPE_JPX + 12 => 'application/octet-stream', // IMAGETYPE_JB2 + 13 => 'application/x-shockwave-flash', // IMAGETYPE_SWC + 14 => 'image/iff', // IMAGETYPE_IFF + 15 => 'image/vnd.wap.wbmp', // IMAGETYPE_WBMP + 16 => 'image/xbm', // IMAGETYPE_XBM + + 'gif' => 'image/gif', // IMAGETYPE_GIF + 'jpg' => 'image/jpeg', // IMAGETYPE_JPEG + 'jpeg' => 'image/jpeg', // IMAGETYPE_JPEG + 'png' => 'image/png', // IMAGETYPE_PNG + 'bmp' => 'image/bmp', // IMAGETYPE_BMP + 'ico' => 'image/x-icon', + ); + + return (isset($image_type_to_mime_type[$imagetype]) ? $image_type_to_mime_type[$imagetype] : false); + } + + + function HexCharDisplay($string) { + $len = strlen($string); + $output = ''; + for ($i = 0; $i < $len; $i++) { + $output .= ' 0x'.str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT); + } + return $output; + } + + + function IsHexColor($HexColorString) { + return eregi('^[0-9A-F]{6}$', $HexColorString); + } + + + function ImageColorAllocateAlphaSafe(&$gdimg_hexcolorallocate, $R, $G, $B, $alpha=false) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && ($alpha !== false)) { + return ImageColorAllocateAlpha($gdimg_hexcolorallocate, $R, $G, $B, intval($alpha)); + } else { + return ImageColorAllocate($gdimg_hexcolorallocate, $R, $G, $B); + } + } + + function ImageHexColorAllocate(&$gdimg_hexcolorallocate, $HexColorString, $dieOnInvalid=false, $alpha=false) { + if (!is_resource($gdimg_hexcolorallocate)) { + die('$gdimg_hexcolorallocate is not a GD resource in ImageHexColorAllocate()'); + } + if (phpthumb_functions::IsHexColor($HexColorString)) { + $R = hexdec(substr($HexColorString, 0, 2)); + $G = hexdec(substr($HexColorString, 2, 2)); + $B = hexdec(substr($HexColorString, 4, 2)); + return phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_hexcolorallocate, $R, $G, $B, $alpha); + } + if ($dieOnInvalid) { + die('Invalid hex color string: "'.$HexColorString.'"'); + } + return ImageColorAllocate($gdimg_hexcolorallocate, 0x00, 0x00, 0x00); + } + + + function HexColorXOR($hexcolor) { + return strtoupper(str_pad(dechex(~hexdec($hexcolor) & 0xFFFFFF), 6, '0', STR_PAD_LEFT)); + } + + + function GetPixelColor(&$img, $x, $y) { + if (!is_resource($img)) { + return false; + } + return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y)); + } + + + function GrayscaleValue($r, $g, $b) { + return round(($r * 0.30) + ($g * 0.59) + ($b * 0.11)); + } + + + function GrayscalePixel($OriginalPixel) { + $gray = phpthumb_functions::GrayscaleValue($OriginalPixel['red'], $OriginalPixel['green'], $OriginalPixel['blue']); + return array('red'=>$gray, 'green'=>$gray, 'blue'=>$gray); + } + + + function GrayscalePixelRGB($rgb) { + $r = ($rgb >> 16) & 0xFF; + $g = ($rgb >> 8) & 0xFF; + $b = $rgb & 0xFF; + return ($r * 0.299) + ($g * 0.587) + ($b * 0.114); + } + + + function ImageCopyResampleBicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) { + // ron at korving dot demon dot nl + // http://www.php.net/imagecopyresampled + + $scaleX = ($src_w - 1) / $dst_w; + $scaleY = ($src_h - 1) / $dst_h; + + $scaleX2 = $scaleX / 2.0; + $scaleY2 = $scaleY / 2.0; + + $isTrueColor = ImageIsTrueColor($src_img); + + for ($y = $src_y; $y < $src_y + $dst_h; $y++) { + $sY = $y * $scaleY; + $siY = (int) $sY; + $siY2 = (int) $sY + $scaleY2; + + for ($x = $src_x; $x < $src_x + $dst_w; $x++) { + $sX = $x * $scaleX; + $siX = (int) $sX; + $siX2 = (int) $sX + $scaleX2; + + if ($isTrueColor) { + + $c1 = ImageColorAt($src_img, $siX, $siY2); + $c2 = ImageColorAt($src_img, $siX, $siY); + $c3 = ImageColorAt($src_img, $siX2, $siY2); + $c4 = ImageColorAt($src_img, $siX2, $siY); + + $r = (( $c1 + $c2 + $c3 + $c4 ) >> 2) & 0xFF0000; + $g = ((($c1 & 0x00FF00) + ($c2 & 0x00FF00) + ($c3 & 0x00FF00) + ($c4 & 0x00FF00)) >> 2) & 0x00FF00; + $b = ((($c1 & 0x0000FF) + ($c2 & 0x0000FF) + ($c3 & 0x0000FF) + ($c4 & 0x0000FF)) >> 2); + + } else { + + $c1 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY2)); + $c2 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY)); + $c3 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY2)); + $c4 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY)); + + $r = ($c1['red'] + $c2['red'] + $c3['red'] + $c4['red'] ) << 14; + $g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6; + $b = ($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue'] ) >> 2; + + } + ImageSetPixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r+$g+$b); + } + } + return true; + } + + + function ImageCreateFunction($x_size, $y_size) { + $ImageCreateFunction = 'ImageCreate'; + if (phpthumb_functions::gd_version() >= 2.0) { + $ImageCreateFunction = 'ImageCreateTrueColor'; + } + if (!function_exists($ImageCreateFunction)) { + return phpthumb::ErrorImage($ImageCreateFunction.'() does not exist - no GD support?'); + } + if (($x_size <= 0) || ($y_size <= 0)) { + return phpthumb::ErrorImage('Invalid image dimensions: '.$ImageCreateFunction.'('.$x_size.', '.$y_size.')'); + } + return $ImageCreateFunction($x_size, $y_size); + } + + + function ImageCopyRespectAlpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct=100) { + for ($x = $src_x; $x < $src_w; $x++) { + for ($y = $src_y; $y < $src_h; $y++) { + $RealPixel = phpthumb_functions::GetPixelColor($dst_im, $dst_x + $x, $dst_y + $y); + $OverlayPixel = phpthumb_functions::GetPixelColor($src_im, $x, $y); + $alphapct = $OverlayPixel['alpha'] / 127; + $opacipct = $pct / 100; + $overlaypct = (1 - $alphapct) * $opacipct; + + $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe( + $dst_im, + round($RealPixel['red'] * (1 - $overlaypct)) + ($OverlayPixel['red'] * $overlaypct), + round($RealPixel['green'] * (1 - $overlaypct)) + ($OverlayPixel['green'] * $overlaypct), + round($RealPixel['blue'] * (1 - $overlaypct)) + ($OverlayPixel['blue'] * $overlaypct), + //$RealPixel['alpha']); + 0); + + ImageSetPixel($dst_im, $dst_x + $x, $dst_y + $y, $newcolor); + } + } + return true; + } + + + function ProportionalResize($old_width, $old_height, $new_width=false, $new_height=false) { + $old_aspect_ratio = $old_width / $old_height; + if (($new_width === false) && ($new_height === false)) { + return false; + } elseif ($new_width === false) { + $new_width = $new_height * $old_aspect_ratio; + } elseif ($new_height === false) { + $new_height = $new_width / $old_aspect_ratio; + } + $new_aspect_ratio = $new_width / $new_height; + if ($new_aspect_ratio == $old_aspect_ratio) { + // great, done + } elseif ($new_aspect_ratio < $old_aspect_ratio) { + // limited by width + $new_height = $new_width / $old_aspect_ratio; + } elseif ($new_aspect_ratio > $old_aspect_ratio) { + // limited by height + $new_width = $new_height * $old_aspect_ratio; + } + return array(round($new_width), round($new_height)); + } + + + function SafeExec($command) { + static $AllowedExecFunctions = array(); + if (empty($AllowedExecFunctions)) { + $AllowedExecFunctions = array('shell_exec'=>true, 'passthru'=>true, 'system'=>true, 'exec'=>true); + if (@ini_get('safe_mode')) { + $AllowedExecFunctions['shell_exec'] = false; + } + $disable_functions = explode(',', @ini_get('disable_functions')); + foreach ($AllowedExecFunctions as $key => $value) { + if (in_array($key, $disable_functions)) { + $AllowedExecFunctions[$key] = false; + } + } + } + foreach ($AllowedExecFunctions as $execfunction => $is_allowed) { + if (!$is_allowed) { + continue; + } + if ($execfunction == 'passthru') { + ob_start(); + $execfunction($command); + $returnvalue = ob_get_contents(); + ob_end_clean(); + } else { + $returnvalue = @$execfunction($command); + } + return $returnvalue; + } + return false; + } + + + function ApacheLookupURIarray($filename) { + // apache_lookup_uri() only works when PHP is installed as an Apache module. + if (php_sapi_name() == 'apache') { + $keys = array('status', 'the_request', 'status_line', 'method', 'content_type', 'handler', 'uri', 'filename', 'path_info', 'args', 'boundary', 'no_cache', 'no_local_copy', 'allowed', 'send_bodyct', 'bytes_sent', 'byterange', 'clength', 'unparsed_uri', 'mtime', 'request_time'); + if ($apacheLookupURIobject = @apache_lookup_uri($filename)) { + $apacheLookupURIarray = array(); + foreach ($keys as $dummy => $key) { + $apacheLookupURIarray[$key] = @$apacheLookupURIobject->$key; + } + return $apacheLookupURIarray; + } + } + return false; + } + + + function gd_is_bundled() { + static $isbundled = null; + if (is_null($isbundled)) { + $gd_info = gd_info(); + $isbundled = (strpos($gd_info['GD Version'], 'bundled') !== false); + } + return $isbundled; + } + + + function gd_version($fullstring=false) { + static $cache_gd_version = array(); + if (empty($cache_gd_version)) { + $gd_info = gd_info(); + if (eregi('bundled \((.+)\)$', $gd_info['GD Version'], $matches)) { + $cache_gd_version[1] = $gd_info['GD Version']; // e.g. "bundled (2.0.15 compatible)" + $cache_gd_version[0] = (float) $matches[1]; // e.g. "2.0" (not "bundled (2.0.15 compatible)") + } else { + $cache_gd_version[1] = $gd_info['GD Version']; // e.g. "1.6.2 or higher" + $cache_gd_version[0] = (float) substr($gd_info['GD Version'], 0, 3); // e.g. "1.6" (not "1.6.2 or higher") + } + } + return $cache_gd_version[intval($fullstring)]; + } + + + function gd_ImageSaveAlpha(&$img, $flag) { + // requires PHP >= 4.3.2 + // requires GD >= 2.0.1 + if (function_exists('ImageSaveAlpha')) { + return ImageSaveAlpha($img, $flag); + } + return false; + } + + function filesize_remote($remotefile, $timeout=10) { + $size = false; + $url = parse_url($remotefile); + if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) { + fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n"); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + stream_set_timeout($fp, $timeout); + } + while (!feof($fp)) { + $headerline = fgets($fp, 4096); + if (eregi('^Content-Length: (.*)', $headerline, $matches)) { + $size = intval($matches[1]); + break; + } + } + fclose ($fp); + } + return $size; + } + + + function filedate_remote($remotefile, $timeout=10) { + $date = false; + $url = parse_url($remotefile); + if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) { + fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n"); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + stream_set_timeout($fp, $timeout); + } + while (!feof($fp)) { + $headerline = fgets($fp, 4096); + if (eregi('^Last-Modified: (.*)', $headerline, $matches)) { + $date = strtotime($matches[1]) - date('Z'); + break; + } + } + fclose ($fp); + } + return $date; + } + + + function md5_file_safe($filename) { + // md5_file() doesn't exist in PHP < 4.2.0 + if (function_exists('md5_file')) { + return md5_file($filename); + } + if ($fp = @fopen($filename, 'rb')) { + $filedata = fread($fp, filesize($filename)); + fclose($fp); + return md5($filedata); + } + return false; + } + + + function nonempty_min() { + $arg_list = func_get_args(); + $acceptable = array(); + foreach ($arg_list as $dummy => $arg) { + if ($arg) { + $acceptable[] = $arg; + } + } + return min($acceptable); + } + + + function LittleEndian2String($number, $minbytes=1) { + $intstring = ''; + while ($number > 0) { + $intstring = $intstring.chr($number & 255); + $number >>= 8; + } + return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT); + } + + function OneOfThese() { + // return the first useful (non-empty/non-zero/non-false) value from those passed + $arg_list = func_get_args(); + foreach ($arg_list as $key => $value) { + if ($value) { + return $value; + } + } + return false; + } + + function SafeURLread($url, &$error) { + if (function_exists('curl_version')) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); + $rawData = curl_exec($ch); + curl_close($ch); + if (strlen($rawData) > 0) { + return $rawData; + } + $error .= 'CURL available but returned no data; '; + } else { + $error .= 'CURL unavailable; '; + } + if (@ini_get('allow_url_fopen')) { + $rawData = ''; + ob_start(); + if ($fp = fopen($url, 'rb')) { + do { + $buffer = fread($fp, 8192); + $rawData .= $buffer; + } while (strlen($buffer) > 0); + fclose($fp); + } else { + $error = trim(strip_tags(ob_get_contents())); + } + ob_end_clean(); + if (!$error) { + return $rawData; + } + $error .= '; "allow_url_fopen" enabled but returned no data; '; + } else { + $error .= '"allow_url_fopen" disabled; '; + } + return false; + } + +} + + +if (!function_exists('gd_info')) { + // built into PHP v4.3.0+ (with bundled GD2 library) + function gd_info() { + static $gd_info = array(); + if (empty($gd_info)) { + // based on code by johnschaefer at gmx dot de + // from PHP help on gd_info() + $gd_info = array( + 'GD Version' => '', + 'FreeType Support' => false, + 'FreeType Linkage' => '', + 'T1Lib Support' => false, + 'GIF Read Support' => false, + 'GIF Create Support' => false, + 'JPG Support' => false, + 'PNG Support' => false, + 'WBMP Support' => false, + 'XBM Support' => false + ); + $phpinfo_array = phpthumb_functions::phpinfo_array(); + foreach ($phpinfo_array as $dummy => $line) { + $line = trim(strip_tags($line)); + foreach ($gd_info as $key => $value) { + //if (strpos($line, $key) !== false) { + if (strpos($line, $key) === 0) { + $newvalue = trim(str_replace($key, '', $line)); + $gd_info[$key] = $newvalue; + } + } + } + if (empty($gd_info['GD Version'])) { + // probable cause: "phpinfo() disabled for security reasons" + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_PNG) { + $gd_info['PNG Support'] = true; + } + if ($imagetypes & IMG_GIF) { + $gd_info['GIF Create Support'] = true; + } + if ($imagetypes & IMG_JPG) { + $gd_info['JPG Support'] = true; + } + if ($imagetypes & IMG_WBMP) { + $gd_info['WBMP Support'] = true; + } + } + // to determine capability of GIF creation, try to use ImageCreateFromGIF on a 1px GIF + if (function_exists('ImageCreateFromGIF')) { + if ($tempfilename = phpthumb::phpThumb_tempnam()) { + if ($fp_tempfile = @fopen($tempfilename, 'wb')) { + fwrite($fp_tempfile, base64_decode('R0lGODlhAQABAIAAAH//AP///ywAAAAAAQABAAACAUQAOw==')); // very simple 1px GIF file base64-encoded as string + fclose($fp_tempfile); + + // if we can convert the GIF file to a GD image then GIF create support must be enabled, otherwise it's not + $gd_info['GIF Read Support'] = (bool) @ImageCreateFromGIF($tempfilename); + } + unlink($tempfilename); + } + } + if (function_exists('ImageCreateTrueColor') && @ImageCreateTrueColor(1, 1)) { + $gd_info['GD Version'] = '2.0.1 or higher (assumed)'; + } elseif (function_exists('ImageCreate') && @ImageCreate(1, 1)) { + $gd_info['GD Version'] = '1.6.0 or higher (assumed)'; + } + } + } + return $gd_info; + } +} + + +if (!function_exists('is_executable')) { + // in PHP v3+, but v5.0+ for Windows + function is_executable($filename) { + // poor substitute, but better than nothing + return file_exists($filename); + } +} + + +if (!function_exists('file_get_contents')) { + // included in PHP v4.3.0+ + function file_get_contents($filename) { + if (eregi('^(f|ht)tp\://', $filename)) { + return SafeURLread($filename); + } + if ($fp = @fopen($filename, 'rb')) { + $buffer = fread($fp, filesize($filename)); + fclose($fp); + return $buffer; + } + return false; + } +} + + +if (!function_exists('file_put_contents')) { + // included in PHP v5.0.0+ + function file_put_contents($filename, $filedata) { + if ($fp = @fopen($filename, 'wb')) { + fwrite($fp, $filedata); + fclose($fp); + return true; + } + return false; + } +} + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/phpthumb.gif.php b/site/racecalendar/phpthumb/phpthumb.gif.php new file mode 100644 index 0000000..e928594 --- /dev/null +++ b/site/racecalendar/phpthumb/phpthumb.gif.php @@ -0,0 +1,1168 @@ + = gif_loadFile(filename, [index]) +// = gif_getSize( or filename, &width, &height) +// = gif_outputAsPng(, filename, [bgColor]) +// = gif_outputAsBmp(, filename, [bgcolor]) +// = gif_outputAsJpeg(, filename, [bgcolor]) - use cjpeg if available otherwise uses GD +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Original code by Fabien Ezber +// Modified by James Heinrich for use in phpThumb() - December 10, 2003 +// * Added function gif_loadFileToGDimageResource() - this returns a GD image resource +// * Modified gif_outputAsJpeg() to check if it's running under Windows, or if cjpeg is not +// available, in which case it will attempt to output JPEG using GD functions +// * added @ error-suppression to two lines where it checks: if ($this->m_img->m_bTrans) +// otherwise warnings are generated if error_reporting == E_ALL +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_loadFile($lpszFileName, $iIndex = 0) +{ + $gif = new CGIF(); + if ($gif->loadFile($lpszFileName, $iIndex)) { + return $gif; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// Added by James Heinrich - December 10, 2003 +function gif_loadFileToGDimageResource($gifFilename, $bgColor = -1) +{ + if ($gif = gif_loadFile($gifFilename)) { + + @set_time_limit(300); + // general strategy: convert raw data to PNG then convert PNG data to GD image resource + $PNGdata = $gif->getPng($bgColor); + if ($img = @ImageCreateFromString($PNGdata)) { + + // excellent - PNG image data successfully converted to GD image + return $img; + + } elseif ($img = $gif->getGD_PixelPlotterVersion()) { + + // problem: ImageCreateFromString() didn't like the PNG image data. + // This has been known to happen in PHP v4.0.6 + // solution: take the raw image data and create a new GD image and plot + // pixel-by-pixel on the GD image. This is extremely slow, but it does + // work and a slow solution is better than no solution, right? :) + return $img; + + } + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsBmp($gif, $lpszFileName, $bgColor = -1) +{ + if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) { + return false; + } + + $fd = $gif->getBmp($bgColor); + if (strlen($fd) <= 0) { + return false; + } + + if (!($fh = @fopen($lpszFileName, 'wb'))) { + return false; + } + @fwrite($fh, $fd, strlen($fd)); + @fflush($fh); + @fclose($fh); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsPng($gif, $lpszFileName, $bgColor = -1) +{ + if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) { + return false; + } + + $fd = $gif->getPng($bgColor); + if (strlen($fd) <= 0) { + return false; + } + + if (!($fh = @fopen($lpszFileName, 'wb'))) { + return false; + } + @fwrite($fh, $fd, strlen($fd)); + @fflush($fh); + @fclose($fh); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsJpeg($gif, $lpszFileName, $bgColor = -1) +{ + // JPEG output that does not require cjpeg added by James Heinrich - December 10, 2003 + if ((strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') && (file_exists('/usr/local/bin/cjpeg') || `which cjpeg`)) { + + if (gif_outputAsBmp($gif, $lpszFileName.'.bmp', $bgColor)) { + exec('cjpeg '.$lpszFileName.'.bmp >'.$lpszFileName.' 2>/dev/null'); + @unLink($lpszFileName.'.bmp'); + + if (@file_exists($lpszFileName)) { + if (@fileSize($lpszFileName) > 0) { + return true; + } + + @unLink($lpszFileName); + } + } + + } else { + + // either Windows, or cjpeg not found in path + if ($img = @ImageCreateFromString($gif->getPng($bgColor))) { + if (@ImageJPEG($img, $lpszFileName)) { + return true; + } + } + + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_getSize($gif, &$width, &$height) +{ + if (isSet($gif) && (@get_class($gif) == 'cgif') && $gif->loaded()) { + $width = $gif->width(); + $height = $gif->height(); + } elseif (@file_exists($gif)) { + $myGIF = new CGIF(); + if (!$myGIF->getSize($gif, $width, $height)) { + return false; + } + } else { + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFLZW +{ + var $MAX_LZW_BITS; + var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode; + var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFLZW() + { + $this->MAX_LZW_BITS = 12; + unSet($this->Next); + unSet($this->Vals); + unSet($this->Stack); + unSet($this->Buf); + + $this->Next = range(0, (1 << $this->MAX_LZW_BITS) - 1); + $this->Vals = range(0, (1 << $this->MAX_LZW_BITS) - 1); + $this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1); + $this->Buf = range(0, 279); + } + + /////////////////////////////////////////////////////////////////////////// + + function deCompress($data, &$datLen) + { + $stLen = strlen($data); + $datLen = 0; + $ret = ''; + + // INITIALIZATION + $this->LZWCommand($data, true); + + while (($iIndex = $this->LZWCommand($data, false)) >= 0) { + $ret .= chr($iIndex); + } + + $datLen = $stLen - strlen($data); + + if ($iIndex != -2) { + return false; + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function LZWCommand(&$data, $bInit) + { + if ($bInit) { + $this->SetCodeSize = ord($data{0}); + $data = substr($data, 1); + + $this->CodeSize = $this->SetCodeSize + 1; + $this->ClearCode = 1 << $this->SetCodeSize; + $this->EndCode = $this->ClearCode + 1; + $this->MaxCode = $this->ClearCode + 2; + $this->MaxCodeSize = $this->ClearCode << 1; + + $this->GetCode($data, $bInit); + + $this->Fresh = 1; + for ($i = 0; $i < $this->ClearCode; $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = $i; + } + + for (; $i < (1 << $this->MAX_LZW_BITS); $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = 0; + } + + $this->sp = 0; + return 1; + } + + if ($this->Fresh) { + $this->Fresh = 0; + do { + $this->FirstCode = $this->GetCode($data, $bInit); + $this->OldCode = $this->FirstCode; + } + while ($this->FirstCode == $this->ClearCode); + + return $this->FirstCode; + } + + if ($this->sp > 0) { + $this->sp--; + return $this->Stack[$this->sp]; + } + + while (($Code = $this->GetCode($data, $bInit)) >= 0) { + if ($Code == $this->ClearCode) { + for ($i = 0; $i < $this->ClearCode; $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = $i; + } + + for (; $i < (1 << $this->MAX_LZW_BITS); $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = 0; + } + + $this->CodeSize = $this->SetCodeSize + 1; + $this->MaxCodeSize = $this->ClearCode << 1; + $this->MaxCode = $this->ClearCode + 2; + $this->sp = 0; + $this->FirstCode = $this->GetCode($data, $bInit); + $this->OldCode = $this->FirstCode; + + return $this->FirstCode; + } + + if ($Code == $this->EndCode) { + return -2; + } + + $InCode = $Code; + if ($Code >= $this->MaxCode) { + $this->Stack[$this->sp] = $this->FirstCode; + $this->sp++; + $Code = $this->OldCode; + } + + while ($Code >= $this->ClearCode) { + $this->Stack[$this->sp] = $this->Vals[$Code]; + $this->sp++; + + if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error! + return -1; + + $Code = $this->Next[$Code]; + } + + $this->FirstCode = $this->Vals[$Code]; + $this->Stack[$this->sp] = $this->FirstCode; + $this->sp++; + + if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) { + $this->Next[$Code] = $this->OldCode; + $this->Vals[$Code] = $this->FirstCode; + $this->MaxCode++; + + if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) { + $this->MaxCodeSize *= 2; + $this->CodeSize++; + } + } + + $this->OldCode = $InCode; + if ($this->sp > 0) { + $this->sp--; + return $this->Stack[$this->sp]; + } + } + + return $Code; + } + + /////////////////////////////////////////////////////////////////////////// + + function GetCode(&$data, $bInit) + { + if ($bInit) { + $this->CurBit = 0; + $this->LastBit = 0; + $this->Done = 0; + $this->LastByte = 2; + return 1; + } + + if (($this->CurBit + $this->CodeSize) >= $this->LastBit) { + if ($this->Done) { + if ($this->CurBit >= $this->LastBit) { + // Ran off the end of my bits + return 0; + } + return -1; + } + + $this->Buf[0] = $this->Buf[$this->LastByte - 2]; + $this->Buf[1] = $this->Buf[$this->LastByte - 1]; + + $Count = ord($data{0}); + $data = substr($data, 1); + + if ($Count) { + for ($i = 0; $i < $Count; $i++) { + $this->Buf[2 + $i] = ord($data{$i}); + } + $data = substr($data, $Count); + } else { + $this->Done = 1; + } + + $this->LastByte = 2 + $Count; + $this->CurBit = ($this->CurBit - $this->LastBit) + 16; + $this->LastBit = (2 + $Count) << 3; + } + + $iRet = 0; + for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) { + $iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j; + } + + $this->CurBit += $this->CodeSize; + return $iRet; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFCOLORTABLE +{ + var $m_nColors; + var $m_arColors; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFCOLORTABLE() + { + unSet($this->m_nColors); + unSet($this->m_arColors); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, $num) + { + $this->m_nColors = 0; + $this->m_arColors = array(); + + for ($i = 0; $i < $num; $i++) { + $rgb = substr($lpData, $i * 3, 3); + if (strlen($rgb) < 3) { + return false; + } + + $this->m_arColors[] = (ord($rgb{2}) << 16) + (ord($rgb{1}) << 8) + ord($rgb{0}); + $this->m_nColors++; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function toString() + { + $ret = ''; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $ret .= + chr(($this->m_arColors[$i] & 0x000000FF)) . // R + chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G + chr(($this->m_arColors[$i] & 0x00FF0000) >> 16); // B + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function toRGBQuad() + { + $ret = ''; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $ret .= + chr(($this->m_arColors[$i] & 0x00FF0000) >> 16) . // B + chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G + chr(($this->m_arColors[$i] & 0x000000FF)) . // R + "\x00"; + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function colorIndex($rgb) + { + $rgb = intval($rgb) & 0xFFFFFF; + $r1 = ($rgb & 0x0000FF); + $g1 = ($rgb & 0x00FF00) >> 8; + $b1 = ($rgb & 0xFF0000) >> 16; + $idx = -1; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $r2 = ($this->m_arColors[$i] & 0x000000FF); + $g2 = ($this->m_arColors[$i] & 0x0000FF00) >> 8; + $b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16; + $d = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1); + + if (($idx == -1) || ($d < $dif)) { + $idx = $i; + $dif = $d; + } + } + + return $idx; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFFILEHEADER +{ + var $m_lpVer; + var $m_nWidth; + var $m_nHeight; + var $m_bGlobalClr; + var $m_nColorRes; + var $m_bSorted; + var $m_nTableSize; + var $m_nBgColor; + var $m_nPixelRatio; + var $m_colorTable; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFFILEHEADER() + { + unSet($this->m_lpVer); + unSet($this->m_nWidth); + unSet($this->m_nHeight); + unSet($this->m_bGlobalClr); + unSet($this->m_nColorRes); + unSet($this->m_bSorted); + unSet($this->m_nTableSize); + unSet($this->m_nBgColor); + unSet($this->m_nPixelRatio); + unSet($this->m_colorTable); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, &$hdrLen) + { + $hdrLen = 0; + + $this->m_lpVer = substr($lpData, 0, 6); + if (($this->m_lpVer <> 'GIF87a') && ($this->m_lpVer <> 'GIF89a')) { + return false; + } + + $this->m_nWidth = $this->w2i(substr($lpData, 6, 2)); + $this->m_nHeight = $this->w2i(substr($lpData, 8, 2)); + if (!$this->m_nWidth || !$this->m_nHeight) { + return false; + } + + $b = ord(substr($lpData, 10, 1)); + $this->m_bGlobalClr = ($b & 0x80) ? true : false; + $this->m_nColorRes = ($b & 0x70) >> 4; + $this->m_bSorted = ($b & 0x08) ? true : false; + $this->m_nTableSize = 2 << ($b & 0x07); + $this->m_nBgColor = ord(substr($lpData, 11, 1)); + $this->m_nPixelRatio = ord(substr($lpData, 12, 1)); + $hdrLen = 13; + + if ($this->m_bGlobalClr) { + $this->m_colorTable = new CGIFCOLORTABLE(); + if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) { + return false; + } + $hdrLen += 3 * $this->m_nTableSize; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFIMAGEHEADER +{ + var $m_nLeft; + var $m_nTop; + var $m_nWidth; + var $m_nHeight; + var $m_bLocalClr; + var $m_bInterlace; + var $m_bSorted; + var $m_nTableSize; + var $m_colorTable; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFIMAGEHEADER() + { + unSet($this->m_nLeft); + unSet($this->m_nTop); + unSet($this->m_nWidth); + unSet($this->m_nHeight); + unSet($this->m_bLocalClr); + unSet($this->m_bInterlace); + unSet($this->m_bSorted); + unSet($this->m_nTableSize); + unSet($this->m_colorTable); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, &$hdrLen) + { + $hdrLen = 0; + + $this->m_nLeft = $this->w2i(substr($lpData, 0, 2)); + $this->m_nTop = $this->w2i(substr($lpData, 2, 2)); + $this->m_nWidth = $this->w2i(substr($lpData, 4, 2)); + $this->m_nHeight = $this->w2i(substr($lpData, 6, 2)); + + if (!$this->m_nWidth || !$this->m_nHeight) { + return false; + } + + $b = ord($lpData{8}); + $this->m_bLocalClr = ($b & 0x80) ? true : false; + $this->m_bInterlace = ($b & 0x40) ? true : false; + $this->m_bSorted = ($b & 0x20) ? true : false; + $this->m_nTableSize = 2 << ($b & 0x07); + $hdrLen = 9; + + if ($this->m_bLocalClr) { + $this->m_colorTable = new CGIFCOLORTABLE(); + if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) { + return false; + } + $hdrLen += 3 * $this->m_nTableSize; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFIMAGE +{ + var $m_disp; + var $m_bUser; + var $m_bTrans; + var $m_nDelay; + var $m_nTrans; + var $m_lpComm; + var $m_gih; + var $m_data; + var $m_lzw; + + /////////////////////////////////////////////////////////////////////////// + + function CGIFIMAGE() + { + unSet($this->m_disp); + unSet($this->m_bUser); + unSet($this->m_bTrans); + unSet($this->m_nDelay); + unSet($this->m_nTrans); + unSet($this->m_lpComm); + unSet($this->m_data); + $this->m_gih = new CGIFIMAGEHEADER(); + $this->m_lzw = new CGIFLZW(); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($data, &$datLen) + { + $datLen = 0; + + while (true) { + $b = ord($data{0}); + $data = substr($data, 1); + $datLen++; + + switch($b) { + case 0x21: // Extension + if (!$this->skipExt($data, $len = 0)) { + return false; + } + $datLen += $len; + break; + + case 0x2C: // Image + // LOAD HEADER & COLOR TABLE + if (!$this->m_gih->load($data, $len = 0)) { + return false; + } + $data = substr($data, $len); + $datLen += $len; + + // ALLOC BUFFER + if (!($this->m_data = $this->m_lzw->deCompress($data, $len = 0))) { + return false; + } + $data = substr($data, $len); + $datLen += $len; + + if ($this->m_gih->m_bInterlace) { + $this->deInterlace(); + } + return true; + + case 0x3B: // EOF + default: + return false; + } + } + return false; + } + + /////////////////////////////////////////////////////////////////////////// + + function skipExt(&$data, &$extLen) + { + $extLen = 0; + + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + + switch($b) { + case 0xF9: // Graphic Control + $b = ord($data{1}); + $this->m_disp = ($b & 0x1C) >> 2; + $this->m_bUser = ($b & 0x02) ? true : false; + $this->m_bTrans = ($b & 0x01) ? true : false; + $this->m_nDelay = $this->w2i(substr($data, 2, 2)); + $this->m_nTrans = ord($data{4}); + break; + + case 0xFE: // Comment + $this->m_lpComm = substr($data, 1, ord($data{0})); + break; + + case 0x01: // Plain text + break; + + case 0xFF: // Application + break; + } + + // SKIP DEFAULT AS DEFS MAY CHANGE + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + while ($b > 0) { + $data = substr($data, $b); + $extLen += $b; + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + } + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } + + /////////////////////////////////////////////////////////////////////////// + + function deInterlace() + { + $data = $this->m_data; + + for ($i = 0; $i < 4; $i++) { + switch($i) { + case 0: + $s = 8; + $y = 0; + break; + + case 1: + $s = 8; + $y = 4; + break; + + case 2: + $s = 4; + $y = 2; + break; + + case 3: + $s = 2; + $y = 1; + break; + } + + for (; $y < $this->m_gih->m_nHeight; $y += $s) { + $lne = substr($this->m_data, 0, $this->m_gih->m_nWidth); + $this->m_data = substr($this->m_data, $this->m_gih->m_nWidth); + + $data = + substr($data, 0, $y * $this->m_gih->m_nWidth) . + $lne . + substr($data, ($y + 1) * $this->m_gih->m_nWidth); + } + } + + $this->m_data = $data; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIF +{ + var $m_gfh; + var $m_lpData; + var $m_img; + var $m_bLoaded; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIF() + { + $this->m_gfh = new CGIFFILEHEADER(); + $this->m_img = new CGIFIMAGE(); + $this->m_lpData = ''; + $this->m_bLoaded = false; + } + + /////////////////////////////////////////////////////////////////////////// + + function loadFile($lpszFileName, $iIndex) + { + if ($iIndex < 0) { + return false; + } + + // READ FILE + if (!($fh = @fopen($lpszFileName, 'rb'))) { + return false; + } + $this->m_lpData = @fRead($fh, @fileSize($lpszFileName)); + fclose($fh); + + // GET FILE HEADER + if (!$this->m_gfh->load($this->m_lpData, $len = 0)) { + return false; + } + $this->m_lpData = substr($this->m_lpData, $len); + + do { + if (!$this->m_img->load($this->m_lpData, $imgLen = 0)) { + return false; + } + $this->m_lpData = substr($this->m_lpData, $imgLen); + } + while ($iIndex-- > 0); + + $this->m_bLoaded = true; + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function getSize($lpszFileName, &$width, &$height) + { + if (!($fh = @fopen($lpszFileName, 'rb'))) { + return false; + } + $data = @fRead($fh, @fileSize($lpszFileName)); + @fclose($fh); + + $gfh = new CGIFFILEHEADER(); + if (!$gfh->load($data, $len = 0)) { + return false; + } + + $width = $gfh->m_nWidth; + $height = $gfh->m_nHeight; + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function getBmp($bgColor) + { + $out = ''; + + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $nColors = $this->m_img->m_gih->m_nTableSize; + $rgbq = $this->m_img->m_gih->m_colorTable->toRGBQuad(); + if ($bgColor != -1) { + $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor); + } + } elseif ($this->m_gfh->m_bGlobalClr) { + $nColors = $this->m_gfh->m_nTableSize; + $rgbq = $this->m_gfh->m_colorTable->toRGBQuad(); + if ($bgColor != -1) { + $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor); + } + } else { + $nColors = 0; + $bgColor = -1; + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth; + $bmp = ''; + $nPad = ($this->m_gfh->m_nWidth % 4) ? 4 - ($this->m_gfh->m_nWidth % 4) : 0; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) { + // TRANSPARENT -> BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } else { + $bmp .= $data{$nPxl}; + } + } else { + // BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } + } + $nPxl -= $this->m_gfh->m_nWidth << 1; + + // ADD PADDING + for ($x = 0; $x < $nPad; $x++) { + $bmp .= "\x00"; + } + } + + // BITMAPFILEHEADER + $out .= 'BM'; + $out .= $this->dword(14 + 40 + ($nColors << 2) + strlen($bmp)); + $out .= "\x00\x00"; + $out .= "\x00\x00"; + $out .= $this->dword(14 + 40 + ($nColors << 2)); + + // BITMAPINFOHEADER + $out .= $this->dword(40); + $out .= $this->dword($this->m_gfh->m_nWidth); + $out .= $this->dword($this->m_gfh->m_nHeight); + $out .= "\x01\x00"; + $out .= "\x08\x00"; + $out .= "\x00\x00\x00\x00"; + $out .= "\x00\x00\x00\x00"; + $out .= "\x12\x0B\x00\x00"; + $out .= "\x12\x0B\x00\x00"; + $out .= $this->dword($nColors % 256); + $out .= "\x00\x00\x00\x00"; + + // COLOR TABLE + if ($nColors > 0) { + $out .= $rgbq; + } + + // DATA + $out .= $bmp; + + return $out; + } + + /////////////////////////////////////////////////////////////////////////// + + function getPng($bgColor) + { + $out = ''; + + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $nColors = $this->m_img->m_gih->m_nTableSize; + $pal = $this->m_img->m_gih->m_colorTable->toString(); + if ($bgColor != -1) { + $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor); + } + } elseif ($this->m_gfh->m_bGlobalClr) { + $nColors = $this->m_gfh->m_nTableSize; + $pal = $this->m_gfh->m_colorTable->toString(); + if ($bgColor != -1) { + $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor); + } + } else { + $nColors = 0; + $bgColor = -1; + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = 0; + $bmp = ''; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + $bmp .= "\x00"; + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + $bmp .= $data{$nPxl}; + } else { + // BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } + } + } + $bmp = gzcompress($bmp, 9); + + /////////////////////////////////////////////////////////////////////// + // SIGNATURE + $out .= "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; + /////////////////////////////////////////////////////////////////////// + // HEADER + $out .= "\x00\x00\x00\x0D"; + $tmp = 'IHDR'; + $tmp .= $this->ndword($this->m_gfh->m_nWidth); + $tmp .= $this->ndword($this->m_gfh->m_nHeight); + $tmp .= "\x08\x03\x00\x00\x00"; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + /////////////////////////////////////////////////////////////////////// + // PALETTE + if ($nColors > 0) { + $out .= $this->ndword($nColors * 3); + $tmp = 'PLTE'; + $tmp .= $pal; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + } + /////////////////////////////////////////////////////////////////////// + // TRANSPARENCY + if (@$this->m_img->m_bTrans && ($nColors > 0)) { + $out .= $this->ndword($nColors); + $tmp = 'tRNS'; + for ($i = 0; $i < $nColors; $i++) { + $tmp .= ($i == $this->m_img->m_nTrans) ? "\x00" : "\xFF"; + } + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + } + /////////////////////////////////////////////////////////////////////// + // DATA BITS + $out .= $this->ndword(strlen($bmp)); + $tmp = 'IDAT'; + $tmp .= $bmp; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + /////////////////////////////////////////////////////////////////////// + // END OF FILE + $out .= "\x00\x00\x00\x00IEND\xAE\x42\x60\x82"; + + return $out; + } + + /////////////////////////////////////////////////////////////////////////// + + // Added by James Heinrich - January 5, 2003 + + // Takes raw image data and plots it pixel-by-pixel on a new GD image and returns that + // It's extremely slow, but the only solution when ImageCreateFromString() fails + function getGD_PixelPlotterVersion() + { + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $pal = $this->m_img->m_gih->m_colorTable->toString(); + } elseif ($this->m_gfh->m_bGlobalClr) { + $pal = $this->m_gfh->m_colorTable->toString(); + } else { + die('No color table available in getGD_PixelPlotterVersion()'); + } + + $PlottingIMG = ImageCreate($this->m_gfh->m_nWidth, $this->m_gfh->m_nHeight); + $NumColorsInPal = floor(strlen($pal) / 3); + for ($i = 0; $i < $NumColorsInPal; $i++) { + $ThisImageColor[$i] = ImageColorAllocate( + $PlottingIMG, + ord($pal{(($i * 3) + 0)}), + ord($pal{(($i * 3) + 1)}), + ord($pal{(($i * 3) + 2)})); + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + set_time_limit(30); + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) { + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]); + } else { + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[ord($data{$nPxl})]); + } + } else { + // BACKGROUND + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]); + } + } + $nPxl -= $this->m_gfh->m_nWidth << 1; + + } + + return $PlottingIMG; + } + + /////////////////////////////////////////////////////////////////////////// + + function dword($val) + { + $val = intval($val); + return chr($val & 0xFF).chr(($val & 0xFF00) >> 8).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF000000) >> 24); + } + + /////////////////////////////////////////////////////////////////////////// + + function ndword($val) + { + $val = intval($val); + return chr(($val & 0xFF000000) >> 24).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF00) >> 8).chr($val & 0xFF); + } + + /////////////////////////////////////////////////////////////////////////// + + function width() + { + return $this->m_gfh->m_nWidth; + } + + /////////////////////////////////////////////////////////////////////////// + + function height() + { + return $this->m_gfh->m_nHeight; + } + + /////////////////////////////////////////////////////////////////////////// + + function comment() + { + return $this->m_img->m_lpComm; + } + + /////////////////////////////////////////////////////////////////////////// + + function loaded() + { + return $this->m_bLoaded; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/phpthumb.ico.php b/site/racecalendar/phpthumb/phpthumb.ico.php new file mode 100644 index 0000000..aed7214 --- /dev/null +++ b/site/racecalendar/phpthumb/phpthumb.ico.php @@ -0,0 +1,119 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.ico.php - .ICO output format functions // +// /// +////////////////////////////////////////////////////////////// + + +class phpthumb_ico { + + function phpthumb_ico() { + return true; + } + + + function GD2ICOstring(&$gd_image_array) { + foreach ($gd_image_array as $key => $gd_image) { + + $ImageWidths[$key] = ImageSX($gd_image); + $ImageHeights[$key] = ImageSY($gd_image); + $bpp[$key] = ImageIsTrueColor($gd_image) ? 32 : 24; + $totalcolors[$key] = ImageColorsTotal($gd_image); + + $icXOR[$key] = ''; + for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) { + for ($x = 0; $x < $ImageWidths[$key]; $x++) { + $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); + $a = round(255 * ((127 - $argb['alpha']) / 127)); + $r = $argb['red']; + $g = $argb['green']; + $b = $argb['blue']; + + if ($bpp[$key] == 32) { + $icXOR[$key] .= chr($b).chr($g).chr($r).chr($a); + } elseif ($bpp[$key] == 24) { + $icXOR[$key] .= chr($b).chr($g).chr($r); + } + + if ($a < 128) { + @$icANDmask[$key][$y] .= '1'; + } else { + @$icANDmask[$key][$y] .= '0'; + } + } + // mask bits are 32-bit aligned per scanline + while (strlen($icANDmask[$key][$y]) % 32) { + $icANDmask[$key][$y] .= '0'; + } + } + $icAND[$key] = ''; + foreach ($icANDmask[$key] as $y => $scanlinemaskbits) { + for ($i = 0; $i < strlen($scanlinemaskbits); $i += 8) { + $icAND[$key] .= chr(bindec(str_pad(substr($scanlinemaskbits, $i, 8), 8, '0', STR_PAD_LEFT))); + } + } + + } + + foreach ($gd_image_array as $key => $gd_image) { + $biSizeImage = $ImageWidths[$key] * $ImageHeights[$key] * ($bpp[$key] / 8); + + // BITMAPINFOHEADER - 40 bytes + $BitmapInfoHeader[$key] = ''; + $BitmapInfoHeader[$key] .= "\x28\x00\x00\x00"; // DWORD biSize; + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageWidths[$key], 4); // LONG biWidth; + // The biHeight member specifies the combined + // height of the XOR and AND masks. + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageHeights[$key] * 2, 4); // LONG biHeight; + $BitmapInfoHeader[$key] .= "\x01\x00"; // WORD biPlanes; + $BitmapInfoHeader[$key] .= chr($bpp[$key])."\x00"; // wBitCount; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biCompression; + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($biSizeImage, 4); // DWORD biSizeImage; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biXPelsPerMeter; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biYPelsPerMeter; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrUsed; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrImportant; + } + + + $icondata = "\x00\x00"; // idReserved; // Reserved (must be 0) + $icondata .= "\x01\x00"; // idType; // Resource Type (1 for icons) + $icondata .= phpthumb_functions::LittleEndian2String(count($gd_image_array), 2); // idCount; // How many images? + + $dwImageOffset = 6 + (count($gd_image_array) * 16); + foreach ($gd_image_array as $key => $gd_image) { + // ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) + + $icondata .= chr($ImageWidths[$key]); // bWidth; // Width, in pixels, of the image + $icondata .= chr($ImageHeights[$key]); // bHeight; // Height, in pixels, of the image + $icondata .= chr($totalcolors[$key]); // bColorCount; // Number of colors in image (0 if >=8bpp) + $icondata .= "\x00"; // bReserved; // Reserved ( must be 0) + + $icondata .= "\x01\x00"; // wPlanes; // Color Planes + $icondata .= chr($bpp[$key])."\x00"; // wBitCount; // Bits per pixel + + $dwBytesInRes = 40 + strlen($icXOR[$key]) + strlen($icAND[$key]); + $icondata .= phpthumb_functions::LittleEndian2String($dwBytesInRes, 4); // dwBytesInRes; // How many bytes in this resource? + + $icondata .= phpthumb_functions::LittleEndian2String($dwImageOffset, 4); // dwImageOffset; // Where in the file is this image? + $dwImageOffset += strlen($BitmapInfoHeader[$key]); + $dwImageOffset += strlen($icXOR[$key]); + $dwImageOffset += strlen($icAND[$key]); + } + + foreach ($gd_image_array as $key => $gd_image) { + $icondata .= $BitmapInfoHeader[$key]; + $icondata .= $icXOR[$key]; + $icondata .= $icAND[$key]; + } + + return $icondata; + } + +} + +?> \ No newline at end of file diff --git a/site/racecalendar/phpthumb/phpthumb.unsharp.php b/site/racecalendar/phpthumb/phpthumb.unsharp.php new file mode 100644 index 0000000..799b5cd --- /dev/null +++ b/site/racecalendar/phpthumb/phpthumb.unsharp.php @@ -0,0 +1,162 @@ + // +// for use in phpThumb() on 3 February 2003. // +// // +// phpThumb() is found at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// + +/* +WARNING! Due to a known bug in PHP 4.3.2 this script is not working well in this version. +The sharpened images get too dark. The bug is fixed in version 4.3.3. + +Unsharp masking is a traditional darkroom technique that has proven very suitable for +digital imaging. The principle of unsharp masking is to create a blurred copy of the image +and compare it to the underlying original. The difference in colour values +between the two images is greatest for the pixels near sharp edges. When this +difference is subtracted from the original image, the edges will be +accentuated. + +The Amount parameter simply says how much of the effect you want. 100 is 'normal'. +Radius is the radius of the blurring circle of the mask. 'Threshold' is the least +difference in colour values that is allowed between the original and the mask. In practice +this means that low-contrast areas of the picture are left unrendered whereas edges +are treated normally. This is good for pictures of e.g. skin or blue skies. + +Any suggenstions for improvement of the algorithm, expecially regarding the speed +and the roundoff errors in the Gaussian blur process, are welcome. +*/ + +class phpUnsharpMask { + + function applyUnsharpMask(&$img, $amount, $radius, $threshold) { + + // $img is an image that is already created within php using + // imgcreatetruecolor. No url! $img must be a truecolor image. + + // Attempt to calibrate the parameters to Photoshop: + $amount = min($amount, 500); + $amount = $amount * 0.016; + if ($amount == 0) { + return true; + } + + $radius = min($radius, 50); + $radius = $radius * 2; + + $threshold = min($threshold, 255); + + $radius = abs(round($radius)); // Only integers make sense. + if ($radius == 0) { + return true; + } + + $w = ImageSX($img); + $h = ImageSY($img); + $imgCanvas = ImageCreateTrueColor($w, $h); + $imgCanvas2 = ImageCreateTrueColor($w, $h); + ImageCopy($imgCanvas, $img, 0, 0, 0, 0, $w, $h); + ImageCopy($imgCanvas2, $img, 0, 0, 0, 0, $w, $h); + + + $builtinFilterSucceeded = false; + if ($radius == 1) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($imgCanvas, IMG_FILTER_GAUSSIAN_BLUR) && ImageFilter($imgCanvas2, IMG_FILTER_GAUSSIAN_BLUR)) { + $builtinFilterSucceeded = true; + } + } + } + + if (!$builtinFilterSucceeded) { + $imgBlur = ImageCreateTrueColor($w, $h); + $imgBlur2 = ImageCreateTrueColor($w, $h); + + /////////////////////////// + // + // Gaussian blur matrix: + // 1 2 1 + // 2 4 2 + // 1 2 1 + // + /////////////////////////// + + // Move copies of the image around one pixel at the time and merge them with weight + // according to the matrix. The same matrix is simply repeated for higher radii. + for ($i = 0; $i < $radius; $i++) { + ImageCopy ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20 ); // up + ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center + ImageCopy ($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h); + + // During the loop above the blurred copy darkens, possibly due to a roundoff + // error. Therefore the sharp picture has to go through the same loop to + // produce a similar image for comparison. This is not a good thing, as processing + // time increases heavily. + ImageCopy ($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 20 ); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 16.666667); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); + ImageCopy ($imgCanvas2, $imgBlur2, 0, 0, 0, 0, $w, $h); + } + ImageDestroy($imgBlur); + ImageDestroy($imgBlur2); + } + + // Calculate the difference between the blurred pixels and the original + // and set the pixels + for ($x = 0; $x < $w; $x++) { // each row + for ($y = 0; $y < $h; $y++) { // each pixel + + $rgbOrig = ImageColorAt($imgCanvas2, $x, $y); + $rOrig = (($rgbOrig >> 16) & 0xFF); + $gOrig = (($rgbOrig >> 8) & 0xFF); + $bOrig = ($rgbOrig & 0xFF); + + $rgbBlur = ImageColorAt($imgCanvas, $x, $y); + $rBlur = (($rgbBlur >> 16) & 0xFF); + $gBlur = (($rgbBlur >> 8) & 0xFF); + $bBlur = ($rgbBlur & 0xFF); + + // When the masked pixels differ less from the original + // than the threshold specifies, they are set to their original value. + $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig; + $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig; + $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig; + + if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) { + $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew); + ImageSetPixel($img, $x, $y, $pixCol); + } + } + } + ImageDestroy($imgCanvas); + ImageDestroy($imgCanvas2); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/site/racecalendar/pointlist.php b/site/racecalendar/pointlist.php new file mode 100644 index 0000000..58afa46 --- /dev/null +++ b/site/racecalendar/pointlist.php @@ -0,0 +1,145 @@ += 40 AND points < 100'; + $pointname = 'International'; +} elseif ($_GET[points] == 'mid') { + $where = 'points >= 100 AND points < 180'; + $pointname = 'Mid-Length'; +} elseif ($_GET[points] == 'ultra') { + $where = 'points >= 180'; + $pointname = 'Ultra'; +} else { + header('Location: https://slowtwitch.com/calendar/'); + exit(); +} + +/**Less than 40 points = sprint +40 points to 99 points = international +100 points to 179 points = mid +More than 180 points = ultra**/ + + +/*$results = mysql_query("SELECT gtr.regionlong, gt.onetype, gt.twotype, threetype, oneunit, twounit, threeunit, name, nametag, gt.statetag, swim, bike, run, city, state, uid, UNIX_TIMESTAMP(date) as fooFROM gforum_TriathlonsRegions WHERE gtr.regionid = ".intval(mysql_escape_string($_GET[region]))." LEFT JOIN gforum_TriathlonsStates AS gts ON gts.regionid = gtr.regionid LEFT JOIN gforum_Triathlons AS gt ON gt.statetag = gts.statetag AND valid=1 AND date > '2008-01-01' ORDER BY gt.date ASC");*/ + +$sql = "SELECT gt.onetype, gt.twotype, gt.threetype, gt.oneunit, gt.twounit, gt.threeunit, gt.name, gt.nametag, gt.statetag, gt.swim, gt.bike, gt.run, gt.city, gt.state, gt.uid, UNIX_TIMESTAMP(gt.date) as foo +FROM gforum_Triathlons AS gt +WHERE valid = 1 AND date > '".$min_date."' AND ".$where." ORDER BY gt.date ASC"; + +$results = mysql_query($sql); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} + +/*$results = mysql_query("SELECT onetype, twotype, threetype, oneunit, twounit, threeunit, name, nametag, statetag, swim, bike, run, city, state, uid, UNIX_TIMESTAMP(date) as foo FROM gforum_Triathlons RIGHT JOIN WHERE regionid='$_GET[region]' AND valid=1 AND date > '2008-01-01' ORDER BY date ASC");**/ + +// set the page title +$pagetitle = $pointname." Triathlons"; + +// set meta tags +$meta_keywords = $pointname." distance triathlons"; +$meta_description = "Trying to find triathlons or duathlons of ".$pointname." distance? Here is a listing of all ".$pointname." triathlons. Users can even rate and comment on races."; +?> + + + + + +
    + + +
    + + + + + +

    Triathlons

    +
    + + + +"> + +"> +"> + +"> + +"> + +

    ">
    +
    Description:
    + 400){ +$phrase = " (...)"; }else{ +$phrase = ""; } + +echo substr(stripslashes(stripslashes($row[courseinfo])), 0, 400); echo $phrase; ?> +
    +Location:
    +">More information +

    +
    + + +
    + +
    + + + + diff --git a/site/racecalendar/racetag_X.php b/site/racecalendar/racetag_X.php new file mode 100644 index 0000000..a0f129b --- /dev/null +++ b/site/racecalendar/racetag_X.php @@ -0,0 +1,103 @@ + + + + + + +
    + + +
    + + + + + +

    Clearing Race Tags…

    +
    +"; + +while($row = mysql_fetch_array($results)) { + // select users who are in the exploded tags + $tagresults = mysql_query("SELECT racetags FROM gforum_Triathlons WHERE uid=$row[uid]"); + $tagrow = mysql_fetch_array($tagresults); + $tags = explode(",", $tagrow[racetags]); + + // DEBUG: which UIDs are we processing + echo ("RACE_UID: ".$row[uid]."
    "); + + echo "
    Processing users…
    "; + foreach ($tags AS $temp_useruid) { + if ($temp_useruid != '') { + // DEBUG: which USERUID are we processing + echo ("USER_UID: ".$temp_useruid."
    "); + $profileresults = mysql_query("SELECT user_racetags FROM ".$prefix."User WHERE user_id='$temp_useruid'") or die(mysql_error()); + $profilerow = mysql_fetch_array($profileresults); + $profiletags = explode(",", $profilerow[user_racetags]); + + //clear the race from the users tags + $key = array_search($row[uid], $profiletags); + unset($profiletags[$key]); + $profiletags = implode(",", $profiletags); + mysql_query("UPDATE ".$prefix."User SET user_racetags='$profiletags' WHERE user_id=$temp_useruid"); + } + } + echo "
    "; + + //clear the race + mysql_query("UPDATE gforum_Triathlons SET racetags='' WHERE uid=$row[uid]") or die(mysql_error()); + + // increment the counter of races cleared + $tags_cleared = $tags_cleared + 1; +} + +echo "Done processing races.
    "; + +// DEBUG: how many tags were cleared +echo ("Racetags cleared: ".$tags_cleared."
    "); + +//header('Location: https://slowtwitch.com/calendar/?tags_cleared='.$tags_cleared.'.php'); + +?> + +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/site/racecalendar/rating-example.php b/site/racecalendar/rating-example.php new file mode 100644 index 0000000..6225023 --- /dev/null +++ b/site/racecalendar/rating-example.php @@ -0,0 +1,60 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

    Race Rating System:

    + + + + + \ No newline at end of file diff --git a/site/racecalendar/rating/ajax.rate.item.php b/site/racecalendar/rating/ajax.rate.item.php new file mode 100644 index 0000000..38c90de --- /dev/null +++ b/site/racecalendar/rating/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/racecalendar/rating/classes/database.class.php b/site/racecalendar/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/racecalendar/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/racecalendar/rating/classes/error.class.php b/site/racecalendar/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/racecalendar/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Error Template Output + $output = "
    \r\n" . + "
    {$error}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Warning Template Output + $output = "
    \r\n" . + "
    {$warning}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/racecalendar/rating/classes/include.all.php b/site/racecalendar/rating/classes/include.all.php new file mode 100644 index 0000000..2c1fa21 --- /dev/null +++ b/site/racecalendar/rating/classes/include.all.php @@ -0,0 +1,7 @@ + diff --git a/site/racecalendar/rating/classes/rating.class.php b/site/racecalendar/rating/classes/rating.class.php new file mode 100644 index 0000000..0461f59 --- /dev/null +++ b/site/racecalendar/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +
    {$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
    {$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
    Overall Rating
    "; + $output .= "
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    \r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_TriathlonsRating` (`rating_triathlon_id`, `rating_category_id`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_TriathlonsRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_TriathlonsRating` WHERE `rating_category_id`='{$varItem}' AND `rating_triathlon_id`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_TriathlonsRating` WHERE `rating_triathlon_id`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_TriathlonsRating` WHERE `rating_category_id`='{$varItem}' AND `rating_triathlon_id`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> diff --git a/site/racecalendar/rating/int.to.words.php b/site/racecalendar/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/racecalendar/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/racecalendar/rating/rating-example.php b/site/racecalendar/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/racecalendar/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

    Race Rating System:

    + + + + + + + \ No newline at end of file diff --git a/site/racecalendar/regionlist.php b/site/racecalendar/regionlist.php new file mode 100644 index 0000000..d9121aa --- /dev/null +++ b/site/racecalendar/regionlist.php @@ -0,0 +1,91 @@ + '2008-01-01' ORDER BY gt.date ASC");*/ + +$results = mysql_query("SELECT gt.onetype, gt.twotype, gt.threetype, gt.oneunit, gt.twounit, gt.threeunit, gt.name, gt.nametag, gt.statetag, gt.swim, gt.bike, gt.run, gt.city, gt.state, gt.uid, UNIX_TIMESTAMP(gt.date) as foo +FROM gforum_Triathlons AS gt +RIGHT JOIN gforum_TriathlonsStates AS gts +ON gts.regionid = '".intval(mysql_escape_string($_GET[region]))."' AND gt.statetag = gts.statetag +WHERE valid = 1 AND date > '".$min_date."' ORDER BY gt.date ASC"); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} + + + +/*$results = mysql_query("SELECT onetype, twotype, threetype, oneunit, twounit, threeunit, name, nametag, statetag, swim, bike, run, city, state, uid, UNIX_TIMESTAMP(date) as foo FROM gforum_Triathlons RIGHT JOIN WHERE regionid='$_GET[region]' AND valid=1 AND date > '2008-01-01' ORDER BY date ASC");**/ + +// set the page title +$pagetitle = $regionname; +$selected_item = mysql_escape_string($_GET[region]); + +// set meta tags +$meta_keywords = "triathlons in ".$regionname; +$meta_description = "Trying to find triathlons or duathlons in ".$regionname."? Here is a listing of all ".$regionname." triathlons. Users can even rate and comment on races."; + +?> + + + + + + +
    + +
    +
    + + + +
    + +
    +
    + +
    +

    Triathlons

    + Back + + " class="btn btn-white float-right">Add Race + +
    + + +

    Region

    +
    + No triathlons have been entered yet for $regionname.

    "; + } + ?> + + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/racecalendar/search.php b/site/racecalendar/search.php new file mode 100644 index 0000000..c8ffd3a --- /dev/null +++ b/site/racecalendar/search.php @@ -0,0 +1,275 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Search For A Race

    + +

    If you would like to search for a race, please use the form below. None of the fields are mandatory. Checking no box "selects all." Checking regions selects all states in that region. Checking any state's box selects or deselects that state.

    Our keyword search is new and very crude. It is not meant to be Google. It's not very forgiving of misspellings, etc. Please feel free to contact us with any feedback.

    + +
    +

    +
    +
    +
    Name Search
    +
    +
    + +

    This will become the primary ordering of results, THEN date. This will search all races within the past 365 days and all future races. To search back beyond that, you need to manually override the date range below.

    +
    +
    +
    +
    Date Override
    +
    +
    + Yes +

    overrides keyword search default and allows you to use the date boxes below. Also resets default search to start with today's date.

    +
    +
    +
    +
    Start Date
    +
    +
    + + + Leave blank for today's date +
    +
    +
    +
    End Date
    +
    +
    + + + +
    +
    +
    +
    Race Type
    +
    +
    + Triathlon + Duathlon + Other +Leave blank to select all. +
    +
    +
    +
    Race distance
    +
    + Sprint + International + Half + Ultra +Leave blank to select all. +
    +
    +
    +
    +
    Bike Surface Type
    +
    +
    + Road + Offroad + Gravel +Leave blank to select all. +
    +
    +
    +
    Drafting Rules
    +
    +
    + Non-drafting + Draft legal +Leave blank to select all. +
    +
    +
    +
    Kids' Races
    +
    +
    + "Normal" (18yo+) Races ONLY + Kids' Races ONLY +Leave blank to select all. +
    +
    +
    +
    aces with registration fees included in price
    +
    +
    + Races where it is not specified if fees are included in price + Races where it is explicitly stated that the price includes all registration fee(s) +Leave blank to select all. +
    +
    +
    +
    Region
    +
    +
    + +"; +foreach($regions AS $region => $statetag) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + +} + +?> + +
    $region
    + +

    Selecting a region will select all states in that region. You can then deselect or select any additional states. Only the selected states will be included in your search. Leaving all boxes blank will select races in all states.

    +
    +
    +
    +
    State
    +
    +
    + +"; +while($row = mysql_fetch_array($state_list)){ + if(!($i%4)) echo ""; + echo "\n"; + $i++; +} +?> + +
    $row[statelong]
    +

    Leave blank to select all.

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + +
    + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/racecalendar/search_X.php b/site/racecalendar/search_X.php new file mode 100644 index 0000000..ca13bb6 --- /dev/null +++ b/site/racecalendar/search_X.php @@ -0,0 +1,221 @@ += '$afterdate'"; } + else { $sql = $sql." AND date >= NOW()"; } + if ($_POST[beforemonth] != 0 AND $_POST[beforeday] != 0) { + $beforedate = "$_POST[beforeyear]-$_POST[beforemonth]-$_POST[beforeday]"; + $sql = $sql." AND date <= '$beforedate'"; + } +} else { + $last_year = time() - 365*24*60*60; + $sql = $sql." AND date >= '".date('Y-m-d', $last_year)."'"; +} + +// regions are checkboxes that then check off all states within that region +// add states +if (isset($_POST[states])) { + $glue = "','"; + $statelist = "('".implode($glue, $_POST[states])."')"; + $sql = $sql." AND statetag IN $statelist"; +} + +// add distances +if (isset($_POST[points])) { + // convert the array to a SQL friendly format + $glue = ","; + $pointlist = "(".implode($glue, $_POST[points]).")"; + $sql = $sql." AND pointclass IN $pointlist"; +} + +$sql = $sql." ORDER BY date ASC"; + +$results = mysql_query($sql); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} +$race_count = mysql_num_rows($results); + +// trim redundant keywords: triathlon, duathlon +$trim_words = array(" the ", " a ", " an ", "and ", " half ", "triathlon", "duathlon"); +foreach ($trim_words AS $word) { + $_POST['keyword'] = str_ireplace($word, " ", $_POST['keyword']); +} +$bool_Keywords = false; +if (isset($_POST['keyword']) && $_POST['keyword'] != "") { +//keyword search + $bool_Keywords = true; + while($row_races = mysql_fetch_array($results)) { + // build an array that we can loop through. + $arr_Races[$i] = $row_races; + $i++; + } + + $arr_Matches = array(); + foreach ($arr_Races AS $race) { + if (stripos($race['name'], $_POST['keyword']) !== false) { + // push this onto the array of matches + $race['percent'] = 100; + array_push($arr_Matches, $race); + } else { + $name_nospace = str_replace(" ", "", $race['name']); + $keyword_nospace = str_replace(" ", "", $_POST['keyword']); + if (stripos($name_nospace, $keyword_nospace) !== false) { + // push this onto the array of matches + $race['percent'] = 90; + array_push($arr_Matches, $race); + } else { + // trim redundant keywords + $race_name = $race['name']; + foreach ($trim_words AS $word) { + $race_name = str_ireplace($word, " ", $race_name); + } + //$race_name = str_ireplace(" ", "", $race_name); + $race_name = strtolower($race_name); + $arr_race_name = explode(" ", $race_name); + $_POST['keyword'] = strtolower($_POST['keyword']); + $_POST['keyword'] = str_replace(" ", "", $_POST['keyword']); + foreach ($arr_race_name AS $test_word) { + similar_text($test_word, $_POST['keyword'], $percent); + if ($percent >= 65) { + // push this onto the array of matches + $race['percent'] = round($percent, 0); + //$race['trimmed'] = $race_name; + array_push($arr_Matches, $race); + break; + } + } + } + } + } + + if (count($arr_Matches) == 0) { + $none = TRUE; + } + $race_count = count($arr_Matches); + + //sort the array by keyword match success instead of by date + function cmp($a, $b) + { + if ($a['percent'] == $b['percent']) { + return 0; + } + return ($a['percent'] > $b['percent']) ? -1 : 1; + } + + usort($arr_Matches, "cmp"); +} +//end keyword search + +// set the page title +$pagetitle = "Search Results"; + +// set meta tags +$meta_keywords = "triathlons in matching a user's search query."; +$meta_description = "A list of matching races."; +?> + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Search Results

    +

    Races Match Your Search

    + + + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/racecalendar/searchlist.php b/site/racecalendar/searchlist.php new file mode 100644 index 0000000..e69de29 diff --git a/site/racecalendar/statelist.php b/site/racecalendar/statelist.php new file mode 100644 index 0000000..17e5d4a --- /dev/null +++ b/site/racecalendar/statelist.php @@ -0,0 +1,127 @@ + '".$min_date."' ORDER BY date ASC"); + +// set the page title +$pagetitle = $statename; +$selected_item = substr(mysql_escape_string($_GET[state]),0,20); + +// set meta tags +$meta_keywords = "triathlons in ".$statename; +$meta_description = "Trying to find triathlons or duathlons in ".$statename."? Here is a listing of all ".$statename." triathlons. Users can even rate and comment on races."; +?> + + + + + + + +
    + +
    +
    + + + +
    + +
    +
    + +
    +

    Triathlons

    + Back + + Add Triathlon + +
    + + +

    State

    +
    + No triathlons have been entered yet for $statename.

    "; + } + ?> + + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/racecalendar/top_races.php b/site/racecalendar/top_races.php new file mode 100644 index 0000000..7046799 --- /dev/null +++ b/site/racecalendar/top_races.php @@ -0,0 +1,65 @@ + '".$min_date."' AND gt.valid = 1 AND gtr.rating_triathlon_id = gt.uid GROUP BY gtr.rating_triathlon_id HAVING COUNT(gtr.rating_vote) > 50 ORDER BY score DESC, respondents DESC LIMIT 10"); + +// set the page title +$pagetitle = "Top Races"; + +// set meta tags +$meta_keywords = "top ranked triathlons"; +$meta_description = "Top ranked triathlons and duathlons based on rankings submitted by the user."; +?> + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Top Ranked Triathlons

    +
    + + No triathlons have been entered yet.

    "; + } + ?> +

    + + + +

    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/racecalendar/validate.php b/site/racecalendar/validate.php new file mode 100644 index 0000000..3b0d7a5 --- /dev/null +++ b/site/racecalendar/validate.php @@ -0,0 +1,130 @@ + '".$min_date."' ORDER BY date ASC"); + +// check to see if set is empty +$none = FALSE; +if (mysql_num_rows($results) == 0) { $none = TRUE; } + +// set the page title +$pagetitle = "Admin: Race Validation"; + +// set meta tags +$meta_keywords = ""; +$meta_description = ""; +?> + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Unvalidated Triathlons

    +
    + +
    + +
    + "> +
    Date: +
    +
    +
    + +
    + + Bike Surface: +
    + Location:
    + More information +
    Validate this race. Delete this race. +
    + +
    +

    + +

    +
    + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/racecalendar/validate_X.php b/site/racecalendar/validate_X.php new file mode 100644 index 0000000..75c6202 --- /dev/null +++ b/site/racecalendar/validate_X.php @@ -0,0 +1,34 @@ + \ No newline at end of file diff --git a/site/racecalendar/wiki_buttons.php b/site/racecalendar/wiki_buttons.php new file mode 100644 index 0000000..65bfa7a --- /dev/null +++ b/site/racecalendar/wiki_buttons.php @@ -0,0 +1,21 @@ + + +
    + +
    + + +
    + +
    + + +
    + +
    diff --git a/site/racecalendar/wiki_edit.php b/site/racecalendar/wiki_edit.php new file mode 100644 index 0000000..b894b45 --- /dev/null +++ b/site/racecalendar/wiki_edit.php @@ -0,0 +1,539 @@ + + +"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); +?> + + + + + + +
    + +
    +
    + + +
    +
    +
    + +
    + +

    Thank you

    + Thank you. Your race should be added within 24 hours. You will now be redirected back to the add page.

    "; + echo ""; + } else if($confirm == 1){ ?> +

    Edit a Race: Step 2 of 2

    + +

    Edit a Race: Step 1 of 2

    + +

    Thank you

    + +

    To edit a race, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes as a NEW race (for instance, if you have multiple races in the same location), hit the "SAVE AS A NEW RACE" button. To save changes to the existing race entry, hit the "SAVE CHANGES TO YOUR RACE" button. You will have a chance to review the data before confirming.

    + + + +
    +

    +
    +
    +
    Race Name
    +
    +
    + +
    +
    + +
    +
    Race Date
    +
    +
    + + + +
    +
    +
    +
    Start Time
    +
    +
    + + : + + +
    +
    +
    +
    Race Type
    +
    +
    + +
    +
    +
    +
    Bike Surface
    +
    +
    + >Road + >Offroad + >Gravel +
    +
    +
    +
    Draft Legal (on-road only)
    +
    +
    + >Yes, draft legal. (Leave un-checked for non-drafting) +
    +
    +
    +
    Kids' Race
    +
    +
    + >Yes, this is a kids' race. (Leave un-checked for a "normal" race) +
    +
    +
    +
    Individual entry fee
    +
    +
    + +
    +
    +
    +
    Team entry fee
    +
    +
    + +
    +
    +
    +
    Registration fees disclosed?
    +
    +
    + >Yes, registration fees are included or disclosed at the beginning of registration. (check this box if your entry fee *includes* any & all registration/convenience fees; or if at a minimum all registration fees are disclosed at the beginning of registration). +
    +
    +
    +
    +
    +
    + *************************************************************** +
    + IMPORTANT: Fractional lengths must be entered as a decimal number
    + Examples: 0.25, 1.2, 0.1, 13.2. If your race contains only two legs, simply + leave the third leg blank. +
    +
    +
    +
    1st distance
    +
    +
    + + + +
    +
    +
    +
    2nd distance
    +
    +
    + + + +
    +
    +
    +
    3rd distance
    +
    +
    + + + +
    +
    +
    +
    +
    +
    + ************************************************************** +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Phone Contact
    +
    +
    + +
    +
    +
    +
    E-mail Contact
    +
    +
    + +
    +
    +
    +
    Course Info
    +
    +
    + +
    +
    +
    +
    More Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    Registration link
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    Results
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + +
    +
    +
    + +
    + + + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + + diff --git a/site/racecalendar/wiki_edit_X.php b/site/racecalendar/wiki_edit_X.php new file mode 100644 index 0000000..ed02ab6 --- /dev/null +++ b/site/racecalendar/wiki_edit_X.php @@ -0,0 +1,175 @@ +"; } + $dupmsg = NULL; + + foreach ($arr_Races AS $race) { + if ($dupmsg) { $spacer = "
    "; } + similar_text($race['name'], $_POST['name'], $percent); + if ($race[uid] != $_POST[uid] && $percent >= 75 && $race['type'] == $_POST['type']) { + // DEBUG: which USERUID are we processing + $dupmsg = $dupmsg.$spacer."POTENTIAL DUPLICATE: ".$race[uid].". ".$race[name]." (".round($percent,0)."%) Please check this race first and update it instead of adding a new one."; + } + } + } + //end check for duplicate entry + // BEGIN ERROR MESSAGE CHECK + if(!$errmsg){ + $race_uid_fk = mysql_real_escape_string(trim($_POST[uid])); + $editor_user_id_fk = mysql_real_escape_string(trim($_POST[edited_by])); + $name = mysql_real_escape_string(trim($_POST[name])); + $nametag = strtolower(str_replace(" ","", $name)); + if(strlen($nametag) > 12){ //Shorten it + $nametag = substr($nametag, 0, 12); + } + $state = $_POST[state]; + $statetag = strtolower(str_replace(" ","", $state)); + $type = $_POST[type]; + $bike_surface = $_POST[bike_surface]; + if ($_POST[draft_legal] != "") { $draft_legal = $_POST[draft_legal]; } else { $draft_legal = 0; } + if ($_POST[kids_race] != "") { $kids_race = $_POST[kids_race]; } else { $kids_race = 0; } + $indivfee = mysql_real_escape_string(trim($_POST[indivfee])); + $teamfee = mysql_real_escape_string(trim($_POST[teamfee])); + if ($_POST[registration] != "") { $registration = $_POST[registration]; } else { $registration = 0; } + $swim = $_POST[swim]; + $oneunit = $_POST[oneunit]; + $twounit = $_POST[twounit]; + $threeunit = $_POST[threeunit]; + $onetype = $_POST[onetype]; + $twotype = $_POST[twotype]; + $threetype = $_POST[threetype]; + $bike = $_POST[bike]; + if ($_POST[run] != "") { $run = $_POST[run]; } else { $run = 0; } + $city = mysql_real_escape_string(trim($_POST[city])); + $address = mysql_real_escape_string(trim($_POST[address])); + $phone = mysql_real_escape_string(trim($_POST[phone])); + $email = mysql_real_escape_string(trim($_POST[email])); + $courseinfo = substr(mysql_real_escape_string(trim($_POST[courseinfo])), 0, 4096); + $moreinfo = substr(mysql_real_escape_string(trim($_POST[moreinfo])), 0, 4096); + $directions = substr(mysql_real_escape_string(trim($_POST[directions])), 0, 4096); + $substring = "http"; + $register = mysql_real_escape_string(trim($_POST[register])); + $website = mysql_real_escape_string(trim($_POST[website])); + $results = mysql_real_escape_string(trim($_POST[results])); + if (!is_int(strpos($register, $substring))) { + $register = "http://".$register; + } + if (!is_int(strpos($website, $substring))) { + $website = "http://".$website; + } + $hour = $_POST[hour]; + //if($_POST[daypart] == 1){ $hour = $hour + 12; } + $minute = $_POST[minute]; + $year = $_POST[year]; + $month = $_POST[month]; + $day = $_POST[day]; + $date = "$year-$month-$day $hour:$minute:00"; + $uid = $_POST[uid]; + $submitted_by = $_POST[submitted_by]; + $edited_by = $_POST[edited_by]; + $edit_timestamp = time(); + + if($type == 1){ $typename = 'Triathlon'; } + if($type == 2){ $typename = 'Duathlon'; } + if($type == 3){ $typename = 'Other'; } + + // BEGIN CONFIRM ENTRY CHECK + if($_POST[confirm_entry] == 1){ + + // BEGIN POINTS CALCULATIONS + + $one_points = 0; + $two_points = 0; + $three_points = 0; + + $arrSwimPoints = array(1 => 17.6, 2 => 0.011, 3 => 0.01, 4 => 11); + $arrBikePoints = array(1 => 1, 2 => 0.00062, 3 => 0.00057, 4=> .62); + $arrRunPoints = array(1 => 4, 2 => 0.0025, 3 => 0.0023, 4 => 2.5); + $arrPaddlePoints = array(1 => 2.6667, 2 => 0.00167, 3 => 0.00153, 4 => 1.6667); + $arrSkiPoints = array(1 => 2.75, 2 => 0.00172, 3 => 0.00158, 4 => 1.72); + $arrMtbPoints = array(1 => 2, 2 => 0.00124, 3 => 0.00114, 4=> 1.24); + $arrPoints = array(1 => $arrSwimPoints, 2=> $arrBikePoints, 3 => $arrRunPoints, 4 => $arrPaddlePoints, 5 => $arrSkiPoints); + + $one_points = $swim*$arrPoints[$onetype][$oneunit]; + $two_points = $bike*$arrPoints[$twotype][$twounit]; + $three_points = $run*$arrPoints[$threetype][$threeunit]; + + $points = $one_points + $two_points + three_points; + + if ($points < 40) { $pointclass = 1; + } elseif ($points >= 40 AND $points < 100) { $pointclass = 2; + } elseif ($points >= 100 AND $points < 180) { $pointclass = 3; + } else { $pointclass = 4; } + + // END POINTS CALCULATION + + if(isset($_POST['add_race'])){ + $sql = "INSERT INTO gforum_Triathlons(onetype, twotype, threetype, oneunit, twounit, threeunit, racetags, valid, name, nametag, date, type, indivfee, teamfee, swim, bike, bike_surface, draft_legal, kids_race, run, state, statetag, city, address, phone, email, courseinfo, moreinfo, directions, register, website, submitted_by, one_points, two_points, three_points, points, pointclass, registration) VALUES('$onetype', '$twotype', '$threetype', '$oneunit', '$twounit', '$threeunit', '0', 0, '$name', '$nametag', '$date', $type, '$indivfee', '$teamfee', $swim, $bike, $bike_surface, $draft_legal, $kids_race, $run, '$state', '$statetag', '$city', '$address', '$phone', '$email', '$courseinfo', '$moreinfo', '$directions', '$register', '$website', '$submitted_by', $one_points, $two_points, $three_points, $points, $pointclass, $registration)"; + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/add.php?confirmed=yes'); + } elseif(isset($_POST['save_changes'])) { + $sql = "INSERT INTO gforum_TriathlonsEdits(race_uid_fk, editor_user_id_fk, edit_timestamp, onetype, twotype, threetype, oneunit, twounit, threeunit, name, nametag, date, type, indivfee, teamfee, swim, bike, bike_surface, draft_legal, kids_race, run, state, statetag, city, address, phone, email, courseinfo, moreinfo, directions, register, website, submitted_by, one_points, two_points, three_points, points, pointclass, registration) VALUES('$race_uid_fk', '$editor_user_id_fk', '$edit_timestamp', '$onetype', '$twotype', '$threetype', '$oneunit', '$twounit', '$threeunit', '$name', '$nametag', '$date', $type, '$indivfee', '$teamfee', $swim, $bike, $bike_surface, $draft_legal, $kids_race, $run, '$state', '$statetag', '$city', '$address', '$phone', '$email', '$courseinfo', '$moreinfo', '$directions', '$register', '$website', '$submitted_by', $one_points, $two_points, $three_points, $points, $pointclass, $registration)"; + //echo $sql; + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/individual.php?uid='.$uid.'&wiki_change=success'); + } else { + header('Location: '.$site_url.'/individual.php?uid='.$uid.'&changes=failure'); + } + } else { + $confirm = 1; + } // END CONFIRM CHECK +} // END ERROR MESSAGE CHECK + +?> diff --git a/site/racecalendar/wiki_validate.php b/site/racecalendar/wiki_validate.php new file mode 100644 index 0000000..3bbcf1c --- /dev/null +++ b/site/racecalendar/wiki_validate.php @@ -0,0 +1,165 @@ + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Unvalidated Public Edits

    +
    + +
    + + +
    +
    Edited on: by ".$editor_user_username.""; if ($boolEditorIsOwner) { echo " (original race submitter)"; } else { echo ""; } ?>
    +
    "mile", 2 => "meter", 3 => "yard", 4 => "kilometer" ); + $arrType = array(1 => "swim", 2 => "bike", 3 => "run", 4 => "paddle", 5 => "ski" ); + + ?> +
    Course: + +
    + +
    + Bike Surface: +
    + +
    + Drafting rules: +
    + +
    + Is this a kids' race? +
    + +
    + Registration fees included: +
    + +
    Description: + 400){ + $phrase = "…"; }else{ + $phrase = ""; } + + echo substr(htmlspecialchars(stripslashes($row[courseinfo])), 0, 160); + echo $phrase; + ?> +
    + +
    Additional Info: + 400){ + $phrase = "…"; }else{ + $phrase = ""; } + + echo substr(htmlspecialchars(stripslashes($row[moreinfo])), 0, 160); + echo $phrase; + ?> +
    + +
    + Location:
    + ">More information +
    Validate this edit. Delete this edit. +
    + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/racecalendar/wiki_validate_X.php b/site/racecalendar/wiki_validate_X.php new file mode 100644 index 0000000..63fc4b7 --- /dev/null +++ b/site/racecalendar/wiki_validate_X.php @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/site/racecalendar/wiki_view.php b/site/racecalendar/wiki_view.php new file mode 100644 index 0000000..5d7e73e --- /dev/null +++ b/site/racecalendar/wiki_view.php @@ -0,0 +1,204 @@ + "Triathlon", 2 => "Duathlon", 3 => "Other"); + echo $arrRaceType[$_POST[type]]; + + + // set the page title + $pagetitle = $row[name]; + + // set meta tags + $meta_keywords = "triathlons, ".$row[name].", ".$row[state]." triathlon"; + $meta_description = "Considering racing at the ".$row[name]."? Here is all of the information including date, time, location, and course information."; + + include("include_common_head.php"); +?> + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    + + + +
    + + + +Editor: ".$strEditor.""; ?> +
    + +Edit Date: +
    + +Date: +
    + +Race Type: "Triathlon", 2 => "Duathlon", 3 => "Other"); + echo $arrRaceType[$row[type]]; +?> +
    + + +Bike Surface: +
    + + +Drafting rules:? +
    + + +Kids Race? +
    + +Course: + "mile", 2 => "meter", 3 => "yard", 4 => "kilometer" ); + $arrType = array(1 => "swim", 2 => "bike", 3 => "run", 4 => "paddle", 5 => "ski" ); + + echo $row[swim]." ".$arrUnits[$row[oneunit]]." ".$arrType[$row[onetype]].", ".$row[bike]." ".$arrUnits[$row[twounit]]." ".$arrType[$row[twotype]]; + + if ($row[run] != 0) { echo ", ".$row[run]." ".$arrUnits[$row[threeunit]]." ".$arrType[$row[threetype]]; } +?> +
    + +Start: +
    + +Location: +
    + +Address: +
    + +Contact: $row[email]"; ?> +

    + +Individual Price: +
    + +Team Price: +
    + + +Registration fees included?: +

    + +Course Info: "; ?> +
    + +More: "; ?> +
    + +Directions: "; ?> +
    + 0){ + +$substring = "http"; +if (!is_int(strpos($row[register], $substring))) { + $row[register] = "http://".$row[register]; +} + +?> + +Register: Click here"; ?> +
    + + + + +Website: $row[name]"; ?> +
    + +
    + +
    +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/retailers/add.php b/site/retailers/add.php new file mode 100644 index 0000000..7757cb4 --- /dev/null +++ b/site/retailers/add.php @@ -0,0 +1,532 @@ + + +"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); +?> + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + + +

    Thank You

    +

    Thank you. Your shop should be added within 24 hours. You will now be redirected back to the homepage page.

    + + +

    Add a Shop: Step 2 of 2

    + +

    Add a Shop: Step 1 of 2

    + +

    Thank you

    + +
    + + +

    If you would like to add your triathlon/bike shop to our website, simply fill out the form below. Be sure to fill out every field. After filling out each field, click submit. You will then be prompted to confirm your information before the information is sent to us.

    + + + +
    +

    +
    +
    +
    Shop Name
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Address 2
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    Online Shopping Cart
    +
    +
    + (Must be a fully functional ecommerce system) +
    +
    +
    +
    Spoke Alliance Member
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    We ship mail-order via
    +
    +
    + >e-commerce site
    + >phone +
    +
    +
    +
    We offer local home/work delivery, transacting via
    +
    +
    + >e-commerce site
    + >phone +
    +
    +
    +
    You may order in advance, and pick up, transacting via
    +
    +
    + >e-commerce site
    + >phone +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    F.I.S.T. Tri Fitter(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    F.I.S.T. Road Fitter(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    F.I.S.T. Advanced Fitter(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    BFACT Score
    +
    +
    + +
    +
    +
    +
    BikeFit, BodyGeometry, Retul, Serotta, or Trek Fitter(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    Default Tri-Fit Methodology
    +
    +
    +"); +while ($list = mysql_fetch_array($fetch)) { + echo("$list[retailer_method_name]\n"); + $i++; +} +?> +
    +
    +
    +
    Fit Bikes
    +
    +
    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[retailers_fitbike_name]\n"); +} +?> +
    +
    +
    +
    Motion-Capture Systems
    +
    +
    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[retailers_motioncapture_name]\n"); +} +?> +
    +
    +
    +
    +
    +
    + +

    IMPORTANT: Tri and road bike brands of which you'll have six or more sitting on the floor during the season.

    +
    +
    +
    +
    Wetsuits
    +
    +
    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[retailers_wetsuit_name]\n"); +} +?> +
    +
    +
    +
    Bikes
    +
    +
    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[retailers_bike_name]\n"); +} +?> +
    +
    +
    +
    Custom Frames
    +
    +
    +

    IMPORTANT: Custom brands of which you'll sell six or more in a 12 month period.

    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[retailers_custom_name]\n"); +} +?> +
    +
    +
    +
    Shop Hours
    +
    +
    + +
    +
    +
    +
    Barnett-Trained Mechanic(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    United Bicycle Institute-Trained Mechanic(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    Shop Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + Thank you. Your shop should be added within 24 hours. You will now be redirected back to the add page.

    "; + echo ""; + } + + if($confirm == 1){ + $confirm = 0; + include("include_add_confirm.php"); + } + } ?> + +
    +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/retailers/add_X.php b/site/retailers/add_X.php new file mode 100644 index 0000000..05a362e --- /dev/null +++ b/site/retailers/add_X.php @@ -0,0 +1,152 @@ + 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = mysql_real_escape_string(trim($_POST[address])); + $address_two = mysql_real_escape_string(trim($_POST[address_two])); + $city = mysql_real_escape_string(trim($_POST[city])); + $state = mysql_real_escape_string($_POST[state]); + $state_tag = mysql_real_escape_string(strtolower(str_replace(" ","", $state))); + $zip = mysql_real_escape_string(trim($_POST[zip])); + $phone = mysql_real_escape_string(trim($_POST[phone])); + $fax = mysql_real_escape_string(trim($_POST[fax])); + $email = mysql_real_escape_string(trim($_POST[email])); + $website = mysql_real_escape_string(trim($_POST[website])); + $cart = mysql_real_escape_string(trim($_POST[cart])); + $spoke = mysql_real_escape_string(trim($_POST[spoke])); + $mailorder_ecommerce = mysql_real_escape_string(trim($_POST[mailorder_ecommerce])); + $mailorder_phone = mysql_real_escape_string(trim($_POST[mailorder_phone])); + $local_ecommerce = mysql_real_escape_string(trim($_POST[local_ecommerce])); + $local_phone = mysql_real_escape_string(trim($_POST[local_phone])); + $pickup_ecommerce = mysql_real_escape_string(trim($_POST[pickup_ecommerce])); + $pickup_phone = mysql_real_escape_string(trim($_POST[pickup_phone])); + $contact = mysql_real_escape_string($_POST[contact]); + if ( $contact == 0 ){ $contact_names = NULL; }else{ $contact_names = mysql_real_escape_string(trim($_POST[contact_names])); } + $fist = mysql_real_escape_string($_POST[fist]); + if ( $fist == 0 ){ $fist_names = NULL; }else{ $fist_names = mysql_real_escape_string(trim($_POST[fist_names])); } + $fist_road = mysql_real_escape_string($_POST[fist_road]); + if ( $fist_road == 0 ){ $fist_road_names = NULL; }else{ $fist_road_names = mysql_real_escape_string(trim($_POST[fist_road_names])); } + $fist_advanced = mysql_real_escape_string($_POST[fist_advanced]); + if ( $fist_advanced == 0 ){ $fist_advanced_names = NULL; }else{ $fist_advanced_names = mysql_real_escape_string(trim($_POST[fist_advanced_names])); } + $bfact = mysql_real_escape_string(trim($_POST[bfact])); + $serotta = mysql_real_escape_string($_POST[serotta]); + if ( $serotta == 0 ){ $serotta_names = NULL; }else{ $serotta_names = mysql_real_escape_string(trim($_POST[serotta_names])); } + /* Need to ltrim and rtrim commas before insertion --> or ltrim/rtrim before implosion*/ + $methods = mysql_real_escape_string($_POST[methods]); + $fitbikes = mysql_real_escape_string($_POST[fitbikes]); + $motioncapture = mysql_real_escape_string($_POST[motioncapture]); + $wetsuits = mysql_real_escape_string($_POST[wetsuits]); + $bikes = mysql_real_escape_string($_POST[bikes]); + $customs = mysql_real_escape_string($_POST[customs]); + $hours = mysql_real_escape_string(trim($_POST[hours])); + $barnett = mysql_real_escape_string($_POST[barnett]); + if ( $barnett == 0 ){ $barnett_names = NULL; }else{ $barnett_names = mysql_real_escape_string(trim($_POST[barnett_names])); } + $ubi = mysql_real_escape_string($_POST[ubi]); + if ( $ubi == 0 ){ $ubi_names = NULL; }else{ $ubi_names = mysql_real_escape_string(trim($_POST[ubi_names])); } + $info = mysql_real_escape_string(nl2br(substr(trim($_POST[info]), 0, 4096))); + $directions = mysql_real_escape_string(nl2br(substr(trim($_POST[directions]), 0, 4096))); + $submitted_by = mysql_real_escape_string($_POST[submitted_by]); + + if($_POST[confirm1] == 1){ + $sql = "INSERT INTO gforum_Retailers (retailer_name, retailer_name_tag, retailer_address, retailer_address_two, retailer_city, retailer_state, retailer_state_tag, retailer_zip, retailer_phone, retailer_fax, retailer_email, retailer_website, retailer_cart, retailer_mailorder_ecommerce, retailer_mailorder_phone, retailer_local_ecommerce, retailer_local_phone, retailer_pickup_ecommerce, retailer_pickup_phone, retailer_contact, retailer_contact_names, retailer_fist, retailer_fist_names, retailer_fist_road, retailer_fist_road_names, retailer_fist_advanced, retailer_fist_advanced_names, retailer_bfact, retailer_serotta, retailer_serotta_names, retailer_method, retailer_fitbikes, retailer_motioncapture, retailer_wetsuits, retailer_bikes, retailer_customs, retailer_hours, retailer_barnett, retailer_barnett_names, retailer_ubi, retailer_ubi_names, retailer_info, retailer_directions, retailer_submitted_by, retailer_valid, retailer_spoke) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', '$cart', '$mailorder_ecommerce', '$mailorder_phone', '$local_ecommerce', '$local_phone', '$pickup_ecommerce', '$pickup_phone', $contact, '$contact_names', $fist, '$fist_names', $fist_road, '$fist_road_names', $fist_advanced, '$fist_advanced_names', '$bfact', $serotta, '$serotta_names', '$methods', ',$fitbikes,', ',$motioncapture,', ',$wetsuits,', ',$bikes,', ',$customs,', '$hours', $barnett, '$barnett_names', $ubi, '$ubi_names', '$info', '$directions', $submitted_by, 0, '$spoke')"; + //echo("shop entered!"); + //echo($sql); + //exit(); + mysql_query($sql) OR die(mysql_error()); + //exit(); + }else{ + //echo("shop NOT entered."); + $confirm = 1; +} + } +//}else{ + // $errmsg = 'Incorrect key.'; +//} +?> diff --git a/site/retailers/ajax.rate.item.php b/site/retailers/ajax.rate.item.php new file mode 100644 index 0000000..694db67 --- /dev/null +++ b/site/retailers/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/retailers/all_retailers_ranked.php b/site/retailers/all_retailers_ranked.php new file mode 100644 index 0000000..54f7d2f --- /dev/null +++ b/site/retailers/all_retailers_ranked.php @@ -0,0 +1,117 @@ + 1325375999) GROUP BY grr.rating_retailer_id HAVING COUNT(grr.rating_vote) > 1 ORDER BY gr.retailer_name"); + +$top_retailers = array(); +while($row = mysql_fetch_array($results)) { + + $row['weighted_score'] = $row['score']+$w_respondents*($row['respondents']); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_cart*($row['retailer_cart']); + + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_shopper_tags*substr_count($row['retailer_shopper_tags'], ','); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_fitbikes*substr_count($row['retailer_fitbikes'], ','); + + $row['weighted_score'] = $row['weighted_score']* $w_retailer_motioncapture+substr_count($row['retailer_motioncapture'], ','); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_wetsuits*substr_count($row['retailer_wetsuits'], ','); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_bikes*substr_count($row['retailer_bikes'], ','); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_fist_names*substr_count($row['retailer_fist_names'], ','); + + array_push($top_retailers, $row); +} + +//sort the array by score +function weight_sort($a, $b) +{ + if ($a['weighted_score'] == $b['weighted_score']) { + return 0; + } + return ($a['weighted_score'] > $b['weighted_score']) ? -1 : 1; +} + +//sort the array alphabetically +function alpha_sort($a, $b) +{ + return strcmp($a['retailer_name'], $b['retailer_name']); +} + +usort($top_retailers, "weight_sort"); + +$max_score = $top_retailers[0]['weighted_score']; + +usort($top_retailers, "alpha_sort"); + +// set the page title +$pagetitle = "2013 Top Retailers"; + +// set meta tags +$meta_keywords = "top ranked retailers"; +$meta_description = "Top ranked triathlon retailers based on rankings submitted by the user."; +?> + + + + + +
    + + +
    + + + + + +

    2013 Top Ranked Triathlon Retailers

    +
    +These rankings are compiled based off Slowtwitch.com's own scoring algorithm. The individual ranking - by stars - of each shop is still shown. But the list's ranking and the score shown on this page is the Slowtwitch.com score for each retailer. Rankings based on votes placed in the past two years (since Jan 1, 2012).

    + + + +"> + + +
    +
    + - +
    +
    +
    + + + +
    + +
    + + + + diff --git a/site/retailers/comments_add.php b/site/retailers/comments_add.php new file mode 100644 index 0000000..002d2b6 --- /dev/null +++ b/site/retailers/comments_add.php @@ -0,0 +1,31 @@ + + +
    + + + + +
    + +Add A Comment +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    + + +
    diff --git a/site/retailers/comments_add_X.php b/site/retailers/comments_add_X.php new file mode 100644 index 0000000..451545e --- /dev/null +++ b/site/retailers/comments_add_X.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/site/retailers/comments_show.php b/site/retailers/comments_show.php new file mode 100644 index 0000000..997f0d4 --- /dev/null +++ b/site/retailers/comments_show.php @@ -0,0 +1,19 @@ + + + + +" data-num-posts="5" data-width="500">
    */ ?> +" num_posts="5" width="500">**/ ?> + diff --git a/site/retailers/comments_validate.php b/site/retailers/comments_validate.php new file mode 100644 index 0000000..cb92334 --- /dev/null +++ b/site/retailers/comments_validate.php @@ -0,0 +1,88 @@ + + + + + + +
    + + +
    + + + + + +

    Unvalidated Comments

    +
    +
    + + + + "> + + + +
    Reviewed by: ".$commenter_user_username.""; echo " on ".date("F j, Y g:i A", $arrComments[comment_time]); echo " about ".$retailer_name."";?>
    + +
    Validate this comment. Delete this comment.
    +
    + +
    +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/site/retailers/comments_validate_X.php b/site/retailers/comments_validate_X.php new file mode 100644 index 0000000..47ab879 --- /dev/null +++ b/site/retailers/comments_validate_X.php @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/site/retailers/config.php b/site/retailers/config.php new file mode 100644 index 0000000..1b38b17 --- /dev/null +++ b/site/retailers/config.php @@ -0,0 +1,78 @@ += '4.0.4pl1' && strstr($_SERVER["HTTP_USER_AGENT"],'compatible')) { + if (extension_loaded('zlib')) { + ob_end_clean(); + ob_start('ob_gzhandler'); + } +} else if ($phpver > '4.0') { + if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) { + if (extension_loaded('zlib')) { + $do_gzip_compress = TRUE; + ob_start(array('ob_gzhandler',5)); + ob_implicit_flush(0); + header('Content-Encoding: gzip'); + } + } +} +$phpver = explode(".", $phpver); +$phpver = "$phpver[0]$phpver[1]"; +if ($phpver >= 41) { + $PHP_SELF = $_SERVER['PHP_SELF']; +} + +if (!ini_get("register_globals")) { + /* import_request_variables('GPC'); */ +} + +$statecount = mysql_num_rows(mysql_query("SELECT * FROM gforum_Retailers")); + +function curPageURL() { + $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); + $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); + $port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : ''; + $url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.$_SERVER["REQUEST_URI"]; + return $url; +} + +?> diff --git a/site/retailers/delete_X.php b/site/retailers/delete_X.php new file mode 100644 index 0000000..6606c11 --- /dev/null +++ b/site/retailers/delete_X.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/site/retailers/edit.php b/site/retailers/edit.php new file mode 100644 index 0000000..09fd447 --- /dev/null +++ b/site/retailers/edit.php @@ -0,0 +1,847 @@ + + + + + + +
    + +"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); +?> + + +
    + + + + + + +

    Thank you

    +Thank you. Your shop should be added within 24 hours. You will now be redirected back to the add page.

    "; +echo ""; +} else if($confirm == 1){ ?> +

    Edit a Shop: Step 2 of 2

    + +

    Edit a Shop: Step 1 of 2

    + +

    Thank you

    + +

    To edit a retailer, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes as a NEW retailer (for instance, if you have multiple locations), hit the "SAVE AS A NEW RETAILER" button. To save changes to the existing retailer entry, hit the "SAVE CHANGES TO YOUR SHOP" button. You will have a chance to review the data before confirming.

    + + + +
    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Shop Name:
    Street address:
    Street address two:
    City:
    State: + + +
    Zip/Postal Code:
    Phone:
    Fax / Alternate Phone:
    E-mail:
    Website: +(include http:// ) +
    Online Shopping Cart:
    (Must be a fully functional ecommerce system)
    +>No +>Yes +
    +
    + +
    +
    +
    Key Tri-Specific Contact(s): +>None +>Yes, Their Names: + + +
    F.I.S.T. Fitter(s): >None +>Yes, Their Names: + + +
    Serotta Fitter(s): >None +>Yes, Their Names: + + + +
    Fit Bikes: "); +echo(""); +while ($fetch = mysql_fetch_array($list)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +echo(""); + +?> +
    $fetch[retailers_fitbike_name]
    +
    Motion-Capture Systems: "); +echo(""); +while ($fetch = mysql_fetch_array($list)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +echo(""); + +?> +
    $fetch[retailers_motioncapture_name]
    +
    +
    + +
    +IMPORTANT: Wetsuit brands of which you'll have 12 or more continually in stock during the season.
    +
    +
    Wetsuits: "); +echo(""); +while ($fetch = mysql_fetch_array($list)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +echo(""); + +?> +
    $fetch[retailers_wetsuit_name]
    +
    +
    +
    +IMPORTANT: Tri and road bike brands of which you'll have six or more sitting on the floor during the season.
    +
    +
    Bikes: "); +echo(""); +while ($fetch = mysql_fetch_array($list)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +echo(""); + +?> +
    $fetch[retailers_bike_name]
    +
    +
    +
    +IMPORTANT: Custom brands of which you'll sell six or more in a 12 month period.
    +
    +
    Custom Frames: "); +echo(""); +while ($fetch = mysql_fetch_array($list)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +echo(""); + +?> +
    $fetch[retailers_custom_name]
    +
    +
    + +
    Shop Hours:
    Barnett-Trained Mechanic(s): >None +>Yes, Their Names: + + + +
    United Bicycle Institute-Trained Mechanic(s): >None +>Yes, Their Names: + + + +
    Shop Info:
    Directions:
    + + + + + + + +
    +
    + +Thank you. Your shop should be edited within 24 hours. You will now be redirected back to the home page.

    "; +echo ""; +}**/ + +if($confirm == 1){ + $confirm = 0; +?> +
    +Please confirm your shop information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your shop information before submitting.
    +
    + +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Shop Name:
    Street address:
    Street address two:
    City:
    State:
    Zip/Postal Code:
    Phone:
    Fax / Alternate Phone:
    E-mail:
    Website: +
    Cart: +
    +
    + +
    +
    +
    Key Tri-Specific Contact(s):
    F.I.S.T. Fitter(s):
    Serotta Fitter(s):
    Fit Bikes: +
    Motion-Capture Systems: +
    +
    + +
    +
    +
    Wetsuits: +
    Bikes: +
    Custom Frames: +
    +
    + +
    Shop Hours:
    Barnett-Trained Mechanic(s):
    United Bicycle Institute-Trained Mechanic(s):
    Shop Info:
    Directions:
    +
    +
    + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +This data will be saved as a NEW RETAILER. + + + +This data will be saved as a modification to the EXISTING RETAILER. + + + + +    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    + + + diff --git a/site/retailers/edit_X.php b/site/retailers/edit_X.php new file mode 100644 index 0000000..5a5ec3a --- /dev/null +++ b/site/retailers/edit_X.php @@ -0,0 +1,166 @@ + 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = trim($_POST[retailer_address]); + $address_two = trim($_POST[retailer_address_two]); + $city = trim($_POST[retailer_city]); + $state = $_POST[retailer_state]; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = trim($_POST[retailer_zip]); + $phone = trim($_POST[retailer_phone]); + $fax = trim($_POST[retailer_fax]); + $email = trim($_POST[retailer_email]); + $website = trim($_POST[retailer_website]); + $cart = trim($_POST[retailer_cart]); + $contact = $_POST[retailer_contact]; + if ( $contact == 0 ){ $contact_names = NULL; }else{ $contact_names = trim($_POST[retailer_contact_names]); } + $fist = $_POST[retailer_fist]; + if ( $fist == 0 ){ $fist_names = NULL; }else{ $fist_names = trim($_POST[retailer_fist_names]); } + $serotta = $_POST[retailer_serotta]; + if ( $serotta == 0 ){ $serotta_names = NULL; }else{ $serotta_names = trim($_POST[retailer_serotta_names]); } + /* Need to ltrim and rtrim commas before insertion --> or ltrim/rtrim before implosion*/ + $fitbikes = $_POST[retailer_fitbikes]; + $motioncapture = $_POST[retailer_motioncapture]; + $wetsuits = $_POST[retailer_wetsuits]; + $bikes = $_POST[retailer_bikes]; + $customs = $_POST[retailer_customs]; + $hours = trim($_POST[retailer_hours]); + $barnett = $_POST[retailer_barnett]; + if ( $barnett == 0 ){ $barnett_names = NULL; }else{ $barnett_names = trim($_POST[retailer_barnett_names]); } + $ubi = $_POST[retailer_ubi]; + if ( $ubi == 0 ){ $ubi_names = NULL; }else{ $ubi_names = trim($_POST[retailer_ubi_names]); } + $info = nl2br(substr(trim($_POST[retailer_info]), 0, 4096)); + $directions = nl2br(substr(trim($_POST[retailer_directions]), 0, 4096)); + $submitted_by = $_POST[retailer_submitted_by]; + $id = $_POST[retailer_id]; + + // BEGIN CONFIRM ENTRY CHECK + if($_POST[confirm_entry] == 1){ + if(isset($_POST[new_shop])){ + $sql = "INSERT INTO gforum_Retailers (retailer_name, retailer_name_tag, retailer_address, retailer_address_two, retailer_city, retailer_state, retailer_state_tag, retailer_zip, retailer_phone, retailer_fax, retailer_email, retailer_website, retailer_cart, retailer_contact, retailer_contact_names, retailer_fist, retailer_fist_names, retailer_serotta, retailer_serotta_names, retailer_fitbikes, retailer_motioncapture, retailer_wetsuits, retailer_bikes, retailer_customs, retailer_hours, retailer_barnett, retailer_barnett_names, retailer_ubi, retailer_ubi_names, retailer_info, retailer_directions, retailer_submitted_by, retailer_valid) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', '$cart', $contact, '$contact_names', $fist, '$fist_names', $serotta, '$serotta_names', ',$fitbikes,', ',$motioncapture,', ',$wetsuits,', ',$bikes,', ',$customs,', '$hours', $barnett, '$barnett_names', $ubi, '$ubi_names', '$info', '$directions', $submitted_by, 0)"; + //echo("shop entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/add.php?confirmed=yes'); + } elseif(isset($_POST[save_changes])) { + $sql = "UPDATE gforum_Retailers + SET retailer_name = '$name', + retailer_name_tag = '$name_tag', + retailer_address = '$address', + retailer_address_two = '$address_two', + retailer_city = '$city', + retailer_state = '$state', + retailer_state_tag = '$state_tag', + retailer_zip = '$zip', + retailer_phone = '$phone', + retailer_fax = '$fax', + retailer_email = '$email', + retailer_website = '$website', + retailer_cart = '$cart', + retailer_contact = '$contact', + retailer_contact_names = '$contact_names', + retailer_fist = '$fist', + retailer_fist_names = '$fist_names', + retailer_serotta = '$serotta', + retailer_serotta_names = '$serotta_names', + retailer_fitbikes = ',$fitbikes,', + retailer_motioncapture = ',$motioncapture,', + retailer_wetsuits = ',$wetsuits,', + retailer_bikes = ',$bikes,', + retailer_customs = ',$customs,', + retailer_hours = '$hours', + retailer_barnett = '$barnett', + retailer_barnett_names = '$barnett_names', + retailer_ubi = '$ubi', + retailer_ubi_names = '$ubi_names', + retailer_info = '$info', + retailer_directions = '$directions' + WHERE retailer_id = $id"; + mysql_query($sql) OR die(mysql_error()); + //echo $sql; + header('Location: '.$site_url.'/individual.php?retailer_id='.$id.'&changes=success'); + } else { + header('Location: '.$site_url.'/individual.php?retailer_id='.$id.'&changes=failure'); + } + } else { + //echo("shop NOT entered."); + $confirm = 1; + } + // END CONFIRM ENTRY CHECK + } + // END ERROR MESSAGE CHECK +?> diff --git a/site/retailers/include_add_confirm.php b/site/retailers/include_add_confirm.php new file mode 100644 index 0000000..1d6a41e --- /dev/null +++ b/site/retailers/include_add_confirm.php @@ -0,0 +1,442 @@ +

    + Please confirm your shop information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your shop information before submitting. +

    + + +
    +
    +
    Store Name
    +
    +
    +
    +
    +
    Address
    +
    +
    +
    +
    +
    Address 2
    +
    +
    +
    +
    +
    City
    +
    +
    +
    +
    +
    State
    +
    +
    +
    +
    +
    Zip
    +
    +
    +
    +
    +
    Phone
    +
    +
    +
    +
    +
    Fax
    +
    +
    +
    +
    +
    E-mail
    +
    +
    +
    +
    +
    Website
    +
    +
    +
    +
    +
    Cart
    +
    +
    +
    +
    +
    Spoke Alliance
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    We ship mail-order via
    +
    +
    + + +
    +
    +
    +
    We offer local home/work delivery, transacting via
    +
    +
    + + +
    +
    +
    +
    You may order in advance, and pick up, transacting via
    +
    +
    + + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Tri Fitter(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Road Fitter(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Advanced Fitter(s)
    +
    +
    + +
    +
    +
    +
    BFACT Score
    +
    +
    + +
    +
    +
    +
    BikeFit, BodyGeometry, Retul, Serotta, or Trek Fitter(s)
    +
    +
    + +
    +
    +
    +
    Default Tri-Fit Methodology
    +
    +
    + 0) { + while ($row = mysql_fetch_array($results)) { + echo ("$row[retailer_method_name]"); + } + } else { + echo ("Unanswered"); + } +} +?> +
    +
    +
    +
    Fit Bikes
    +
    +
    + +
    +
    +
    +
    Motion-Capture Systems
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Wetsuits
    +
    +
    + +
    +
    +
    +
    Bikes
    +
    +
    + +
    +
    +
    +
    Custom Frames
    +
    +
    + +
    +
    +
    +
    Shop Hours
    +
    +
    + +
    +
    +
    +
    Barnett-Trained Mechanic(s)
    +
    +
    + +
    +
    +
    +
    United Bicycle Institute-Trained Mechanic(s)
    +
    +
    + +
    +
    +
    +
    Shop Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + + diff --git a/site/retailers/include_breadcrumb.php b/site/retailers/include_breadcrumb.php new file mode 100644 index 0000000..518c1ef --- /dev/null +++ b/site/retailers/include_breadcrumb.php @@ -0,0 +1,12 @@ + diff --git a/site/retailers/include_buttons.php b/site/retailers/include_buttons.php new file mode 100644 index 0000000..90d2d29 --- /dev/null +++ b/site/retailers/include_buttons.php @@ -0,0 +1,107 @@ + + +
    +
    + + + + + + +
    +
    " style="display: inline;"> + +
    + +
    " style="display: inline;"> + +
    + +
    " style="display: inline;"> + +
    + + + +
    + + +
    + +
    Entered By: $username"); + } +} +?> +
    diff --git a/site/retailers/include_common_content.php b/site/retailers/include_common_content.php new file mode 100644 index 0000000..c056049 --- /dev/null +++ b/site/retailers/include_common_content.php @@ -0,0 +1,45 @@ + + + +> + + +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    +
    +
    diff --git a/site/retailers/include_common_footer.php b/site/retailers/include_common_footer.php new file mode 100644 index 0000000..7812696 --- /dev/null +++ b/site/retailers/include_common_footer.php @@ -0,0 +1 @@ + diff --git a/site/retailers/include_common_head.php b/site/retailers/include_common_head.php new file mode 100644 index 0000000..369ddac --- /dev/null +++ b/site/retailers/include_common_head.php @@ -0,0 +1,16 @@ + + + + +Slowtwitch.com Retailer Database: <? echo $pagetitle; ?> + + + + + + + diff --git a/site/retailers/include_edit_confirm.php b/site/retailers/include_edit_confirm.php new file mode 100644 index 0000000..56d653e --- /dev/null +++ b/site/retailers/include_edit_confirm.php @@ -0,0 +1,471 @@ +

    + Please confirm your shop information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your shop information before submitting. +

    + +

    + + +
    +
    +
    Store Name
    +
    +
    +
    +
    +
    Address
    +
    +
    +
    +
    +
    Address 2
    +
    +
    +
    +
    +
    City
    +
    +
    +
    +
    +
    State
    +
    +
    +
    +
    +
    Zip
    +
    +
    +
    +
    +
    Phone
    +
    +
    +
    +
    +
    Fax
    +
    +
    +
    +
    +
    E-mail
    +
    +
    +
    +
    +
    Website
    +
    +
    +
    +
    +
    Cart
    +
    +
    +
    +
    +
    Spoke Alliance Member
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    We ship mail-order via
    +
    +
    + + +
    +
    +
    +
    We offer local home/work delivery, transacting via
    +
    +
    + + +
    +
    +
    +
    You may order in advance, and pick up, transacting via
    +
    +
    + + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Tri Fitter(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Road Fitter(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Advanced Fitter(s)
    +
    +
    + +
    +
    +
    +
    BFACT Score
    +
    +
    + +
    +
    +
    +
    BikeFit, BodyGeometry, Retul, Serotta, or Trek Fitter(s)
    +
    +
    + +
    +
    +
    +
    Default Tri-Fit Methodology
    +
    +
    + 0) { + while ($method_list = mysql_fetch_array($fetch)) { + echo ("$method_list[retailer_method_name]"); + } + } else { + echo ("Unanswered"); + } +} +?> +
    +
    +
    +
    Fit Bikes
    +
    +
    + +
    +
    +
    +
    Motion-Capture Systems
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Wetsuits
    +
    +
    + +
    +
    +
    +
    Bikes
    +
    +
    + +
    +
    +
    +
    Custom Frames
    +
    +
    + +
    +
    +
    +
    Shop Hours
    +
    +
    + +
    +
    +
    +
    Barnett-Trained Mechanic(s)
    +
    +
    + +
    +
    +
    +
    United Bicycle Institute-Trained Mechanic(s)
    +
    +
    + +
    +
    +
    +
    Shop Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This data will be saved as a NEW RETAILER.
    + + + + This data will be saved as a modification to the EXISTING RETAILER. + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + + diff --git a/site/retailers/include_navigation.php b/site/retailers/include_navigation.php new file mode 100644 index 0000000..de8f32b --- /dev/null +++ b/site/retailers/include_navigation.php @@ -0,0 +1,78 @@ + '2008-01-01'")); +$intcount = mysql_num_rows(mysql_query("SELECT date FROM gforum_Triathlons WHERE points >= 40 AND points < 100 AND valid = 1 AND date > '2008-01-01'")); +$midcount = mysql_num_rows(mysql_query("SELECT date FROM gforum_Triathlons WHERE points >= 100 AND points < 180 AND valid = 1 AND date > '2008-01-01'")); +$ultracount = mysql_num_rows(mysql_query("SELECT date FROM gforum_Triathlons WHERE points > 180 AND valid = 1 AND date > '2008-01-01'"));**/ + +/**$sqlstatelist = "SELECT gts.statetag AS statetag, gts.statelong AS statelong, COUNT(gt.uid) AS numshops +FROM gforum_TriathlonsStates AS gts +LEFT JOIN gforum_Triathlons AS gt +ON gts.statetag = gt.statetag AND gt.date > '2008-01-01' +GROUP BY gts.statetag ORDER BY gts.statetag ASC";**/ + +$sqlregionlist = "SELECT gtr.regionlong AS regionlong, gtr.regionid AS regionid, gtr.regionname AS regionname, gts.statetag AS statetag, gts.statelong AS statelong, COUNT(gr.retailer_id) AS numshops +FROM gforum_TriathlonsStates AS gts +LEFT JOIN gforum_Retailers AS gr +ON gts.statetag = gr.retailer_state_tag AND gr.retailer_valid = 1 +LEFT JOIN gforum_TriathlonsRegions AS gtr +ON gts.regionid = gtr.regionid +GROUP BY gtr.regionlong, gts.statetag ORDER BY gtr.regionlong ASC"; + +//$resultstatelist = mysql_query($sqlstatelist); + +$resultregionlist = mysql_query($sqlregionlist); + +?> +
    +

    Browse Retailers

    +
    +$currentregion ($regioncount)$state_string"; + echo ("
    " . $currentregion . " (" . $regioncount . ")+
    "); + echo $tempstring; + echo ("
    \n"); + } + $currentregion = $rowregionlist[regionlong]; + $currentrid = $rowregionlist[regionid]; + $currenttag = $rowregionlist[regionname]; + $regioncount = 0; + $tempstring = ''; + $state_string = ''; + } + if ($selected_item == $rowregionlist[statetag]) { + $selected_state = ' selected="selected"'; + } + $state_string .= ""; + $tempstring = $tempstring. "$rowregionlist[statelong] ($rowregionlist[numshops])\n"; + $regioncount += $rowregionlist[numshops]; +} + +echo ("
    ".$currentregion." (".$regioncount.")+
    "); +echo $tempstring; +echo ('
    '); +if ( $selected_item == 'top') { $selected_region = ' selected="selected"'; } +$region_dropdown .= ""; +?> + + +
    +
    diff --git a/site/retailers/include_rating.php b/site/retailers/include_rating.php new file mode 100644 index 0000000..d56f31b --- /dev/null +++ b/site/retailers/include_rating.php @@ -0,0 +1,61 @@ +What do you think of these?  On the rating that shows up on the race info +page, we ought to put in parentheses the number of people whose ratings make +up the average rating per category. + +Should the race get an overall rating?  The only one of these categories +below that is not specifically good or bad is course difficulty.  If you +think challenging is inherently good, then we could give an overall rating. +Me, I do think it's good. But, perhaps we could just get rid of this course +challenge and then everything is really good or bad, and we can give an +overall rating. + + +1. COURSE DENSITY + +dense   O O O O O  sparse + +2. RACE MARSHALS + +none  O O O O O   many + +3. COURSE SAFETY + +felt safe  O O O O O  felt less safe + +4. PRE-/POST-RACE FOOD + +sparse  O O O O O   plentiful/tasty + +5. AID STATIONS + +sparse  O O O O O   plentiful + +6. BATHROOMS + +sparse  O O O O O   plentiful + +7. START TIMES + +late  O O O O O   timely + +8. RESULTS + +late  O O O O O   timely + +9. AWARDS or QUAL SLOTS + +lacking  O O O O O   substantial + +10. LOCAL CULTURE & COMMUNITY + +limited   O O O O O  plentiful + +ONE VOTE PER IP + +LEAVE BLANK TO "N/A" A GIVEN CATEGORY + +At the top -- aggregate rating + +Button at top ("RATE THIS RACE") + +Button at the bottom as well (in case user did not see button at top) \ No newline at end of file diff --git a/site/retailers/include_rating_X.php b/site/retailers/include_rating_X.php new file mode 100644 index 0000000..e69de29 diff --git a/site/retailers/include_sidebar.php b/site/retailers/include_sidebar.php new file mode 100644 index 0000000..5086566 --- /dev/null +++ b/site/retailers/include_sidebar.php @@ -0,0 +1,14 @@ + + +
    + + + +
    + + diff --git a/site/retailers/include_starfunc.php b/site/retailers/include_starfunc.php new file mode 100644 index 0000000..ea4dbd4 --- /dev/null +++ b/site/retailers/include_starfunc.php @@ -0,0 +1,40 @@ += 0)or($tut_rating == 0)) && ($tut_rating <= 0.50)){ + echo "Not Rated"; + } + if((($tut_rating >= 0.50)or($tut_rating == 0.50)) && ($tut_rating <= .99)){ + echo ""; + } + if((($tut_rating >= 1.00)or($tut_rating == 1.50)) && ($tut_rating <= 1.49)){ + echo ""; + } + if((($tut_rating >= 1.50)or($tut_rating == 1.50)) && ($tut_rating <= 1.99)){ + echo ""; + } + if((($tut_rating >= 2.00)or($tut_rating == 2.00)) && ($tut_rating <= 2.49)){ + echo ""; + } + + if((($tut_rating >= 2.50)or($tut_rating == 2.50)) && ($tut_rating <= 2.99)){ + echo ""; + } + + if((($tut_rating >= 3.00)or($tut_rating == 3.00)) && ($tut_rating <= 3.49)){ + echo ""; + } + + if((($tut_rating >= 3.50)or($tut_rating == 3.50)) && ($tut_rating <= 3.99)){ + echo ""; + } + if((($tut_rating >= 4.00)or($tut_rating == 4.00)) && ($tut_rating <= 4.49)){ + echo ""; + } + if((($tut_rating >= 4.50)or($tut_rating == 4.50)) && ($tut_rating <= 4.99)){ + echo ""; + } + if($tut_rating == 5.0){ + echo ""; + } +} +?> diff --git a/site/retailers/include_status.php b/site/retailers/include_status.php new file mode 100644 index 0000000..5cbe5b5 --- /dev/null +++ b/site/retailers/include_status.php @@ -0,0 +1,11 @@ +
    Admin:"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table." WHERE ".$field_lead."valid = 0")); + echo("
    Validate Entries (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Edits")); + echo("
    Validate Edits (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Comment WHERE comment_valid = 0")); + echo("
    Validate Comments (".$unvalid_count.")"); +} +?> diff --git a/site/retailers/include_store.php b/site/retailers/include_store.php new file mode 100644 index 0000000..5278803 --- /dev/null +++ b/site/retailers/include_store.php @@ -0,0 +1,26 @@ +
    +
    +

    ">

    +
    + +

    + (Slowtwitch.com score of based on ) +

    + +
    + $row[retailer_address_two]"); } + echo("
    $row[retailer_city], $row[retailer_state] $row[retailer_zip]"); + ?> +
    Phone: +
    Fax: +
    +
    + Email: $row[retailer_email]"; ?>
    + Website: $row[retailer_website]"; ?>
    + "); } ?> + ">More info > +
    +
    diff --git a/site/retailers/index.php b/site/retailers/index.php new file mode 100644 index 0000000..4c73a91 --- /dev/null +++ b/site/retailers/index.php @@ -0,0 +1,148 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Retailers

    + + + Add Retailer + +
    + + +
    +
    +
    + + +

    Welcome to Slowtwitch.com's North American Multisport Retailer Database

    +

    retailers and counting. This collection of retailers is the most complete and comprehensive + selection of tri-specific bike dealers in North America. The purpose is to + introduce triathletes to the dealers they should know, and to present as + much pertinent information about them as possible. + +

    Searching the database

    +

    + Our Advanced Search is very potent, and will help you drill down to that set + of retailers conforming to a specific purpose you have in mind. For + example, you could search for those shops that have F.I.S.T. Certified + fitters on staff; and that carry Cervelo and Kuota; and that have either a + Serotta or Exit Cycling fit bike; and that are in either Wisconsin or + Illinois. Or you could search for shops in Georgia that stock Quintana Roo + wetsuits. The search parameters are yours to choose. +

    + +

    Browsing the database

    +

    + You do not need to log in to do this. You'll find a list of retailers in + your region by clicking the regional links on the left. Click the (+) sign + and the region will expand to expose the individual states. Click on the + state to show that list of retailers in it. If you want to see retailers in + multiple states, but not those states we've aggregated into the regions you + see at left, you may do this via our Advanced Search. +

    +

    F.I.S.T. Certified Dealers

    +

    + Many readers want to know which bike dealers near them have + F.I.S.T.-Certified fitters on staff. Each dealer's informational entry will + show whether such fitters are employed there. If you want a list of such + shops in your area, the Advanced Search will provide this for you. +

    +

    Showing solidarity with your LBS

    +

    + When you see your local bike shop listed here, you may click the "I SHOP + HERE" button. Your User Name will be added to the shop's list of customers, + just like your User Name appends to those races you choose when you build + your Slowtwitch Personal Race Calendar. Likewise, your Forum User Profile + will show that this is your LBS of choice. +

    + +

    How to enter a retailer

    +

    + You must be a registered user to add a retailer to the database. There is + one common type of registration on Slowtwitch, and if you are registered to + post on our Reader Forum you are one of + + who have made a registration, + and this means you're able to add retailers to our database. However, this + is not like adding a race to our calendar. There are a lot of technical + elements to this entry, and almost certainly the retailer will want to do + this himself. Therefore, it is wisest not to make an entry on behalf of + your preferred retailer, but to urge him to do so himself. +

    +

    + If you're not registered, the login prompt is to the left of the page, near + the top. The registration process is straightforward, easy, and free. It + will require you to receive an email and click on a link to complete your + registration. All this should take you only a minute or two. Then... +

    + 1. Click the ADD A SHOP button to begin adding to the database. +

    + 2. Once you SUBMIT your shop, you'll also need to CONFIRM your submission + via a link at the bottom of the page. +

    + 3. Once you successfully add your shop, it will not immediately be visible + to you. We must validate the addition on our end before anyone can see it. + We do this so that spammers won't use the shop registration as a way to spam + our database. +

    +

    How to edit published information about a retailer

    +

    + Any registered user may edit information for a listing. We will review the full contents of each update before confirming any changes that are made. A list of all editors who have made changes is visible at the bottom of each listing. If an entry has been updated, but those changes have not yet been confirmed, this is evident via a note on the individual page for that particular entry. This is to prevent conflicting updates from occuring simultaneously. If you wish to update an entry with pending changes, please wait until we have had a chance to review those changes first. Someone may have already changed the information you were going to change yourself. +

    +

    How to comment on a retailer

    +

    + Any registered user may make a comment on a retailer. These comments are subject to validation by an administrator before being published. +

    + +

    Global retailer map

    +

    + The map below shows the location of all registered Slowtwitch retailers around the globe. You can drag the map, zoom-in, zoom-out, and use any other of the standard Google Maps features. Anywhere you see a red icon, you can click to see the name of that retailer and a street address. +

    +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/retailers/individual.php b/site/retailers/individual.php new file mode 100644 index 0000000..8746052 --- /dev/null +++ b/site/retailers/individual.php @@ -0,0 +1,322 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Retailers

    + +
    + +
    + + Back +
    + + + +
    +
    +

    +
    +
    + Comment +
    +
    +
    +
    + "); } ?> + ,
    + Phone:
    + Fax: +
    +
    + Email:
    + Website:
    Spoke Alliance Member: +
    +
    + +

    Commenter: your comments have been submitted and will be validated within 24 hours.

    + + +

    Editor: your changes have been submitted and will be validated within 24 hours.

    + + +

    Group Edits: there are group edits waiting to be validated.

    + +
    + +
    +
    +

    Product Delivery Channels

    +
    + We ship mail-order via: + +
    + We offer local home/work delivery, transacting via: + +
    + You may order in advance, and pick up, transacting via: + +
    +
    +
    +
    +

    Bike Fit

    +
    + Key Tri-Specific Contact(s): +
    + F.I.S.T. Tri Fitter(s): +
    + F.I.S.T. Road Fitter(s): +
    + F.I.S.T. Advanced Fitter(s): +
    + BFACT Score:
    + BikeFit, BodyGeometry, Retul, Serotta, or Trek Fitter(s): +
    + Default Tri-Fit Methodology: + 0) { + while ($method_list = mysql_fetch_array($fetch)) { + echo ("$method_list[retailer_method_name]"); + } + } else { + echo ("Unanswered"); + } + ?>
    + Fit Bikes: +
    + Motion-Capture Systems: + +
    +
    +
    +

    Brands

    +
    + Wetsuits: +
    + Bikes: +
    + Custom Frames: + +
    +
    +
    +

    General Information

    +
    + Shop Hours:
    + Barnett-Trained Mechanic(s): +
    + United Bicycle Institute-Trained Mechanic(s): +
    + Shop Info:
    + Directions: +
    +
    +
    +
    +
    + +
    + + Map location is based off of a geocode of the addressed entered using Google's Google Maps API. If your address does not geocode properly, you can either update the address (we will attempt to re-geocode after any updates to your entry) or you can use Google's geocoding tool found here: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html to obtain a lat/long for your location and enter that. To use the utility, type in an address that is close to your location and then drag-and-drop the marker to obtain the desired lat/long. If you choose to enter a lat/long, you must check the box on the edit page that says, "override geocode with entered lat/long." + +
    +
    +
    + +

    +
    + 0) { + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if ( $i > 1 ) { echo ", "; } + echo "$temprow[user_username]"; + } + $i++; + } + if (count($tags) <= 1) { echo "No users"; } + ?> +
    +
    +
    + +

    +
    + = 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i >= 1) { echo "
    "; } + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + } + $i++; + } + if ($numcount <= 0) { echo "No users"; } + ?> +
    +
    +
    + +
    + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/retailers/individual.php.old b/site/retailers/individual.php.old new file mode 100644 index 0000000..f08cc1f --- /dev/null +++ b/site/retailers/individual.php.old @@ -0,0 +1,522 @@ + 0){ + $total = 0; + while($testrow = mysql_fetch_array($test)){ + if($testrow[rating] < 6){ $total = $total + $testrow[rating]; } + if($testrow[rating] == 6){ $num = $num - 1; } + } + $avg = $total / $num; +}else{ + //No ratings + $avg = 0; +}**/ +?> + + + + + + +
    + + + + +
    + +
    +

    + + +
    + + + +
    + + +Commenter: your comments have been submitted and will be validated within 24 hours. +

    + + + +Editor: your changes have been submitted and will be validated within 24 hours. +

    + + + +Group Edits: there are group edits waiting to be validated. +

    + + +Street Address: +
    +Street Address Two: +
    +City: +
    +State: +
    +Zip/Postal Code: +
    +Phone: +
    +Fax / Alternate Phone: +
    +E-mail: +
    +Website: + +
    +
    + +
    + +
    +
    +
    + +We ship mail-order via: + + +
    +We offer local home/work delivery, transacting via: + + +
    +You may order in advance, and pick up, transacting via: + + + +
    +
    + +
    + +
    + +
    +Key Tri-Specific Contact(s): + +
    +F.I.S.T. Tri Fitter(s): + +
    +F.I.S.T. Road Fitter(s): + +
    +F.I.S.T. Advanced Fitter(s): + +
    +BFACT Score: +
    +BikeFit, BodyGeometry, Retul, Serotta, or Trek Fitter(s): + +
    +Default Tri-Fit Methodology: + 0) { + while ($method_list = mysql_fetch_array($fetch)) { + echo ("$method_list[retailer_method_name]"); + } +} else { + echo ("Unanswered"); +} + +?> +
    +Fit Bikes: + +
    +Motion-Capture Systems: + +

    +
    + +
    + +
    +Wetsuits: + +
    +Bikes: + +
    +Custom Frames: + +

    +
    + +
    +
    +Shop Hours: +
    +Barnett-Trained Mechanic(s): + +
    +United Bicycle Institute-Trained Mechanic(s): + +

    +Shop Info: + +

    +Directions: + + +
    +
    + +
    + + +"; + include ('comments_add.php'); +}**/ + +?> + + + +
    + + + +
    + + + + +
    +
    Google Map
    +
    + +
    + + +
    + +
    +Map location is based off of a geocode of the addressed entered using Google's Google Maps API. If your address does not geocode properly, you can either update the address (we will attempt to re-geocode after any updates to your entry) or you can use Google's geocoding tool found here: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html to obtain a lat/long for your location and enter that. To use the utility, type in an address that is close to your location and then drag-and-drop the marker to obtain the desired lat/long. If you choose to enter a lat/long, you must check the box on the edit page that says, "override geocode with entered lat/long." + +
    + + + + + +"; +?> + + + + + +
    +
    +
    + 0){ +$tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value'") or die (mysql_error()); +$temprow = mysql_fetch_array($tempresults); +if($i > 1){ echo ", "; } +// TODO: SLOWTWITCH EDIT +//echo "$temprow[user_username]"; +// replace the link above with the link below for integration into gforum +echo "$temprow[user_username]"; +// TODO: SLOWTWITCH EDIT END +} +$i++; +} +if(count($tags) <= 1){ echo "No users"; } +?> +
    + +
    + + +Rate This Shop:

    + +Below are the current ratings for this retail shop, based on ".int_to_words($numVoters).""); if($numVoters == 1) { echo(" respondent"); } else { echo(" respondents"); } ?>. To rate this shop yourself, just mouse over each set of +"stars" below, and click on the star that corresponds to your view in each +category. Your vote in each category is recorded once you click the +appropriate star. The composite average rating for the shop is displayed at the top of the page. To view the top-10 retailers, +click here. +

    + + + +
    + + + +"; +?> + + + + +
    +
    +
    += 0){ +$tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); +$temprow = mysql_fetch_array($tempresults); +if($i >= 1){ echo "
    "; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + // TODO: SLOWTWITCH EDIT END +} +$i++; +} +if($numcount <= 0){ echo "No users"; } +?> +
    + +
    + +
    + +
    + + + + diff --git a/site/retailers/logout.php b/site/retailers/logout.php new file mode 100644 index 0000000..e6df200 --- /dev/null +++ b/site/retailers/logout.php @@ -0,0 +1,7 @@ + diff --git a/site/retailers/mod_rewrite.txt b/site/retailers/mod_rewrite.txt new file mode 100644 index 0000000..b8d3858 --- /dev/null +++ b/site/retailers/mod_rewrite.txt @@ -0,0 +1,15 @@ + + ServerName forum.slowtwitch.com + DocumentRoot /srv/www/htdocs/trifind + Options +FollowSymLinks + RewriteEngine On + RewriteRule ^/racereports/(.*)-([0-9]+).html$ /indivreport.php?report=$2 + RewriteRule ^/racereports/page([0-9]+).html$ /racereports.php?page=$1 + RewriteRule ^/editprofile/(.*).html$ /editprofile.php?username1=$1 + RewriteRule ^/profiles/(.*).html$ /profile.php?username1=$1 + RewriteRule ^/blogs/(.*)-([0-9]+).html$ /indivblog.php?blog=$2 + RewriteRule ^/(.*)/(.*)-([0-9]+).html$ /individual.php?uid=$3 + RewriteRule ^/state/(.*).html$ /statelist.php?state=$1 + RewriteRule ^/blogs/page([0-9]+).html$ /blog.php?page=$1 + RewriteRule ^/(.*).html$ /$1.php + diff --git a/site/retailers/mysql.class.php b/site/retailers/mysql.class.php new file mode 100644 index 0000000..6d82189 --- /dev/null +++ b/site/retailers/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/retailers/phpthumb/cache/index.php b/site/retailers/phpthumb/cache/index.php new file mode 100644 index 0000000..cee9927 --- /dev/null +++ b/site/retailers/phpthumb/cache/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/retailers/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg b/site/retailers/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg new file mode 100644 index 0000000..af7980d Binary files /dev/null and b/site/retailers/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg differ diff --git a/site/retailers/phpthumb/cache/source/index.php b/site/retailers/phpthumb/cache/source/index.php new file mode 100644 index 0000000..cee9927 --- /dev/null +++ b/site/retailers/phpthumb/cache/source/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/retailers/phpthumb/demo/index.php b/site/retailers/phpthumb/demo/index.php new file mode 100644 index 0000000..266a496 --- /dev/null +++ b/site/retailers/phpthumb/demo/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/retailers/phpthumb/demo/phpThumb.demo.check.php b/site/retailers/phpthumb/demo/phpThumb.demo.check.php new file mode 100644 index 0000000..7dd987c --- /dev/null +++ b/site/retailers/phpthumb/demo/phpThumb.demo.check.php @@ -0,0 +1,278 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.check.php // +// James Heinrich // +// // +// Configuration analyzer for phpThumb settings and server // +// settings that may affect phpThumb performance // +// Live demo is at http://phpthumb.sourceforge.net/demo/ // +// // +////////////////////////////////////////////////////////////// + +$ServerInfo['gd_string'] = 'unknown'; +$ServerInfo['gd_numeric'] = 0; +ob_start(); +if (!@include_once('../phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.functions.php")'); +} +if (!@include_once('../phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.class.php")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +if (include_once('../phpThumb.config.php')) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + } +} +$ServerInfo['gd_string'] = phpthumb_functions::gd_version(true); +$ServerInfo['gd_numeric'] = phpthumb_functions::gd_version(false); +$ServerInfo['im_version'] = $phpThumb->ImageMagickVersion(); +$gd_info = gd_info(); + +?> + + + + phpThumb configuration analyzer + + + + +This demo analyzes your settings (phpThumb.config.php and server/PHP) for phpThumb().
    +
    + + + + + + + + + + + + +
    <-- bad to good -->
                                    
    + + phpthumb_functions::SafeURLread('http://phpthumb.sourceforge.net/?latestversion=1', $dummy), + 'this' => $phpThumb->phpthumb_version, +); +foreach ($versions['raw'] as $key => $value) { + eregi('^([0-9\.]+)\-?(([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))?', $value, $matches); + @list($huge, $major, $minor) = @explode('.', @$matches[1]); + @list($year, $month, $day, $hour, $min) = @$matches[3]; + $versions['base'][$key] = $matches[1]; + $versions['huge'][$key] = $huge; + $versions['major'][$key] = $major; + $versions['minor'][$key] = $minor; + $versions['stamp'][$key] = $matches[2]; + $versions['year'][$key] = $year; + $versions['month'][$key] = $month; + $versions['day'][$key] = $day; + $versions['hour'][$key] = $hour; + $versions['min'][$key] = $min; + $versions['date'][$key] = @mktime($hour, $min, 0, $month, $day, $year); +} + +$downloadlatest = 'Download the latest version from http://phpthumb.sourceforge.net'; +echo ''; +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +?> +
    Latest phpThumb version:'.$versions['raw']['latest'].''.$downloadlatest.'
    This phpThumb version:info@silisoftware.com'; +} elseif (($versions['base']['latest'] == $versions['base']['this']) && ($versions['stamp']['this'] > $versions['stamp']['latest'])) { + // new than latest, must be beta version + echo 'lightblue'; + $message = 'You must be using a pre-release beta version. Please report bugs to info@silisoftware.com'; +} elseif ($versions['base']['latest'] == $versions['base']['this']) { + // latest version + echo 'lime'; + $message = 'You are using the latest released version.'; +} elseif ($versions['huge']['latest'].$versions['major']['latest'] == $versions['huge']['this'].$versions['major']['this']) { + echo 'olive'; + $message = 'One (or more) minor version(s) have been released since this version.
    '.$downloadlatest; +} elseif (floatval($versions['huge']['latest'].str_pad($versions['major']['latest'], 2, '0', STR_PAD_LEFT)) < floatval($versions['huge']['this'].str_pad($t_major, 2, '0', STR_PAD_LEFT))) { + echo 'yellow'; + $message = 'One (or more) major version(s) have been released since this version, you really should upgrade.
    '.$downloadlatest; +} else { + echo 'orange'; + $message = 'Fundamental changes have been made since this version.
    '.$downloadlatest; +} +echo '">'.$phpThumb->phpthumb_version; +echo '
    '.$message.'.
    PHP version:'.phpversion(); +echo 'PHP5 is ideal (support for numerous built-in filters which are much faster than my code).
    PHP v4.3.2+ supports ImageSaveAlpha which is required for proper PNG/ICO output.
    ImageRotate requires PHP v4.3.0+ (but buggy before v4.3.3).
    EXIF thumbnail extraction requires PHP v4.2.0+.
    Most things will work back to PHP v4.1.0, and mostly (perhaps buggy) back to v4.0.6, but no guarantees for any version older than that.
    GD version:'.@$ServerInfo['gd_string']; +echo 'GD2-bundled version is ideal.
    GD2 (non-bundled) is second choice, but there are a number of bugs in the non-bundled version.
    GD1 will also (mostly) work, at much-reduced image quality and several features disabled. phpThumb can perform basic resizing with ImageMagick only, even if GD is not available.
    ImageMagick version:'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a'); +echo 'ImageMagick is faster than GD, can process larger images without PHP memory_limit issues, can resize animated GIFs. phpThumb can perform basic resizing with ImageMagick only, even if GD is not available.
    GD features:'; +$GDfeatures['red'] = array('JPG Support', 'PNG Support'); +$GDfeatures['orange'] = array('GIF Read Support', 'GIF Create Support', 'FreeType Support'); +foreach ($GDfeatures as $missingcolor => $features) { + foreach ($features as $dummy => $feature) { + echo '
    '.htmlentities($feature).'
    '; + } +} +echo '
    PNG support is required for watermarks, overlays, calls to ImageMagick and other internal operations.
    JPG support is obviously quite useful, but ImageMagick can substitute
    GIF read support can be bypassed with ImageMagick and/or internal GIF routines.
    GIF create support can be bypassed with ImageMagick (if no filters are applied)
    FreeType support is needed for TTF overlays.
    GD extension "EXIF"'.(extension_loaded('exif') ? 'TRUE' : 'FALSE'); +echo 'EXIF extension required for auto-rotate images. Also required to extract EXIF thumbnail to use as source if source image is too large for PHP memory_limit and ImageMagick is unavailable.
    magic_quotes_runtime:'.$phpThumb->phpThumbDebugVarDump((bool) @get_magic_quotes_runtime()); +echo 'This setting is evil. Turn it off.
    magic_quotes_gpc:'.$phpThumb->phpThumbDebugVarDump((bool) @get_magic_quotes_gpc()); +echo 'This setting is bad. Turn it off, if possible. phpThumb will attempt to work around it if it is enabled
    safe_mode:'.$phpThumb->phpThumbDebugVarDump((bool) @ini_get('safe_mode')); +echo 'Best if off. Calls to ImageMagick will be disabled if on (limiting max image resolution, no animated GIF resize).
    allow_url_fopen:'.$phpThumb->phpThumbDebugVarDump((bool) @ini_get('allow_url_fopen')); +echo 'Best if on. HTTP source images will be unavailable if disabled and CURL is unavailable.
    curl_version:'.(function_exists('curl_version') ? curl_version() : 'n/a') ; +echo 'Best if available. HTTP source images will be unavailable if CURL unavailable and allow_url_fopen is also disabled.
    disable_functions:'.eregi_replace('(shell_exec|system|passthru|exec)(,|$)', '\\1(\\2)', $disable_functions); +echo 'Best if nothing disabled. Calls to ImageMagick will be prevented if exec+system+shell_exec+passthru are disabled.
    memory_limit:'.($memory_limit ? $memory_limit : 'unlimited'); +echo 'The higher the better. Divide by 5 to get maximum megapixels of source image that can be thumbnailed (without ImageMagick).'.($memory_limit ? ' Your setting ('.$memory_limit.') allows images up to approximately '.number_format($memory_limit / 5, 1).' megapixels' : '').'
    + + \ No newline at end of file diff --git a/site/retailers/phpthumb/demo/phpThumb.demo.demo.php b/site/retailers/phpthumb/demo/phpThumb.demo.demo.php new file mode 100644 index 0000000..e8a70d2 --- /dev/null +++ b/site/retailers/phpthumb/demo/phpThumb.demo.demo.php @@ -0,0 +1,249 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.demo.php // +// James Heinrich // +// // +// Demo showing a wide variety of parameters that can be // +// passed to phpThumb.php // +// Live demo is at http://phpthumb.sourceforge.net/demo/ // +// // +////////////////////////////////////////////////////////////// +$ServerInfo['gd_string'] = 'unknown'; +$ServerInfo['gd_numeric'] = 0; +ob_start(); +if (!@include_once('../phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.functions.php")'); +} +if (!@include_once('../phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.class.php")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +if (include_once('../phpThumb.config.php')) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + } +} +$ServerInfo['phpthumb_version'] = $phpThumb->phpthumb_version; +$ServerInfo['im_version'] = $phpThumb->ImageMagickVersion();; +$ServerInfo['gd_string'] = phpthumb_functions::gd_version(true); +$ServerInfo['gd_numeric'] = phpthumb_functions::gd_version(false); +unset($phpThumb); +?> + + + + Demo of phpThumb() - thumbnails created by PHP using GD and/or ImageMagick + + + + +This is a demo of phpThumb() (current version: v)
    +
    +Note: this server is working on GD "= 2) { + echo ', so images should be of optimal quality.'; +} else { + echo ', so images (especially watermarks) do not look as good as they would on GD v2.'; +} +?>
    + +
    +phpThumb.demo.showpic.php demo here
    +Difference between GD1 and GD2
    +
    +
    + The following images have the textured background behind them to illustrate transparency effects. + Note that some browsers, notably Internet Explorer, are incapable of displaying alpha-channel PNGs. + See my page on the PNG transparency problem. + Other modern browsers such as Mozilla/Firefox display alpha-transparent PNGs with no problems. +

    + + + +PNG transparency problem in Internet Explorer'; +$only_gd = '
    (only works with GD (any version), this server is '.($ServerInfo['gd_string'] ? 'running GD "'.$ServerInfo['gd_string'].'" so it will' : 'not running any recognized version of GD so it will not').' work)'; +$only_gd2 = '
    (only works with GD v2.0+, this server is running GD "'.($ServerInfo['gd_string'] ? $ServerInfo['gd_string'] : 'n/a').'" so it '.(($ServerInfo['gd_numeric'] >= 2) ? 'will' : 'will not').' work)'; +$only_php42 = '
    (only works with PHP v4.2.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.2.0', '>=') ? 'will' : 'will not').' work)'; +$only_php43 = '
    (only works with PHP v4.3.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.3.0', '>=') ? 'will' : 'will not').' work)'; +$only_php432 = '
    (only works with PHP v4.3.2+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.3.2', '>=') ? 'will' : 'will not').' work (correctly))'; +$only_php500 = '
    (only works with PHP v5.0.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '5.0.0', '>=') ? 'will' : 'will not').' work (correctly))'; +$php5_or_IM = '
    (only works with PHP v5.0.0+ or ImageMagick, this server is running PHP v'.phpversion().' and "'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a').'" so it '.(($ServerInfo['im_version'] && version_compare(phpversion(), '5.0.0', '>=')) ? 'will' : 'will not').' work (correctly))'; +$only_exif = '
    (only works when the EXIF extension is loaded, so on this server it '.(extension_loaded('exif') ? 'will' : 'will not').' work)'; +$only_im = '
    (requires ImageMagick, this server is running "'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a').'" so it '.($ServerInfo['im_version'] ? 'will' : 'will not').' work)'; + +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200'), 'description' => 'width=200px'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&q=10'), 'description' => 'width=200px, JPEGquality=10%'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['watermark'].'&w=400&aoe=1&bg=ffffff'), 'description' => 'width=400px, AllowOutputEnlargement enabled'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=250&sx=600&sy=5&sw=100&sh=100&aoe=1'), 'description' => 'section from (600x5 - 700x105) cropped and enlarged by 250%, AllowOutputEnlargement enabled'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.urlencode('http://silisoftware.com/images/SiliSoft.gif').'&w=100'), 'description' => 'HTTP source image'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&fltr[]=wmi|'.$img['watermark'].'|BL'), 'description' => 'width=200px, watermark (bottom-left, 75% opacity)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&fltr[]=wmi|'.$img['watermark'].'|*|25'), 'description' => 'width=200px, watermark (tiled, 25% opacity)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=png', $phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=gif', $phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=jpeg'), 'description' => 'source image (GIF) transpancy with transparent output (PNG, GIF) vs. specified background color (JPEG)'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['anigif'], $phpThumbBase.'src='.$img['anigif'].'&w=25&f=gif', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=png', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=ico', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=bmp', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=jpeg'), 'description' => 'resize animated GIF. Notice how output format affects the result: GIF is animated and transparent; PNG and ICO are tranparent but not animated (first frame is rendered as a still image); JPEG and BMP are neither transparent nor animated. Any filters will disable animated resizing (may be fixed in a future version).
    '.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['alpha'].'&f=png', $phpThumbBase.'src='.$img['alpha'].'&f=ico', $phpThumbBase.'src='.$img['alpha'].'&f=gif', $phpThumbBase.'src='.$img['alpha'].'&f=jpeg'), 'description' => 'PNG alpha transparency test, using test image from the PNG transparency test page'.$only_php432); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=usm|80|0.5|3'), 'description' => 'normal vs. unsharp masking at default settings'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=blur|1', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=blur|5'), 'description' => 'normal vs. blur at default (1) and heavy (5)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gblr', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sblr'), 'description' => 'normal vs. gaussian blur vs. selective blur'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=L&bg=0000FF&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['landscape'].'&w=100&h=100&far=T&bg=FF0000&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=C&bg=0000FF&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['landscape'].'&w=100&h=100&far=B&bg=FF0000&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=R&bg=0000FF&f=png&fltr[]=bord|1'), 'description' => 'Forced Aspect Ratio, colored background, PNG output'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=150&ar=L', $phpThumbBase.'src='.$img['landscape'].'&w=150&ar=L'), 'description' => 'auto-rotate counter-clockwise to landscape from portrait & lanscape'.$only_php42.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&hp=100&wl=200', $phpThumbBase.'src='.$img['landscape'].'&hp=100&wl=200'), 'description' => 'auto-selection of W and H based on source image orientation'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['unrotated'].'&w=150&h=150', $phpThumbBase.'src='.$img['unrotated'].'&w=150&h=150&ar=x'), 'description' => 'original image vs. auto-rotated based on EXIF data'.$only_php42.$only_exif.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&ra=30&bg=0000FF', $phpThumbBase.'src='.$img['landscape'].'&w=200&ra=30&f=png', $phpThumbBase.'src='.$img['alpha'].'&ra=30&f=png', $phpThumbBase.'src='.$img['alpha'].'&ra=30&f=gif'), 'description' => 'Rotated 30° (counter-clockwise), width=200px, blue background vs. transparent background vs. rotated image with pre-existing alpha'.$only_php42.$only_gd); +//$Examples[] = array('getstrings' => array($phpThumbBase.'src=images/1-bit.gif&ra=30&f=png', $phpThumbBase.'src=images/4-bit.gif&ra=30&f=png', $phpThumbBase.'src=images/8-bit.gif&ra=30&f=png'), 'description' => '2-color, 16-color, 256-color transparent GIFs'.$only_php42.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&h=300&far=1&bg=CCCCCC', $phpThumbBase.'src='.$img['landscape'].'&w=200&h=300&iar=1'), 'description' => 'Normal resize behavior (left) vs. Forced non-proportional resize (right)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=150&h=150&zc=1', $phpThumbBase.'src='.$img['portrait'].'&w=150&h=150&zc=1'), 'description' => 'Zoom-Crop'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bord|2|20|10|009900&f=png'), 'description' => '2px border, curved border corners (20px horizontal radius, 10px vertical radius)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ric|50|20&f=png'), 'description' => 'curved border corners (20px vertical radius, 50px horizontal radius)
    '.$png_alpha.$only_gd2.$only_php432); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sat|75', $phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sat|-100'), 'description' => 'saturation -75% vs. normal vs. -100%'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ds|75', $phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ds|-100'), 'description' => 'desaturated 75% vs. normal vs. -100%'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=clr|25|00FF00'), 'description' => 'colorized 25% to green (#00FF00)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gray', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sep'), 'description' => 'grayscale vs. sepia'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask3'].'&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask1'].'&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask2'].'&f=jpeg&bg=9900CC&q=100'), 'description' => 'Assorted alpha masks (seen below) applied
    '.$png_alpha.$only_php432.'
    JPEG/GIF output is flattened to "bg" background color'.$only_gd2.'
    '); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=drop|5|10|000000|225&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask3'].'&fltr[]=drop|5|10|000000|225&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=drop|5|10|000000|225&fltr[]=elip&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&fltr[]=drop|5|10|000000|225&f=png'), 'description' => 'Drop shadow. Note how the order in which filters are applied matters.'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&f=jpeg&bg=00FFFF'), 'description' => 'Elipse
    '.$png_alpha.$only_php432.'
    JPEG/GIF output is flattened to "bg" background color'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|x', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|y', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|xy'), 'description' => 'flipped on X, Y and X+Y axes'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bvl|10|FFFFFF|000000', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bvl|10|000000|FFFFFF'), 'description' => '10px bevel edge filter'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=fram|3|2|CCCCCC|FFFFFF|000000', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=fram|3|2|CC9966|333333|CCCCCC'), 'description' => '3+2px frame filter'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=neg'), 'description' => 'Negative filter (inverted color)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=th|105', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask1'].'&fltr[]=th|105&f=png'), 'description' => 'Threshold filter; showing preserved alpha channel'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=150', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=rcd|16|1', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=rcd|16|0', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=gray&fltr[]=rcd|8|1'), 'description' => 'ReduceColorDepth filter; original vs. 16-color dither vs. 16-color nodither vs. 4-gray dither'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['levels'].'&w=200', $phpThumbBase.'src='.$img['levels'].'&w=200&fltr[]=lvl'), 'description' => 'original vs. Levels filter (default settings)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=200', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=wb', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=wb&fltr[]=lvl'), 'description' => 'original vs. White Balance vs. White Balance + Levels'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=hist|rgb', $phpThumbBase.'src='.$img['levels'].'&w=200&fltr[]=hist|*'), 'description' => 'histograms of RGB vs. grayscale'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=edge'), 'description' => 'Edge Detect filter'.$php5_or_IM.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=emb'), 'description' => 'Emboss filter'.$php5_or_IM.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=mean'), 'description' => 'Mean Removal filter'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=smth'), 'description' => 'Smooth filter'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gam|0.6', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gam|1.6'), 'description' => 'Gamma corrected to 0.6 vs. 1.6'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=brit|50', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=brit|-50'), 'description' => 'Brightness filter (original vs. +50 vs. -50)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=cont|50', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=cont|-50'), 'description' => 'Contrast filter (original vs. +50 vs. -50)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=over|'.$img['frame1'].'|0', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=over|'.$img['frame2'].'|1'), 'description' => 'Overlay vs. Underlay

    Original over/under images:
    '.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|phpThumb|18|C|FF0000|loki.ttf|100|5|20&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|copyright+'.date('Y').'|3|BR|00FFFF||50&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|copyright+'.date('Y').'%0AphpThumb()|3|L|00FFFF&f=png'), 'description' => 'Text overlay, TTF and built-in fonts, multiple lines, metacharacters (height, width)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|thumbnail+=+^Xx^Y|3|BR|00FFFF||50&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|click%0Ahere%0A^FkkB|10|L|FF00FF|arial.ttf|100|0||333399|50|y&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|resized:+^Xx^Y+to+^xx^y|10|B|FFFFFF|arial.ttf|100|0||000000|100|x&f=png'), 'description' => 'metacharacters (height, width), background color, background extend'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'new=FF0000&w=100&h=50&fltr[]=bvl|10&fltr[]=wmt|hello|14|C|00FFFF|arial.ttf&f=png', $phpThumbBase.'new=FF0000|25&w=150&h=50&fltr[]=bvl|10&fltr[]=wmt|25%+opaque|14|C|0066FF|arial.ttf&f=png'), 'description' => 'Image created with "new", red background, bevel, TTF text'.$only_gd); + +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['bmp'].'&w=200'), 'description' => 'BMP source, width=200px'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['tiff'], $phpThumbBase.'src='.$img['tiff'].'&w=200&aoe=1'), 'description' => 'TIFF source, width=200px'.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['wmf'].'&w=200'), 'description' => 'WMF source, width=200px'.$only_im); +//$Examples[] = array('getstrings' => array(''), 'description' => ''); + +foreach ($Examples as $key => $ExamplesArray) { + echo '#'.$key.''; + echo '
    '; + foreach ($ExamplesArray['getstrings'] as $dummy => $GETstring) { + echo ''; + echo ''; + echo ' '; + } + echo '
    '; + echo '<img src="'.implode('">'."\n".'<img src="', $ExamplesArray['getstrings']).'">'; + echo $ExamplesArray['description'].'
    '; + echo '


    '; +} + +echo '#pathinfo'; +echo '
    '; +echo ''; +echo '
    '; +echo '<img src="../phpThumb.php/fltr[]=sep;200x200;'.$img['portrait'].'">'; +echo 'PATH_INFO example
    '; +echo '


    '; + +?> + + +
    + + + + + + + + + + + + + + + + +
    + Illustration of potential difference between GD1.x and GD2.x
    + In most cases the thumbnails produced by phpThumb() on GD v1.x are perfectly + acceptable, but in some cases it may look ugly. Diagonal lines and reducing a + very large source image increase chance for bad results (the house/sky picture + has both problems). Here are three static examples: +
    GD v2.0.15kayak.jpg generated with phpThumb() on GD v2.0.15bottle.jpg generated with phpThumb() on GD v2.0.15sky.jpg generated with phpThumb() on GD v2.0.15
    GD v1.6.2kayak.jpg generated with phpThumb() on GD v1.6.2bottle.jpg generated with phpThumb() on GD v1.6.2sky.jpg generated with phpThumb() on GD v1.6.2

    +
    +
    + +Demo of phpThumb.demo.showpic.php
    +
    +Small picture (400x300), window opened at wrong size (640x480):
    + +
    +
    +Big picture (2272x1704), window opened at wrong size (640x480):
    + +
    +
    +
    + +'; +foreach ($img as $key => $value) { + echo '
  • '.basename($value).'
  • '; +} +echo '
    '; + +?> + + \ No newline at end of file diff --git a/site/retailers/phpthumb/demo/phpThumb.demo.object.php b/site/retailers/phpthumb/demo/phpThumb.demo.object.php new file mode 100644 index 0000000..39ae163 --- /dev/null +++ b/site/retailers/phpthumb/demo/phpThumb.demo.object.php @@ -0,0 +1,72 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.object.php // +// James Heinrich // +// // +// Example of how to use phpthumb.class.php as an object // +// // +////////////////////////////////////////////////////////////// + +// Note: phpThumb.php is where the caching code is located, if +// you instantiate your own phpThumb() object that code is +// bypassed and it's up to you to handle the reading and +// writing of cached files. + + + +require_once('../phpthumb.class.php'); + +// create 3 sizes of thumbnail +$thumbnail_widths = array(160, 320, 640); +foreach ($thumbnail_widths as $thumbnail_width) { + + // Note: If you want to loop through and create multiple + // thumbnails from different image sources, you should + // create and dispose an instance of phpThumb() each time + // through the loop and not reuse the object. + $phpThumb = new phpThumb(); + + // set data + $phpThumb->setSourceFilename($_FILES['userfile']['tmp_name']); + // or $phpThumb->setSourceData($binary_image_data); + // or $phpThumb->setSourceImageResource($gd_image_resource); + + // set parameters (see "URL Parameters" in phpthumb.readme.txt) + $phpThumb->w = $thumbnail_width; + //$phpThumb->h = 100; + //$phpThumb->fltr[] = 'gam|1.2'; + + // set options (see phpThumb.config.php) + // here you must preface each option with "config_" + $phpThumb->config_output_format = 'jpeg'; + $phpThumb->config_imagemagick_path = '/usr/local/bin/convert'; + //$phpThumb->config_allow_src_above_docroot = true; // needed if you're working outside DOCUMENT_ROOT, in a temp dir for example + + // generate & output thumbnail + $output_filename = './thumbnails/'.basename($_FILES['userfile']['name']).'_'.$thumbnail_width.'.'.$phpThumb->config_output_format; + if ($phpThumb->GenerateThumbnail()) { // this line is VERY important, do not remove it! + if ($output_filename) { + if ($phpThumb->RenderToFile($output_filename)) { + // do something on success + echo 'Successfully rendered:
    '; + } else { + // do something with debug/error messages + echo 'Failed (size='.$thumbnail_width.'):
    '.implode("\n\n", $phpThumb->debugmessages).'
    '; + } + } else { + $phpThumb->OutputThumbnail(); + } + } else { + // do something with debug/error messages + echo 'Failed (size='.$thumbnail_width.'):
    '.implode("\n\n", $phpThumb->debugmessages).'
    '; + } + + // remember to unset the object each time through the loop + unset($phpThumb); +} + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/demo/phpThumb.demo.random.php b/site/retailers/phpthumb/demo/phpThumb.demo.random.php new file mode 100644 index 0000000..40e3209 --- /dev/null +++ b/site/retailers/phpthumb/demo/phpThumb.demo.random.php @@ -0,0 +1,95 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.random.php // +// James Heinrich // +// // +// Display a random image from a specified directory. // +// Run with no parameters for usage instructions. // +// // +////////////////////////////////////////////////////////////// + +function SelectRandomImage($dirname='.', $portrait=true, $landscape=true, $square=true) { + // return a random image filename from $dirname + // the last 3 parameters determine what aspect ratio of images + // may be returned + $possibleimages = array(); + if ($dh = opendir($dirname)) { + while ($file = readdir($dh)) { + if (is_file($dirname.'/'.$file) && eregi('\.(jpg|jpeg|gif|png|tiff|bmp)$', $file)) { + if ($gis = @GetImageSize($dirname.'/'.$file)) { + if ($portrait && ($gis[0] < $gis[1])) { + // portrait + $possibleimages[] = $file; + } elseif ($landscape && ($gis[0] > $gis[1])) { + // landscape + $possibleimages[] = $file; + } elseif ($square) { + // square + $possibleimages[] = $file; + } + } + } + } + closedir($dh); + } + if (empty($possibleimages)) { + return false; + } + if (phpversion() < '4.2.0') { + mt_srand(time()); + } + $randkey = mt_rand(0, count($possibleimages) - 1); + return realpath($dirname.'/'.$possibleimages[$randkey]); +} + +if (@$_REQUEST['dir']) { + if (is_dir($_REQUEST['dir'])) { + + if (!@$_REQUEST['o']) { + $_REQUEST['o'] = 'PLS'; + } + $_REQUEST['o'] = strtoupper($_REQUEST['o']); + $portrait = (strpos(@$_REQUEST['o'], 'P') !== false); + $landscape = (strpos(@$_REQUEST['o'], 'L') !== false); + $square = (strpos(@$_REQUEST['o'], 'S') !== false); + $randomSRC = SelectRandomImage($_REQUEST['dir'], $portrait, $landscape, $square); + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + $randomSRC = str_replace('\\', '/', eregi_replace('^'.realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath($randomSRC))); + } else { + $randomSRC = str_replace(realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath($randomSRC)); + } + + $otherParams = array(); + foreach ($_GET as $key => $value) { + if (($key == 'dir') || ($key == 'o')) { + continue; + } + if (is_array($value)) { + foreach ($value as $vkey => $vvalue) { + $otherParams[] = urlencode($key).'['.urlencode($vkey).']='.urlencode($vvalue); + } + } else { + $otherParams[] = urlencode($key).'='.urlencode($value); + } + } + header('Location: ../phpThumb.php?src='.urlencode($randomSRC).'&'.implode('&', $otherParams)); + exit; + + } else { + die($_REQUEST['dir'].' is not a directory'); + } + +} else { + + echo 'Usage: '.basename($_SERVER['PHP_SELF']).'?dir=<directory>&<phpThumb parameters>&o=(P|L|S)

    Examples:
      '; + echo '
    • '.basename($_SERVER['PHP_SELF']).'?./images/&o=L (landscape images only)
    • '; + echo '
    • '.basename($_SERVER['PHP_SELF']).'?./images/&o=PS (portrait or square images only)
    • '; + echo '
    '; + +} + +?> diff --git a/site/retailers/phpthumb/demo/phpThumb.demo.showpic.php b/site/retailers/phpthumb/demo/phpThumb.demo.showpic.php new file mode 100644 index 0000000..e7162f3 --- /dev/null +++ b/site/retailers/phpthumb/demo/phpThumb.demo.showpic.php @@ -0,0 +1,98 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +// // +// phpThumb.demo.showpic.php // +// James Heinrich // +// 23 Feb 2004 // +// // +// This code is useful for popup pictures (e.g. thumbnails // +// you want to show larger, such as a larger version of a // +// product photo for example) but you don't know the image // +// dimensions before popping up. This script displays the // +// image with no window border, and resizes the window to // +// the size it needs to be (usually better to spawn it // +// large (600x400 for example) and let it auto-resize it // +// smaller), and if the image is larger than 90% of the // +// current screen area the window respawns itself with // +// scrollbars. // +// // +// Usage: // +// window.open('showpic.php?src=big.jpg&title=Big+picture', // +// 'popupwindowname', // +// 'width=600,height=400,menubar=no,toolbar=no') // +// // +// See demo linked from http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +?> + + + + <?php echo @$_GET['title']; ?> + + + + +'."\n"; + echo 'if (((screen.width * 1.1) > '.$imgdata[0].') || ((screen.height * 1.1) > '.$imgdata[1].')) {'."\n"; + // screen is large enough to fit whole picture on screen with 10% margin + echo 'document.writeln(\'\');'; + echo 'CrossBrowserResizeInnerWindowTo('.$imgdata[0].', '.$imgdata[1].');'."\n"; + echo '} else {'."\n"; + // image is too large for screen: add scrollbars by putting the image inside an IFRAME + echo 'document.writeln(\'\');'; + echo '}'."\n"; + echo ''; + +} else { + + // cannot determine correct window size, or correct size too large: add scrollbars by putting the image inside an IFRAME + echo ''; + +} + +?> + + \ No newline at end of file diff --git a/site/retailers/phpthumb/demo/readme.demos.txt b/site/retailers/phpthumb/demo/readme.demos.txt new file mode 100644 index 0000000..483dfc1 --- /dev/null +++ b/site/retailers/phpthumb/demo/readme.demos.txt @@ -0,0 +1,41 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb() included and related demos // +// /// +////////////////////////////////////////////////////////////// + +The phpThumb() distribution includes several demos, and it +should be self-evident what they do when you run them: + +* phpThumb.demo.demo.php - shows a wide variety of samples, + basically all the different features and filters of phpThumb. + Note: sample image files are not included in the distribution + but can be downloaded from http://phpthumb.sourceforge.net/demo + +* phpThumb.demo.check.php - configuration checker, will check + your config file and server configuration and warn of any + potential problems + +* phpThumb.demo.object.php - example of how to call phpThumb + as an object. + +* phpThumb.demo.random.php - select & display a random thumbnail + from a directory of images. + +* phpThumb.demo.showpic.php - auto-resizes a popup window to + match the dimensions of the image it is displaying + + + +Other people have created useful demos and/or extensions to +phpThumb(). Some of these I know of are: + +* iManager - http://www.j-cons.com/news/ +* iBrowser - http://www.j-cons.com/news/ +* ThumbnailSelector - http://www.silisoftware.com/scripts/ThumbnailSelector + +If you know of any others you think should be mentioned here +please let me know: info@silisoftware.com \ No newline at end of file diff --git a/site/retailers/phpthumb/docs/phpthumb.changelog.txt b/site/retailers/phpthumb/docs/phpthumb.changelog.txt new file mode 100644 index 0000000..e75aa7f --- /dev/null +++ b/site/retailers/phpthumb/docs/phpthumb.changelog.txt @@ -0,0 +1,1040 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// + +¤ = structure change or important new feature +* = less important new feature or change + +v1.7.0 - February 15, 2006 + ¤ ImageMagick output is used directly far more frequently + for much improved speed and minor quality improvement. + ¤ ImageMagick now processes most of the image filters if + possible (will fall back to GD methods if unavailable) + ¤ GD support is now optional if ImageMagick is installed. + Known limitations include: + - no support for HTTP source images + - ICO output is buggy (in some ImageMagick versions) + - most &fltr[] filters don't work at all + - 'ar', 'ra', 'far' don't work + ¤ Added output support for ICO (icon) format (&f=ico). + Currently only supports single-image icons, but multi- + resolution support may be added in future versions + New file: phpthumb.ico.php + ¤ Added output support for BMP (bitmap) format (&f=bmp). + Currently only supports 24-bit RGB format (for simplicity) + ¤ Added new configuration & compatability checker + New file: demo/phpThumb.demo.check.php + * ImageMagick-generated thumbnails now have extra hidden + contents (EXIF data, etc) stripped (by using -thumbnail + instead of -resize) resulting in smaller filesizes + * Added background fill color, opacity and extent options to + 'wmt' filter (thanks craigØpc-fanatics*com) + * Added metacharacter (^*) support for 'wmt', currently: + source filesize in bytes (^Fb), kB (^Fk), MB (^Fm), + source image width (^X), source image height (^Y), + thumbnail width (^x), thumbnail height (^y) and caret (^^) + (Feature Request #1357815) + (thanks ticklemeozmoØusers*sourceforge*net) + * Moved ImageDestroy call from OutputThumbnail to end of + phpThumb.php to allow multiple calls to OutputThumbnail + * Added config_http_user_agent for site with browsersniffers + (thanks redrobØgmail*com) + * Added $PHPTHUMB_CONFIG['disable_pathinfo_parsing'] (default + false) which disables parsing $_SERVER[PATH_INFO] for + parameters. If you want to parse PATH_INFO, set to false + * Added $PHPTHUMB_CONFIG['disable_imagecopyresampled'] (default + false) which replaces ImageCopyResampled with + ImageCopyResampleBicubic for buggy PHP-GD versions + (thanks g*pelagattiØnetface*it) + * Added $PHPTHUMB_CONFIG['cache_prefix'] to allow sharing of + cache files across virtual servers (Feature Request #1395332) + (thanks doggyfrØusers*sourceforge*net) + * Added $PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] with + default=true (increased speed) to allow direct passthru of + images that don't have GD support. (Feature Request #1396446) + (thanks zedboyØusers*sourceforge*net) + * Removed $PHPTHUMB_CONFIG['cache_differentiate_offsite'] because + it is now automatically tied in with nooffsitelink_enabled + (thanks doggysworldØlibertysurf*fr) + * Removed phpThumb.demo.cacheconvert2.php + * Debug messages are now passed back from filters + * $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] now + defaults to true for much-improved cached performance + (thanks redrobØgmail*com) + * $PHPTHUMB_CONFIG['cache_differentiate_offsite'] now defaults + to false + * Added $PHPTHUMB_DEFAULTS['ar']='x' to phpThumb.config.php.default + * Added ImageDestroy($this->gdimg_source) to GenerateThumbnail() + to save memory before applying image filters + * gd_info() no longer member of phpthumb_functions + * cache files now default to using SERVER_NAME without 'www.' + * phpUnsharpMask::applyUnsharpMask() should be faster under PHP5 by + using ImageFilter(IMG_FILTER_GAUSSIAN_BLUR) when radius==1 + * Added alternate CURL method for HTTP source images if + allow_url_fopen is disabled (thanks webweberØmotiondraw*com) + * Replaced $this->osslash with DIRECTORY_SEPARATOR constant + * Bugfix: [#1398327] 'new' got broken (1x1 images) + * Bugfix: [#1412552] HTTP source images with special characters were + not getting urlencoded + * Bugfix: ImageSaveAlpha errors on GD v2.0.0 + * Bugfix: phpThumbDebug now entirely disabled if high_security=true + * Bugfix: source images with transparency lost transparency when + rotated (thanks roalklØyahoo*com) + * Bugfix: square source images were not resized when only (w|h)(p|l) + parameters passed + * Bugfix: source images are passed through unmodified in more cases + * Bugfix: ImageMagick not used on systems where it exists outside + defined open_basedir + * Bugfix: ImageMagickVersion() now returns correct versionstring + * Bugfix: ImageMagick warnings no longer cause ImageMagick to fail + * Bugfix: ErrorImage no longer fatal to phpThumbDebug + * Bugfix: "Array to string conversion" in foreach($a as $v) loops + (thanks zeeshanØtargetedmedia*co*uk) + * Bugfix: safe mode warnings in ImageCreateFromStringReplacement + (thanks adminØalex-home*net) + * Bugfix: nooffsitelink broken if !nooffsitelink_require_refer + (thanks depronØgmx*net) + * Bugfix: phpThumb failed when magic_quotes_runtime=true + (thanks stansawyerØyahoo*com) + * Bugfix: several issues with HTTP image sources + (thanks redrobØgmail*com) + * Bugfix: phpThumb_tempnam() would return incomplete temp filenames + under Windows, which may result in orphaned zero-byte temp files + in C:\ if multiple drives exist + +v1.6.2 - November 24, 2005 + ¤ Animated GIF output is now possible if ImageMagick is + available and no filters (other than resize) are applied + (thanks brandenbassØgmail*com for idea) + * Added $PHPTHUMB_CONFIG['cache_force_passthru'] to work + around cached-image-only-works-second-time issue + (thanks yakoØ11y11*com) + * Bugfix: black borders on some image edges + (thanks atelierØdelirius*ch && chuckØcatalyststudio*com) + * Bugfix: uncaught PHP warning in RenderToFile DebugMessage + * Bugfix: allow phpThumbDebug in noGD PHP installations + * Bugfix: 'hash' warning in high_security mode + (thanks bernhardØwtf*at) + * Bugfix: non-TTF rotated text watermarks now work (unrotated) + with no warnings if ImageRotate is unavailable + (thanks aparviaiØusers*sourceforge*net) + +v1.6.1 - August 26, 2005 + ¤ Filters now use GD functions where available (using + ImageFilter, only available in PHP v5.0.0+ with bundled + version of GD). Enabled for: colorize, negative, + grayscale, brightness, contrast, gaussian blur, selective + blur, mean removal (thanks donlaurØmac*com) + ¤ Added config_prefer_imagemagick (defaults=true) + ¤ Added phpthumb_filters::Grayscale() 'gray' + ¤ Added phpthumb_filters::ReduceColorDepth() 'rcd' + ¤ Added phpthumb_filters::Brightness() 'brit' + ¤ Added phpthumb_filters::Contrast() 'cont' + ¤ Added phpthumb_filters::Saturation() 'sat' + ¤ Added phpthumb_filters::EdgeDetect() 'edge' [PHP5 only] + ¤ Added phpthumb_filters::BlurGaussian() 'gblr' [PHP5 only] + ¤ Added phpthumb_filters::BlurSelective() 'gblr' [PHP5 only] + ¤ Added phpthumb_filters::MeanRemoval() 'mean' [PHP5 only] + ¤ Added phpthumb_filters::Smooth() 'smth' [PHP5 only] + * New timing debug info in phpThumbDebug + * Added config_cache_differentiate_offsite + * config_die_on_error now defaults to false + * ResolveSource works better + * cache filenames with 'fltr' parameters have changed + * Filters now skip processing if amount=0 or similar + * [#1263051] 'far' now accepts L,R,T,B,C as values giving + alignment of left/right/top/bottom/center respectively. + Old value of '1' defaults to centered + (thanks webgrappaØusers*sourceforge*net) + * Bugfix: RenderToFile() now fails properly when output format + is unknown + * Bugfix: PNG transparency wasn't working with 'far' + * Bugfix: source images with EXIF thumbnails that differ in + aspect ratio no longer use EXIF thumbnails as source unless + no other options exist + * Bugfix: setting 'src' with setParameter now invokes + setSourceFilename to properly set $this->sourceFilename + (thanks Gazou) + * Bugfix: 'zc' had poor quality when used with ImageMagick + * Bugfix: 'aoe' parameter broken when not using ImageMagick + (thanks frankieali4Øhotmail*com) + * Bugfix: fixed issue with symbolic links + (thanks hornet136Øgmail*com) + * Bugfix: config_max_source_pixels now defaults to same + calculation as used in phpThumb.config.php + (thanks vukshaØhotmail*com) + * Bugfix: Offsite cached thumbnails no longer use unique + referer (now either nothing or "_offsite") + (thanks swaayeØyahoo*com) + * Bugfix: "Unknown image type identified by “] + where is the target hex color to white balance + on, this color is what "should be" white, or light + gray. The filter attempts to maintain brightness so + any gray color can theoretically be used. If is + omitted the filter guesses based on brightest pixels + in each of RGB + ¤ Cached files are used by a Location header instead of + being passed through phpThumb.php using readfile + (thanks newtnØthrillnerds*com) + * Added 'cache_source_filemtime_ignore_local' and + 'cache_source_filemtime_ignore_remote' configurations + to ignore source modification and/or removal + (thanks raynerapeØgmail*com) + * Added 'md5s' parameter, which is the MD5 hash of the + source image -- if this parameter is passed with the + hash of the source image then the source image is not + checked for existance or modification and the cached + file is used (if available). If 'md5s' is passed an + empty string then phpThumb.php dies and outputs the + correct MD5 hash value. This parameter is the single- + file equivalent of 'cache_source_filemtime_ignore_*' + configuration paramters (thanks raynerapeØgmail*com) + * Added /demo/phpThumb.demo.object.php + * Unused parameter 'bgt' removed + * Added empty /cache/source/ directory to distribution + * Added /demo/ and /docs/ and /fonts/ directories + * Set default config_use_exif_thumbnail_for_speed = false + * Bugfix: Wrapped output buffering around all + include_once calls to prevent headers getting sent + accidentally + * Bugfix: md5_file and imagecolorallocatealpha calls + were undefined under PHP v4.1.x (thanks tomØemile*com) + * Bugfix: default 'f' parameter ('jpeg') overrode + config_output_format in object mode + (thanks mailØmmjaeger*com) + * Bugfix: suppressed error message for IIS shell_exec + errors (thanks tomØemile*com) + * Bugfix: Added PHP version check for stream_set_timeout + for HTTP sources (thanks raynerapeØgmail*com) + * Bugfix: overlay margins of 0.5-1.0 cause invalid image + dimensions error (thanks mailØmmjaeger*com) + * Bugfix: underlay margins were not working + (thanks mailØmmjaeger*com) + * Bugfix: [#1187735] EXIF thumbnails were incorrectly + output to the browser directly if requested thumbnail + exactly matched EXIF dimensions + (thanks rebootØusers*sourceforge*net) + +v1.5.2 - April 20, 2005 + ¤ phpThumb.config.php is renamed to + phpThumb.config.php.default to prevent accidental + overwriting. Please migrate your old settings to the new + file, delete your old config and rename the default to + phpThumb.config.php + ¤ Added new filters: + - 'blur' (Blur) [ex: &fltr[]=blur|] + where (0 < < 25) (default = 1) + (thanks thoensiØnetcom*no for code) + - 'hist' (Histogram) + [ex: &fltr[]=hist|||||||] + Where is the color band(s) to display, from back + to front (one or more of "rgba*" for Red Green Blue + Alpha and Grayscale respectively); + is a semicolon-seperated list of hex colors to + use for each graph band (defaults to FF0000, 00FF00, + 0000FF, 999999, FFFFFF respectively); + and are the width and height of the overlaid + histogram in pixels, or if <= 1 then percentage of + source image width/height; + is the alignment (same as for "wmi" and "wmt"); + is opacity from 0 to 100; + is the edge (and inter-tile) margin in percent + - 'over' (OVERlay/underlay image) overlays an image on + the thumbnail, or overlays the thumbnail on another + image (to create a picture frame for example) + [ex: &fltr[]=over||||] + where is the image filename; is "0" (default) + for overlay the image on top of the thumbnail or "1" + for overlay the thumbnail on top of the image; is + the margin - can be absolute pixels, or if < 1 is a + percentage of the thumbnail size [must be < 0.5] + (default is 0 for overlay and 10% for underlay); + is opacity (0 = transparent, 100 = opaque) + (thanks raynerapeØgmail*com, shabazz3Ømsu*edu) + - 'gray' (GRAYscale) [ex: &fltr[]=gray] + is an alias to 100% desaturation + * New configuration 'cache_source_directory' allows the + unprocessed source image to be cached when source is + HTTP or from a database (thanks raynerapeØgmail*com) + * Added 'cache' subdirectory to phpThumb distribution + since this is the default location for the cache + folder. + * Default value for config_error_die_on_source_failure + changed to true (thanks shabazz3Ømsu*edu) + * Added checks to make sure $this->gdimg_output is a + resource before allowing calls to RenderToFile or + OutputThumbnail + * Better error messages when phpThumb.config.php missing + * Bugfix: watermark overlay margins were wrong + * Bugfix: 'lvl' filter no longer processes if not needed + * Bugfix: off-server thumbnail error message was wrong + * Bugfix: several PHP safe mode fixes + (thanks virginiaØalertbutnotalarmed*com) + * Bugfix: cache filenames broken for filter parameters + with paths (thanks srcericØusers.sourceforge.net) + +v1.5.1 - April 06, 2005 + * Added some security upgrades: + - 'config_*' parameters cannot be passed by GETstring + - 'config_nooffsitelink_require_refer' is a new option + (disabled by default) that only allows calls to + phpThumb() from a refering domain listed in + 'config_nooffsitelink_valid_domains' + - disallowed paramters now generate an error image if + present in the GETstring + - 'high_security_enabled' if set to true enabled new + mode of verification, and requires a small function + to generate a hash for calls to phpThumb: + echo ''; + This function is supplied at the bottom of + phpThumb.config.php (thanks paulØstonie*co*uk) + ¤ Added new parameter "new" (phpThumb.php only) which can + create a new image without using "src" parameter. Set + "&new=|" where is the background hex color, + is (optional) opacity (0=transparent, 100=opaque). + (thanks mailØmmjaeger*com) + ¤ Added new filters: + - 'sep' (Sepia) [ex: &fltr[]=sep||] + where is a number between 0 and 100 for the + amount of colorization (default=50), and is + the hex color to colorize to (default=A28065). + (thanks mailØmmjaeger*com) + - 'lvl' (Levels) [ex: &fltr[]=lvl||| + where can be one of 'r', 'g', 'b', 'a' (for + Red, Green, Blue, Alpha respectively), or '*' for all + channels based on average grayscale value (default). + and are the clip points for the levels + (range = 0-255) and are set to clip 0.1% of each end + by default. Use -1 for min and/or max to invoke auto- + detect mode. Using default parameters (&fltr[]=lvl) + is similar to Auto Contrast in Adobe Photoshop. + * Bugfix: Image MIME header was incorrect for cached + images. + * Bugfix: Cache was broken for images pulled from a + database in phpThumb.php + (thanks dragutin*cvetkovicØdragontech-ltd*com) + * Bugfix: Hotlink/Offsite prevention was broken when + image was already cached. + * Bugfix: ImageMagick path was incorrect in some cases + (thanks joshgØtwcny*rr*com) + * Bugfix: ProportionalResize() in phpthumb.functions.php + had a broken check for default values + (thanks Bert*ClaeysØarinso*com) + * Bugfix: transparency now preserved for GIF & PNG input + (thanks tristanØcyrax*ch) + * Bugfix: transparency now supported for GIF output + (thanks j_ivanovØabv*bg) + * Bugfix: alpha transparency could be lost in ApplyMask() + (thanks analyzerxØgmail*com) + * Bugfix: errors on 16/32-bit BMPs + (thanks mattØhellstrominc*com) + * Bugfix: Added datestamp to cached filenames for remote + (HTTP) files, and better warning for caching + (thanks a*gambinoØabramo*it) + * Faster BMP parsing (thanks sgeppertØmail*utexas*edu) + * Added 'error_die_on_source_failure' configuration to + allow invalid source images to show an error rather + than output unmodified source image. + (thanks mindpixelØgmail*com) + * Added $phpThumb->fatalerror which will contain the + text of the fatal error if 'error_die_on_error' is + false. (thanks mindpixelØgmail*com) + +v1.5.0 - February 4, 2005 + * Added new filter parameter 'fltr' that is an array and + can apply multiple effects in sequence. Current filters + that can be called are: + - 'gam' (Gamma Correction) [ex: &fltr[]=gam|] + where can be a number >0 to 10+ (default 1.0) + - 'ds' (DeSaturate) [ex: &fltr[]=ds|] + where is a number between zero (no change) + and 100 (complete desaturation -- grayscale), or it + can be a negative number for saturation boost. + (thanks mailØmmjaeger*com) + - 'clr' (Colorize) [ex: &fltr[]=clr||] + where is a number between 0 and 100 for the + amount of colorization, and is the hex color + to colorize to. (thanks mailØmmjaeger*com) + - 'neg' (Negative) [ex: &fltr[]=neg] + inverts the color + - 'th' (ThresHold) [ex: &fltr[]=th|] (range 0-255) + every grayscale pixel brighter than is set to + white, every darker pixel is set to black + (thanks mailØmmjaeger*com) + - 'usm' (UnSharpMask) [ex: &fltr[]=usm|||] + where is the amount (default = 80), is the + radius (default = 0.5), is the threshold + (default = 3). + - 'wmi' (WaterMarkImage) + [ex: &fltr[]=wmi||||] where is the + filename of the image to overlay, is the + alignment (one of BR, BL, TR, TL, C, R, L, T, B, * + where B=bottom, T=top, L=left, R=right, C=centre, + *=tile), is opacity from 0 to 100, is the + edge (and inter-tile) margin in percent + - 'wmt' (WaterMarkText) + [ex: &fltr[]=wmt||||||||] + where: + is the text to use as a watermark, + is the font size (1-5 for built-in font, or point + size for TrueType fonts), + is the alignment (one of BR, BL, TR, TL, C, R, L, + T, B, * where B=bottom, T=top, L=left, R=right, + C=centre, *=tile), + is the hex color of the text + is the filename of the TTF file (optional, if + omitted a built-in font will be used) + is opacity from 0 to 100, + is the edge (and inter-tile) margin in percent + is the angle + (thanks mailØmmjaeger*com) + - 'flip' [ex: &fltr[]=flip|x or &fltr[]=flip|y] + flip image on X or Y axis + (thanks mailØmmjaeger*com) + - 'elip' [ex: &fltr[]=elip] + similar to rounded corners but more extreme + (thanks mailØmmjaeger*com) + - 'mask' [ex: &fltr[]=mask|filename.png] + greyscale values of mask are applied as the alpha + channel to the main image. White is opaque, black + is transparent. + - 'bvl' (BeVeL) [ex: &fltr[]=bvl|||] + where is the bevel width, is the hex color + for the top and left shading, is the hex color + for the bottom and right shading + (thanks mailØmmjaeger*com) + - 'fram' (FRAMe) draws a frame, similar to border but + more configurable (thanks mailØmmjaeger*com) + [ex: &fltr[]=fram|||||] + where is the width of the main border, is + the width of each side of the bevel part, is the + hex color of the main border, is the highlight + bevel color, is the shadow bevel color + - 'drop' (DROP shadow) + [ex: &fltr[]=drop||||] + where is distance from image to shadow, is + width of shadow fade (not yet implemented), is + the hex color of the shadow, and is the angle of + the shadow (default=225) + - 'ric' (Rounded Image Corners) + [ex: &fltr[]=ric||] + where is the horizontal corner radius, + is the vertical corner radius + * Split out filter functions into phpthumb.filters.php + * 'usa','usr','ust' parameters have been removed and + replaced with the 'fltr' call (see above) + * 'wmf','wma','wmp','wmm' parameters have been removed + and replaced with the 'fltr' call (see above) + * 'brx','bry','bw' parameters have been removed + and replaced with the 'fltr' call (see above) + * 'bw=0' to force aspect ratio has been replaced by + 'far=1' (force aspect ratio) + * Filters that produce transparent sections (such as + Rounded Corners, Ellipse, Mask, Rotate) are now output + as 32-bit/alpha PNG, or flattened with "bg" background + color for JPEG/GIF output (thanks mailØmmjaeger*com) + * Added 'zc' (Zoom Crop) parameter + (thanks arcookeØgmail*com, mailØmmjaeger*com, + pl16056Ømacnews*de, kezzasmØusers*sourceforge*net, etc) + * AutoRotate now can use EXIF orientation tag ('ar=x') + * Added 'ttf_directory' configuration parameter for + TrueType watermarks (thanks mailØmmjaeger*com) + * Added "Last-Modified" header to cache portion of + phpThumb.php which should allow better user-side + caching of thumbnails. (thanks derekØnetsimple*net) + * Added 'cache_disable_warning' configuration which will + cause an error image to be displayed if the cache + directory isn't configured, unless explicitly disabled + * Added 'nooffsitelink_enabled' configuration which + prevents linking to thumbnails on your server from + another domain. Defaults to watermaking linked images + with text warning message. + (thanks anteØabstraktmedia*com) + * Added 'error_image_width' & 'error_image_height' + config variables (thanks mailØmmjaeger*com) + * Rounded image corners now requires GD v2.0.1 and PHP + v4.3.2. Corners are transparent (for PNG output) and + antialiased. + * Rotate by arbitary angle ('ra') now has a transparent + background for PNG output + * Cached filenames now have an additional component for + applied filters + * Cached filenames now have an additional component for + HTTP referer, but only if the refering domain does not + match the domain of the server (designed to prevent + imaged linked from offsite with error message being + cached the same as the local cached version) + * Added setSourceImageResource() to allow use of an + existing GD image resource for thumbnailing + (thanks danØgonmad*co*uk) + * Now including phpThumb.demo.demo1.php (main demo page) + and phpThumb.demo.demo2.php (configurable demo page) + in the phpThumb() distribution + (thanks mailØmmjaeger*com) + * Added many more debugging/tracing message points + * Added set_time_limit(30) to phpThumb.php + * Bugfix: ImageMagick not used if `which convert` points + to a link and not a file (thanks bkainersØgmail*com) + * Bugfix: 'bgt' parameter was sometimes misspelled 'bct' + * Bugfix: 'wmm' couldn't be set to zero + * Bugfix: 'wmm' parameter was only applied to top/left of + image + * Bugfix: auto-detection of document_root failed on + Windows (thanks xbartvØhotmail*com) + * Bugfix: phpThumbDebug could be bypassed if EXIF + thumbnail present (thanks olgradinØcheckfree*com) + * Bugfix: cache file wasn't being written if EXIF data + was used directly (thanks olgradinØcheckfree*com) + * Bugfix: phpThumb.demo.showpic.php was broken by popup + blockers for images larger than the screen. + (thanks mailØmmjaeger*com) + +v1.4.11 - October 11, 2004 + * Changed sx/sy/sw/sh parameters to allow decimal values + (>0 but <1) to represent percent of source image + (thanks mordorØdefault*co*yu) + * Added config_error_silent_die_on_error for no-output + die on fatal errors (thanks johannesØformformat*se) + * Added auto-detection of probable 'document_root' if + that key is not available in $_SERVER + * Bugfix: Check `which convert` failing with error + message (thanks chadØchadshome*com) + * Bugfix: Image cropping to invalid areas outside source + image caused text output (thanks mordorØdefault*co*yu) + +v1.4.10 - August 22, 2004 + * Bugfix: cached files not written in most cases + (thanks kizerØcourtkizer*com, snuffØinbox*ru) + * Bugfix: ApacheLookupURIarray() crashes in CGI mode + (thanks hanskrentelØyahoo*de) + * Bugfix: phpthumb_bmpfile2gd() was broken + (thanks iØmindlace*net) + +v1.4.9 - August 9, 2004 + * Bugfix: changed destination filename in RenderToFile() + (thanks alextkØwalla*com) + * Bugfix: problems with HTTP image source when called as + an object (thanks alextkØwalla*com) + +v1.4.8 - August 4, 2004 + * $this->error has changed to $this->errors and is now + an array of strings (instead of a single string) + * A lot more error conditions (invalid cache directory, + etc) are now reported in $this->errors + (thanks aidan*slingsbyØlineone*net) + * Removed all define(CONSTANT) in the phpThumb() + constructor - you can now access: + - PHPTHUMB_VERSION == $this->phpthumb_version; + - PHPTHUMB_OSSLASH == $this->osslash; + - PHPTHUMB_ISWINDOWS == $this->iswindows; + * Bugfix: Error message from apache_lookup_uri() failing + under Apache2 now reported cleanly + (thanks derbaffØyahoo*com) + * Bugfix: missing phpthumb_functions:: class name for + ImageTypeToMIMEtype() call in ExtractEXIFgetImageSize() + (thanks aidan*slingsbyØlineone*net) + * Bugfix: ImageTypeToMIMEtype() was broken for PHP older + than v4.3.0 (thanks georg*schreiberØbatch-pc*es) + * Bugfix: RenderToFile() now returns false if it fails + (thanks phpthumbØsendthemtomir*com) + * Bugfix: Corrupt JPEG/PNG/GIF files that failed + ImageCreateFrom*() were not being passed to ImageMagick + for fallback, nor passed through unmodified if IM was + unavailable or failed (thanks r*chongØmogenic*net) + * Bugfix: Improved backtick safe-mode limit detection + (thanks 1Øadamcarrington*com) + * Bugfix: EXIF thumbnails were being used as source when + they should not be (thanks aidan*slingsbyØlineone*net) + * Bugfix: Cached files were not being created or used + properly (thanks aidan*slingsbyØlineone*net) + * Bugfix: max_source_pixels not set correct on some PHP + versions (thanks derbaffØyahoo*com) + * Bugfix: 'down' parameter ignored for unprocessed and + cached files (thanks aidan*slingsbyØlineone*net) + +v1.4.7 - July 27, 2004 + * Included a modified version of "module.graphic.bmp.php" + from getID3() [http://getid3.sourceforge.net] as + "phpthumb.bmp.php" for BMP reading support without + ImageMagick. It works, but it's *very* slow, especially + for large images (as in 640x480 or larger). + * Added check to prevent error messages when shell_exec + is disabled (thanks webmasterØneester*com) + +v1.4.6 - July 22, 2004 + * Added new section to phpthumb.config.php where you can + easily specify defaults for any parameter you can set + in the URL. Normally URL parameters override these + default values, unless you set + $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE to false + * Renamed phpthumb.config.php to phpThumb.config.php + since it's part of phpThumb.php, not part of + phpthumb.class.php (change of case only, will not + affect Windows servers, but will affect *nix) + * Changed cached filename of rawImageData-source images + from urlencode('') to md5(rawImageData). This should + make caching thumbnails from non-file sources more + reliable. + * Added ImageMagick debugging information + * Removed unneccesary default values from cached + filenames. This may invalidate some previously cached + files. phpthumb.demo.cacheconvert.php has been updated + to handle v1.4.1-1.4.5 => v1.4.6+ cache filenames. + * Bugfix: Cached filename did not have file-modified + datestamp when used as implmented in phpThumb.php + * Bugfix: RenderToFile() now accepts relative filenames + (thanks aidan*slingsbyØlineone*net) + * Bugfix: AllowOutputEnlargment setting was ignored when + falling back to ImageMagick + * Bugfix: IgnoreAspectRatio setting was ignored when + falling back to ImageMagick + * Bugfix: config_temp_directory was ignored in gd_info() + in PHP < v4.3.0 when phpinfo() returns no GD + information (due to safe mode restrictions) + (thanks mimyrtekØmyrtek*com) + +v1.4.5 - June 28, 2004 + * Added new parameter 'down' where you can specify a + filename and OutputThumbnail() will cause the file + to be downloaded rather than displayed in the browser. + Demo images on silisoftware.com/scripts/phpThumb/demo/ + can all be downloaded to show off this feature. + (thanks stuartscrumpØyahoo*co*uk) + * Added ability to remove old files from cache directory + based on last-access time and/or number of cached files + and/or total size of cached files + (thanks jrmhaigØyahoo*co*uk) + * Added public CleanUpCacheDirectory() for cache cleaning + (see above) if you need to call it manually + * Included new file phpThumb.demo.cacheconvert.php to + convert old-style cache names to the current (and + hopefully last!) standard naming convention. + (thanks joshgØtwcny*rr*com) + * Added configuration value 'document_root' for rare case + when $_SERVER['DOCUMENT_ROOT'] return incorrect value + (thanks joshgØtwcny*rr*com) + * Now tries to create thumbnail with ImageMagick if + ImageCreateFromJPEG etc fails, before falling back to + outputting unmodified source data. + * Bugfix: HTTP image sources were broken + (thanks fritz*weisshartØt-online*de) + * Bugfix: ImageMagick callout wasn't being used if EXIF + thumbnail was available + (thanks joshgØtwcny*rr*com) + * Bugfix: HTTP src with space in filename was broken + (thanks drØrhodes360*com) + * Bugfix: version_compare_replacement() was broken for + PHP v4.1.0+ + +v1.4.4 - June 8, 2004 + * Bugfix: network-share (Windows) source filenames were + not possible. Now works, but you must use the network + name and not a mapped drive name, for example: + \\othercomputer\file.jpg - good + \\192.168.2.1\file.jpg - good + z:\file.jpg - won't work + This is a PHP limitation (see www.php.net/file-exists) + Note: you may want to use "/" slashes instead of "\" if + you have magic_quotes_gpc enabled to avoid stripslashes + problems. + (thanks drØrhodes360*com) + * Bugfix: missing "phpthumb_functions::" in + ImageCreateFromStringReplacement() + (thanks zapletalØsoftwaremedia*cz) + +v1.4.3 - May 25, 2004 + * Added new configuration variable 'config_temp_directory' + to allow you to specify a writable directory name for + temp files if you do not have access to the system temp + directory on your server (Safe Mode restrictions etc) + (thanks nickØregenmag*com) + * Added new configuration variable + 'config_error_die_on_error' which can be set to false if + you want to retrieve the error message without having it + dumped as an image - the error message is now available + in $phpThumb->error + * Images are passed through directly with no processing + and no caching if no parameters are passed to alter the + image (resize, crop, sharpening, etc) + (thanks nchmuraØusers*sourceforge*net) + * Added new configuration variable 'config_disable_debug' + which disabled phpThumbDebug from working if you have + security concerns about the displayed information + * Bugfix: Added detection at the top of phpThumb.php for + no-GD errors to avoid parse errors later in the code + (thanks nickØregenmag*com) + * Bugfix: RoundedImageCorners() had some off-by-1 errors + (thanks ola*thunbergØhome*se) + +v1.4.2 - May 10, 2004 + * Added IE-compatability mode for transparent corners + (set 'bct=256') + * Bugfix: version_compare_replacement() was broken in PHP + older than 4.1.0 + (thanks nickØregenmag*com) + +v1.4.1.1 - May 9, 2004 + * Bugfix: Removed ImageTrueColorToPalette hack. + See http://bugs.php.net/bug.php?id=28341 + * Bugfix: 'maxb' option for PNG/GIF output incorrect + bit depth under some circumstances + +v1.4.1 - May 9, 2004 + * Added 'maxb' (MAXimum Bytes) option to auto-set the + output image quality (JPEG) or bit depth (PNG/GIF) so + that the output thumbnail is less than 'maxb' bytes + (thanks e_belleØhotmail*com) + * Added 'bgt' parameter to make rounded corners from + 'brx'/'bry' option transparent when used with PNG + output. Note: PHP/GD appears buggy at this time, so this + option must force output to 256-color mode for this + to work. The feature will be updated when a non-broken + version of PHP/GD is released. + (thanks javierØircorion*net) + * Bugfix: Caching was broken + (thanks mikeØgdaymate*nl, jurewiczØgo3*pl) + +v1.4.0 - April 30, 2004 + * Rewritten as a PHP class. Split into several files: + - phpthumb.class.php = most processing code + - phpthumb.functions.php = support functions + - phpthumb.readme.txt = usage instructions + - phpthumb.changelog.txt = this file + - phpthumb.config.php = configuration file + - phpthumb.gif.php = Non-GD GIF reading support + - phpthumb.unsharp.php = Unsharp Masking support + - phpThumb.php = demo script that works + exactly as previous versions; this is a drop-in + replacement for existing phpThumb() installations + - phpThumb.demo.showpic.php = demo script that auto- + resizes a popup window to the size of the image + shown. Useful if you want popup images but do not + know the large image size beforehand + * Added optional call-out to ImageMagick (if avaible) if + source image is larger than PHP memory restrictions + allow. ImageMagick installation should be auto-detected + under *nix, but you should configure 'imagemagick_path' + for use under Windows. + * 'max_source_pixels' is now auto-calculated from PHP + configuration settings. Due to various server-level + restrictions that may override PHP settings this + calculated value may not always be correct, and you may + have to specify the value manually. + * Added rounded-corner border option. You must specify + both 'brx' (horizontal radius) and 'bry' (vertical + radius) as well as 'bw' (border width). If 'bw' is + greater than zero, the image will be shrunk to fit + inside the border with a margin of background color. + If 'bw' is zero, the corners of the image will be + cut off and filled with background color. + (thanks javierØircorion*net) + * Minor speed improvement for unsharp masking + +v1.3.7 - March 28, 2004 + * Bugfix: GD version detection was broken on PHP <4.3.0 + on servers where phpinfo() was disabled + (thanks javierØircorion*net) + * Bugfix: Non-GD GIF support was broken on restricted + PHP configurations + (thanks javierØircorion*net) + * Bugfix: phpThumb.gif.php output error messages if PHP + was running in Safe Mode + * Added 'iar' parameter (Ignore Aspect Ratio) to allow + non-proportional resizing (stretch image to fit). + You must specify 'h' and 'w' to use this option. + (thanks javierØircorion*net) + +v1.3.6 - March 14, 2004 + * Bugfix: was broken when register_globals turned on + (thanks joshgØtwcny*rr*com) + * Bugfix: Images with transparent backgrounds now have + the background color filled with the color specified + by the 'bg' parameter + * Bugfix: ImageCreateFromString() is broken in the + non-bundled GD. Added workaround, but please use + the bundled version of GD if possible + (thanks dnØxbe*ch) + * Bugfix: EXIF thumbnail caching was broken + * Bugfix: EXIF thumbnail handling was broken for PHP + v4.2.x + (thanks smithk1Øshaw*ca) + * Bugfix: Image borders with GD2 were misaligned + * Bugfix: virtual paths/filenames like /~user/foo.jpg + should now work properly, if PHP is installed as an + Apache module (see www.php.net/apache-lookup-uri) + * Bugfix: contents of any non-image file could be + displayed (including PHP & HTML files) + (thanks arsyanØarsyan*com) + * Added rotation parameters 'ra' and 'ar' + (thanks drØrhodes360*com) + * Added $CONFIG['output_allow_enlarging'], defaulted + to false, to prevent smaller-than-max-size images + from being enlarged beyond their original size. If + you want to be able to enlarge images, set this to + false. Can be overridden with the 'aoe' parameter + (thanks dnØxbe*ch) + * Changed all configuration variables to be under one + array named $CONFIG + * Moved color and font options for ErrorImage() to + $CONFIG variables + * Changed cached filename structure (again) to a more + flexible format that can handle future expansion + (old cached files are invalid and will be recreated) + * Added more debugging code to phpThumbDebug + +v1.3.5 - February 29, 2004 + * Added capability to use EXIF thumbnail that may be + embedded in source image (often is in digital camera + JPEGs) and source image dimensions are larger than + $config_max_source_pixels. This will overcome the + limitation where PHP runs out of memory processing + large images (usually >1600x1200). EXIF thumbnail + extraction requires PHP v4.2.0 or higher and EXIF + support compiled into PHP (or php_exif extension) + * Eliminated intermediate read-file-to-memory stage if + image is created from local file. Should allow + larger images to be processed without running out of + memory. + * Added optional 'goto' parameter to be used with the + 'file' parameter, where 'goto' is a URL that is + redirected to after image is rendered to file + (thanks wimbleØwebdonors*com) + * Added optional 'xto' parameter that will bypass all + processing and just return the embedded EXIF + thumbnail, if available. + * Added error-handling if ImageTypes() is unavailable + +v1.3.4 - February 15, 2004 + * Custom error image option (&err=img.jpg) which can + also be set as $config_error_message_image_default + (thanks carlØ4thstar*net) + * &f=text will now output plain-text error messages + * ErrorImage() now used for anti-hotlink messages (if + $config_nohotlink_erase_image is true) + +v1.3.3 - February 5, 2004 + * Bugfix: Added stripslashes() to filenames if + magic_quotes_gpc is enabled + (thanks arsyanØarsyan*com) + * Output can now be rendered to a file only (not to + browser) specified by the 'file' parameter + (thanks arsyanØarsyan*com) + * JPEG quality now has a maximum of 95%, as specified + in the GD documentation + +v1.3.2.1 - February 3, 2004 + * Bugfix: gd_version() was broken for GD v2.0+ + * Bugfix: removed debugging code + +v1.3.2 - February 3, 2004 + * Bugfix: when borders are enabled, portait images + with no width constraint, or landscape images with + no height constraint were smaller than neccesary by + double the border width + (thanks jjjØxs4all*nl) + * Added unsharp mask option thanks to Torstein Hønsi: + http://www.vikjavev.com/hovudsida/umtestside.php + Note: requires GD v2.x to function + (thanks jjjØxs4all*nl) + * Updated cache filenames to reflect new parameters, + this means old cached files will need to be deleted + (or not, they just will never get called again) and + new cached versions will be created. + * Added caching to gd_info() calls for minor speedup + +v1.3.1 - February 2, 2004 + * Added optional border (width and color configurable) + (thanks arsyanØarsyan*com) + * Added option to create fixed-dimension thumbnails + regardless of source aspect ration. Set the 'bw' + (BorderWidth) parameter (even to 0) and this will be + enabled. Outside the actual image will be filled + with 'bg' color (default FFFFFF) + (thanks arsyanØarsyan*com) + +v1.3.0 - January 27, 2004 + * Added watermarking option to overlay thumbnails with + a semi-transparent watermark image (copied from a + seperate source watermark image) + (thanks arsyanØarsyan*com) + * Added option for absolute filenames (on both Windows + and *nix) outside the DOCUMENT_ROOT directory + * Added debug output dump for diagnosing problems) + +v1.2.8 - January 19, 2004 + * added ability to specify relative pathnames as well + as absolute pathnames (pathname is relative to the + location of phpThumb.php if the passed source does + not begin with "/" + +v1.2.7 - January 7, 2004 + * Added patch to allow use of PHP older than 4.1.0 + (or GD without PNG support) for non-GD GIF support + (thanks hostwebserverØhotmail*com) + +v1.2.6 - January 4, 2004 + * Added patch to allow use of PHP older than 4.1.0 + (without the superglobals arrays) + +v1.2.5 - December 26, 2003 + * Added configuration options for default output image + format and max width/height + +v1.2.4 - December 20, 2003 + * Bugfix: temp directory for non-native GD support not + always returning valid directory + * Caching feature reintroduced (see configuration) + +v1.2.3 - December 19, 2003 + * Added anti-hotlink code so the thumbnail script on + one domain cannot be used by another domain. The + list of allowed domains defaults to the current + domain but is configurable below as + $config_nohotlink_valid_domains. The message, text + size, colors and whether to blank the image or not + are also configurable + * Bugfix: URL image sources were not able to use the + non-GD GIF-reading functions + +v1.2.2 - December 17, 2003 + * Added option to use http:// URL as image source + +v1.2.1 - December 11, 2003 + * Added option to get source data from a database + rather than a physical file + * Bugfix: resize not proportional when wide image + limited more by max height than max width + Thanks mathias_strasserØgmx*net + * Removed caching code + +v1.2.0 - December 10, 2003 + * Added GIF support for versions of GD that do not + have built-in GIF support (v1.6.x) via the "GIF + Util" class by Fabien Ezber (www.yamasoft.com) + GD's built-in GIF-reading functions are faster, and + are present in PHP v4.3.0 or newer, but all versions + of GD can display resized GIF thumbnails now. + +v1.1.2 - October 26, 2003 + * check for source image existance to prevent text + error messages + * if GD not available, a GIF saying "no GD" is shown + instead of showing the original image + * Cache feature introduced + +v1.1.1 - September 28, 2003 + * better resize code by sfisher10Øcox*net + +v1.1.0 - September 1, 2003 + * initial public release + * thumbnails can now be larger than source image + * graphical error messages + +v1.0.0 - January 7, 2002 + * initial private release diff --git a/site/retailers/phpthumb/docs/phpthumb.faq.txt b/site/retailers/phpthumb/docs/phpthumb.faq.txt new file mode 100644 index 0000000..070fb99 --- /dev/null +++ b/site/retailers/phpthumb/docs/phpthumb.faq.txt @@ -0,0 +1,203 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// Frequently Asked Questions (FAQ) about phpThumb() // +// /// +////////////////////////////////////////////////////////////// + + +Q: My question isn't answered here and I can't find any + forums, how do I get support? +A: Please email me directly at info@silisoftware.com with + any questions, suggestions, donations, etc. + + +Q: What is the GPL? Can I use this for commercial sites? +A: See the GPL FAQ: http://www.gnu.org/licenses/gpl-faq.html + In general, if you just want to call phpThumb.php in the + standard manner + then there is no problem, you're free to do this no matter + if you site is commercial or not, or what license your code + is released under. + If you're calling phpThumb() as an object then you will + probably run into license issues, so consult the above FAQ + and the GPL itself. + No matter if you use phpThumb() commercially or not, no + payment is required. However, donations are always welcome + and can be made at http://phpthumb.sourceforge.net + + +Q: Some images generate thumbnails, but some fail (the original + non-resized image is output instead). +A: Your PHP installation does not have a high enough memory_limit + and ImageMagick is not installed on the server. The PHP memory + required is 5 times the number of pixels in the image. + For example: + 640x480x5 = 1.5MB + 1600x1200x5 = 9.2MB + You can adjust the PHP memory limit in php.ini (if you have + permission on your server to do so), or (better yet) install + ImageMagick on the server and that will bypass the memory limit + issue. If you can't do either of the above, you can resize the + images manually (with your favourite image editor) to a size + that your memory_limit setting can handle, and/or you can + re-save the images with an image editor that can embed an EXIF + thumbnail (Photoshop for example) which phpThumb can use as an + image source (lower image quality, but perhaps better than + nothing). + + +Q: I'm getting is this error message: + Failed: RenderToFile() failed because + !is_resource($this->gdimg_output) +A: You missed the call to GenerateThumbnail() before + RenderToFile() or OutputThumbnail. + See /demo/phpThumb.demo.object.php for an example. + + +Q: I'm trying to save a phpThumb-generated image in Internet + Explorer and it saves in BMP format, why? +A: This is not phpThumb's fault, it is an IE issue: + http://support.microsoft.com/default.aspx?scid=kb;en-us;810978 + http://support.microsoft.com/default.aspx?scid=kb;en-us;260650 + + +Q: PNG images with transparent areas show up with gray background + in the areas that are supposed to be transparent. +A: Internet Explorer has had a broken PNG alpha-channel display + implementation for a decade, so it may never get fixed. Other + major browsers generally handle alpha-transparent PNGs fine. + See http://www.silisoftware.com/png_transparency/ + For an alpha-channel PNG display in IE hack, see this page: + http://www.koivi.com/ie-png-transparency/ + + +Q: I'm getting " does not exist" when I know the + file does exist +A: Check these two values are present and properly configured + in phpThumb.config.php (introduced in v1.6.0): + $PHPTHUMB_CONFIG['allow_src_above_docroot'] (default=false) + $PHPTHUMB_CONFIG['allow_src_above_phpthumb'] (default=true) + If your images are outside DOCUMENT_ROOT then you will have + to configure 'allow_src_above_docroot' to true. + + +Q: Should I use phpThumb.php, or use phpThumb() as an object? +A: phpThumb.php is easier to use (less coding) for basic uses. + phpThumb.php handles all caching; your own object will need + to have its own caching code. If you just want to display a + thumbnailed version of an existing image, use phpThumb.php + If you want to render one (or more) thumbnails to static + files (during upload, for example), that's an appropriate + use for the object mode. Also, phpThumb.config.php is only + used by phpThumb.php, so if you instantiate your own object + you need to manually set all configuration options because + phpThumb.config.php has NO effect. So, to repeat: + **always use phpThumb.php unless you NEED to have an object** + + +Q: Are there any front-end GUI interfaces to phpThumb()? +A: See /demo/readme.demo.txt + + +Q: Are there / have there been any security issues in phpThumb? +A: http://secunia.com/product/5199/ + + +Q: Why can't Flash work with images output from phpThumb()? +A: Flash doesn't like progressive JPEG. Set: + $PHPTHUMB_CONFIG['output_interlace'] = false; + + +Q: Image quality is not very good - why? +A: If you're using GD v1.x, no way around it. Upgrade to GD v2.x + + +Q: Image quality is very bad, very pixelated -- why? +A: You may be trying to resize images larger than the available + PHP memory, so phpThumb is simply extracting and using the + EXIF thumbnail as the image source, which is usually about + 160x120 (so if you resize it to 640x480 it will look very bad). + To calculate the required size for memory_limit in php.ini, + calculate the number of pixels in the image and multiply by 5: + For example, 1600x1200 = 1600 * 1200 * 5 = 9600000 = 10M + + +Q: Can I save the generated thumbnail to a file? +A: Yes, there are several ways to do so; the best way is to call + phpThumb as an object and call RenderToFile() to save the + thumbnail to whatever filename you want. + See /demo/phpThumb.demo.object.php for an example. + The other way is to use the 'file' parameter (see + /docs/phpthumb.readme.txt) but this parameter is deprecated + and may not exist in future versions of phpThumb(). + + +Q: "Off-server thumbnailing is not allowed" -- how do I enable it? +A: By default, phpThumb() only makes thumbnails for the same domain + that it is running on. To allow it to make thumbnails for a limited + number of other domains, add them (in phpThumb.config.php) like this: + $PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array( + @$_SERVER['HTTP_HOST'], 'example.com', 'www.example.com', + 'subdomain.example.net', 'example.org'); + To disable off-server thumbnail blocking, just set: + $PHPTHUMB_CONFIG['nohotlink_enabled'] = false; + + +Q: Is it possible to set the parameters (like w/h/fltr[]) in the config, + so that they can't be changed over the URL? +A: Take a look at $PHPTHUMB_DEFAULTS at the bottom of phpThumb.config.php + You'll want to set $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE=false, + possibly also $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS=true. + You may also want to investigate $PHPTHUMB_CONFIG['high_security_enabled'] + (see the example at the bottom of phpThumb.config.php for how to call + images in HighSecurity mode. + + +Q: Is there a way to use phpThumb() object to create thumbnails without the + parameters in the URL showing the location of the image etc? +A: There is a demo in /demo/phpThumb.demo.object.php. You could modify this + into your own file, but there still remains the problem of passing + parameters to the file, whether it's phpThumb.php or your own instantiation + of a phpThumb() object. I would suggest is putting as many of the common + parameters into phpThumb.config.php as possible under $PHPTHUMB_DEFAULTS, + so you then don't have to pass them for each image. If you don't want people + modifying the parameters, turn on $PHPTHUMB_CONFIG['high_security_enabled'] + and set a password (you'll need to generate the tags with phpThumbURL() + provided at the bottom of phpThumb.config.php). If you don't want people + accessing your source images at all, you can place them outside DOCUMENT_ROOT + on your server (as long as phpThumb/PHP has read access to the directory). + The other option is to put your source images in a MySQL database and set + $PHPTHUMB_CONFIG['mysql_query'] and related parameters in phpThumb.config.php + to pull your source images from the database. That way it's impossible to + retrieve the images except through phpThumb.php, and if high_security is enabled, + then nobody can modify the parameters to view anything except what you want to show. + So, yes, it's possible to use your own object, but it's probably better to use + phpThumb.php if possible -- one notable issue is that phpThumb.php handles all + the caching, so you're on your own to deal with that if you create your own object. + + +Q: phpThumb runs slowly, as if the images aren't cached, when I use HTTP source + images (not on my server). How can I make it go faster? +A: $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; + // if true, remote source images will not be checked for modification date and + // cached image will be used if available, even if source image is changed or removed + + +Q: What does the "cache_default_only_suffix" configuration option do? +A: Cache files are normally created with big ugly names like + "phpThumb_cache_www.example.com_src1a482c2c760463795ff18faf073b389f_par3e099041c2f4a73041a7f5d7e7fc481a_dat1119952152.jpeg" + but if cache_default_only_suffix is enabled, cache filenames are simplified to + "pic_thumb.jpg" (for example). The problem is that only one version of that + thumbnail is possible, and you can never call it again with a different size, + or different filters, etc. Generally you don't want that enabled, but it's + there because some people asked for it. + + +Q: Why is the visual size of rotated images smaller than the unrotated images? +A: phpThumb fits the rotated image into the 'w' and 'h' dimensions. + Try not specifying a 'w' parameter: phpThumb.php?src=file.png&ra=15 + That should leave the image the apparent same size as the unrotated image + (in actual fact the canvas size is enlarged to fit the rotated image in it). diff --git a/site/retailers/phpthumb/docs/phpthumb.license.txt b/site/retailers/phpthumb/docs/phpthumb.license.txt new file mode 100644 index 0000000..9fec808 --- /dev/null +++ b/site/retailers/phpthumb/docs/phpthumb.license.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/site/retailers/phpthumb/docs/phpthumb.readme.txt b/site/retailers/phpthumb/docs/phpthumb.readme.txt new file mode 100644 index 0000000..01e6839 --- /dev/null +++ b/site/retailers/phpthumb/docs/phpthumb.readme.txt @@ -0,0 +1,527 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// This code is released under the GNU GPL: // +// http://www.gnu.org/copyleft/gpl.html // +// // +// +-----------------------------------------------+ // +// | phpThumb() is free to use according to the | // +// | terms of the GPL. Donations also gratefully | // +// | GPL FAQ: http://gnu.org/licenses/gpl-faq.html | // +// | | // +// | Donations are gratefully accepted from happy | // +// | users :) See http://phpthumb.sourceforge.net | // +// | | // +// | If you like phpThumb(), please consider | // +// | writing a review at HotScripts.com: | // +// | http://www.hotscripts.com/Detailed/25654.html | // +// | | // +// | If you do use this code somewhere, send me | // +// | an email and tell me how/where you used it. | // +// +-----------------------------------------------+ // +// /// +////////////////////////////////////////////////////////////// + +============ +Description: +============ + +phpThumb() uses the GD library to create thumbnails from +images (GIF, PNG or JPEG) on the fly. The output size is +configurable (can be larger or smaller than the source), +and the source may be the entire image or only a portion +of the original image. True color and resampling is used +if GD v2.0+ is available, otherwise low-color and simple +resizing is used. Source image can be a physical file on +the server or can be retrieved from a database. GIFs are +supported on all versions of GD even if GD does not have +native GIF support thanks to the GIFutil class by Fabien +Ezber. AntiHotlinking feature prevents other people from +using your server to resize their thumbnails, or link to +your images from another server. The cache feature +reduces server load. + + +====== +Usage: +====== + +Call phpThumb() just like you would a normal image. +Examples: + + +See the "demo" link on http://phpthumb.sourceforge.net +for more usage examples). Parameters that can be passed +are listed below under "URL Parameters". + +NOTE: It's recommended you use the local image filename +wherever possible (rather than http://) because performance +is much better, less (or no) use of temp files, and the +last-modified check for cached files doesn't work for +remote files. + +To access files over a LAN with Windows share names you +must use the network name (or IP) and not a mapped drive +name, for example: + //othercomputer/file.jpg - good + //192.168.2.1/file.jpg - good + z:/file.jpg - won't work +This is a PHP limitation (see www.php.net/file-exists) +Note: you may want to use "/" slashes instead of "\" if +you have magic_quotes_gpc enabled to avoid stripslashes +problems, although either slash should work if +magic_quotes_gpc is disabled + + +================================ +Alternate PATH_INFO-style Usage: +================================ + +phpThumb.php can also be called by passing parameters not +after the usual "?" but like this: + phpThumb.php/=;x; +For example: + phpThumb.php/100;pic.jpg + phpThumb.php/100;images/pic.jpg + phpThumb.php/100;/images/pic.jpg + phpThumb.php/100x200;pic.jpg + phpThumb.php/x200;pic.jpg + phpThumb.php/f=jpeg;q=50;100x200;pic.jpg + phpThumb.php/fltr[]=usm;100;pic.jpg + + must be the last item. Dimensions must be the second- +last item. As many key/value pairs for parameters can be +passed before those last two items, with each pair joined by +equals ("=") and seperated by semicolon (";") + + +============== +Configuration: +============== + +There are some configuration options you may (but are +not required to) change. Most configuration options can +be set when you call phpThumb() - see list below), but +default configuration options (such as cache directory) +are in phpThumb.config.php - this is the only file you +should ever modify. + +The configuration file is distributed as +phpThumb.config.php.default to prevent accidental +overwriting of old configuration settings. Please +migrate your old settings to the new file (if upgrading), +or delete your old config and rename the default to +phpThumb.config.php + + +The amount of memory required for phpThumb depends on +several factors: the dimensions of the source image, +the dimensions of the output image, whether unsharp +masking is applied, whether watermarks are applied, etc. +The auto-detection of memory limits works as a general +"safe" value. You may be able to exceed the auto value +by a small or large amount, depending on whether you +apply watermarks and/or sharpening, and the output size +of your thumbnails. I do not currently have a reliable +formula for calculating such things, but I will attempt +to craft one for future versions of phpThumb(). Until +then, set "max_source_pixels" in phpThumb.config.php to a +value that works well for you (or leave it alone if the +defaults give you no problems). + +The configuration options you should maybe modify are: +* cache_directory - thumbnailing is slow and processor- + intensive. Enabling caching will dramatically speed + up future thumbnail serving +* max_source_pixels - This should be auto-detected, but + if auto-detection fails and you get an invalid image + from large source images, set this to about 20% of + your available PHP memory limit. +* imagemagick_path - If the source image is larger than + max_source_pixels allows, but ImageMagick is available + phpThumb() will use it to generate the thumbnail. + + +/////////////////////////////////////////////////////////// +Note: High-Security mode is recommended enabled if possible. + Set $PHPTHUMB_CONFIG['high_security_enabled'] in + phpThumb.config.php to enable it. Each call to phpThumb + needs to be made through the function supplied at the + bottom of phpThumb.config.php which create the hash: + require_once('phpThumb.config.php'); + echo ''; +/////////////////////////////////////////////////////////// + + +============================================== +Calling as an object (not using phpThumb.php): +============================================== + +NOTE: most people don't need to and should not do this. +If you just want to display resized images, please just +use phpThumb.php, not the object mode. To render output +to one (or more) files instead of the browser, you should +skip phpThumb.php and instantiate your own object. Please +take a look at /demo/phpThumb.demo.object.php for details. + +Note: phpThumb.php is where the caching code is located, if + you instantiate your own phpThumb() object that code is + bypassed and it's up to you to handle the reading and + writing of cached files. + + +=============== +URL Parameters: +=============== + + src = filename of source image + new = create new image, not thumbnail of existing image. + Requires "w" and "h" parameters set. + [ex: &new=FF0000|75] - red background, 75% opacity + Set to hex color string of background. Opacity is + optional (defaults to 100% opaque). + w = max width of output thumbnail in pixels + h = max height of output thumbnail in pixels + wp = max width for portrait images + hp = max height for portrait images + wl = max width for landscape images + hl = max height for landscape images + ws = max width for square images + hs = max height for square images + f = output image format ("jpeg", "png", or "gif") + q = JPEG compression (1=worst, 95=best, 75=default) + sx = left side of source rectangle (default = 0) + (values 0 < sx < 1 represent percentage) + sy = top side of source rectangle (default = 0) + (values 0 < sy < 1 represent percentage) + sw = width of source rectangle (default = fullwidth) + (values 0 < sw < 1 represent percentage) + sh = height of source rectangle (default = fullheight) + (values 0 < sh < 1 represent percentage) + zc = zoom-crop. Will auto-crop off the larger dimension + so that the image will fill the smaller dimension + (requires both "w" and "h"). Set "zc=1" to enable. + (overrides both "iar" and "far") + bg = background hex color (default = FFFFFF) + bc = border hex color (default = 000000) +fltr = filter system. Call as an array as follows: + - "brit" (Brightness) [ex: &fltr[]=brit|] + where is the amount +/- to adjust brightness + (range -255 to 255) + Availble in PHP5 with bundled GD only. + - "cont" (Constrast) [ex: &fltr[]=cont|] + where is the amount +/- to adjust contrast + (range -255 to 255) + Availble in PHP5 with bundled GD only. + - "gam" (Gamma Correction) [ex: &fltr[]=gam|] + where can be a number >0 to 10+ (default 1.0) + Must be >0 (zero gives no effect). There is no max, + although beyond 10 is pretty useless. Negative + numbers actually do something, maybe not quite the + desired effect, but interesting nonetheless. + - "sat" (SATuration) [ex: &fltr[]=sat|] + where is a number between zero (no change) + and -100 (complete desaturation = grayscale), or it + can be any positive number for increased saturation. + - "ds" (DeSaturate) [ex: &fltr[]=ds|] + is an alias for "sat" except values are inverted + (positive values remove color, negative values boost + saturation) + - "gray" (Grayscale) [ex: &fltr[]=gray] + remove all color from image, make it grayscale + - "th" (Threshold) [ex: &fltr[]=th|] + makes image greyscale, then sets all pixels brighter + than (range 0-255) to white, and all pixels + darker than to black + - "rcd" (Reduce Color Depth) [ex: &fltr[]=rcd||] + where is the number of colors (2-256) you want + in the output image, and is "1" for dithering + (deault) or "0" for no dithering + - "clr" (Colorize) [ex: &fltr[]=clr||] + where is a number between 0 and 100 for the + amount of colorization, and is the hex color + to colorize to. + - "sep" (Sepia) [ex: &fltr[]=sep||] + where is a number between 0 and 100 for the + amount of colorization (default=50), and is + the hex color to colorize to (default=A28065). + Note: this behaves differently when applied by + ImageMagick, in which case 80 is default, and lower + values give brighter/yellower images and higher + values give darker/bluer images + - "usm" (UnSharpMask) [ex: &fltr[]=usm|||] + where is the amount (default = 80), is the + radius (default = 0.5), is the threshold + (default = 3). + - "blur" (Blur) [ex: &fltr[]=blur|] + where (0 < < 25) (default = 1) + - "gblr" (Gaussian Blur) [ex: &fltr[]=gblr] + Availble in PHP5 with bundled GD only. + - "sblr" (Selective Blur) [ex: &fltr[]=gblr] + Availble in PHP5 with bundled GD only. + - "smth" (Smooth) [ex: &fltr[]=smth|] + where is the weighting value for the matrix + (range -10 to 10, default 6) + Availble in PHP5 with bundled GD only. + - "lvl" (Levels) [ex: &fltr[]=lvl||| + where can be one of 'r', 'g', 'b', 'a' (for + Red, Green, Blue, Alpha respectively), or '*' for all + channels based on average grayscale value (default). + and are the clip points for the levels + and are set to clip 0.1% of each end by default. + (range = 0-255) and are set to clip 0.1% of each end + by default. Use -1 for min and/or max to invoke auto- + detect mode. Using default parameters (&fltr[]=lvl) + is similar to Auto Contrast in Adobe Photoshop. + - "wb" (White Balance) [ex: &fltr[]=wb|] + where is the target hex color to white balance + on, this color is what "should be" white, or light + gray. The filter attempts to maintain brightness so + any gray color can theoretically be used. If is + omitted the filter guesses based on brightest pixels + in each of RGB + - "hist" (Histogram) + [ex: &fltr[]=hist|||||||] + Where is the color band(s) to display, from back + to front (one or more of "rgba*" for Red Green Blue + Alpha and Grayscale respectively); + is a semicolon-seperated list of hex colors to + use for each graph band (defaults to FF0000, 00FF00, + 0000FF, 999999, FFFFFF respectively); + and are the width and height of the overlaid + histogram in pixels, or if <= 1 then percentage of + source image width/height; + is the alignment (same as for "wmi" and "wmt"); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent + - "over" (OVERlay/underlay image) overlays an image on + the thumbnail, or overlays the thumbnail on another + image (to create a picture frame for example) + [ex: &fltr[]=over||||] + where is the image filename; is "0" (default) + for overlay the image on top of the thumbnail or "1" + for overlay the thumbnail on top of the image; is + the margin - can be absolute pixels, or if < 1 is a + percentage of the thumbnail size [must be < 0.5] + (default is 0 for overlay and 10% for underlay); + is opacity (0 = transparent, 100 = opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + (thanks raynerapeØgmail*com, shabazz3Ømsu*edu) + - "wmi" (WaterMarkImage) + [ex: &fltr[]=wmi||||] where + is the filename of the image to overlay; + is the alignment (one of BR, BL, TR, TL, C, + R, L, T, B, *) where B=bottom, T=top, L=left, + R=right, C=centre, *=tile); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent + - "wmt" (WaterMarkText) + [ex: &fltr[]=wmt|||||||||||] + where: + is the text to use as a watermark; + Any instance of metacharacters will be replaced + with their calculated value. Currently supported: + ^Fb = source image filesize in bytes + ^Fk = source image filesize in kilobytes + ^Fm = source image filesize in megabytes + ^X = source image width in pixels + ^Y = source image height in pixels + ^x = thumbnail width in pixels + ^y = thumbnail height in pixels + ^^ = the character ^ + is the font size (1-5 for built-in font, or point + size for TrueType fonts); + is the alignment (one of BR, BL, TR, TL, C, R, L, + T, B, * where B=bottom, T=top, L=left, R=right, + C=centre, *=tile); + is the hex color of the text; + is the filename of the TTF file (optional, if + omitted a built-in font will be used); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent; + is the angle + is the hex color of the background; + is background opacity from 0 (transparent) to + 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the direction(s) in which the background is + extended (either 'x' or 'y' (or both, but both + will obscure entire image)) + Note: works with TTF fonts only, not built-in + (thanks mailØmmjaeger*com, craigØpc-fanatics*com) + - "flip" [ex: &fltr[]=flip|x or &fltr[]=flip|y] + flip image on X or Y axis + - "ric" [ex: &fltr[]=ric||] + rounds off the corners of the image (to transparent + for PNG output), where is the horizontal radius + of the curve and is the vertical radius + - "elip" [ex: &fltr[]=elip] + similar to rounded corners but more extreme + - "mask" [ex: &fltr[]=mask|filename.png] + greyscale values of mask are applied as the alpha + channel to the main image. White is opaque, black + is transparent. + - "bvl" (BeVeL) [ex: &fltr[]=bvl|||] + where is the bevel width, is the hex color + for the top and left shading, is the hex color + for the bottom and right shading + - "bord" (BORDer) [ex: &fltr[]=bord|||| + where is the width in pixels, and are + horizontal and vertical radii for rounded corners, + and is the hex color of the border + - "fram" (FRAMe) draws a frame, similar to "bord" but + more configurable + [ex: &fltr[]=fram|||||] + where is the width of the main border, is + the width of each side of the bevel part, is the + hex color of the main border, is the highlight + bevel color, is the shadow bevel color + - "drop" (DROP shadow) + [ex: &fltr[]=drop||||] + where is distance from image to shadow, is + width of shadow fade (not yet implemented), is + the hex color of the shadow, and is the angle of + the shadow (default=225) +file = if set then thumbnail will be rendered to this + filename, not output and not cached. + (Deprecated. Disabled by default since v1.6.0. + You should instantiate your own object instead) +goto = URL to redirect to after rendering image to file + * Must begin with "http://" + * Requires file parameter set + (Deprecated. Disabled by default since v1.6.0. + You should instantiate your own object instead) + err = custom error image filename instead of showing + error messages (for use on production sites) +md5s = MD5 hash of the source image -- if this parameter is + passed with the hash of the source image then the + source image is not checked for existance or + modification and the cached file is used (if + available). If 'md5s' is passed an empty string then + phpThumb.php dies and outputs the correct MD5 hash + value. This parameter is the single-file equivalent + of 'cache_source_filemtime_ignore_*' configuration + paramters + xto = EXIF Thumbnail Only - set to only extract EXIF + thumbnail and not do any additional processing + ra = Rotate by Angle: angle of rotation in degrees + positive = counterclockwise, negative = clockwise + ar = Auto Rotate: set to "x" to use EXIF orientation + stored by camera. Can also be set to "l" or "L" + for landscape, or "p" or "P" for portrait. "l" + and "P" rotate the image clockwise, "L" and "p" + rotate the image counter-clockwise. + aoe = Output Allow Enlarging - override the setting for + $CONFIG['output_allow_enlarging'] (1=on, 0=off) + ("far" and "iar" both override this and allow output + larger than input) + iar = Ignore Aspect Ratio - disable proportional resizing + and stretch image to fit "h" & "w" (which must both + be set). (1=on, 0=off) (overrides "far") + far = Force Aspect Ratio - image will be created at size + specified by "w" and "h" (which must both be set). + Alignment: L=left,R=right,T=top,B=bottom,C=center + BL,BR,TL,TR use the appropriate direction if the + image is landscape or portrait. +maxb = MAXimum Byte size - output quality is auto-set to + fit thumbnail into "maxb" bytes (compression + quality is adjusted for JPEG, bit depth is adjusted + for PNG and GIF) +down = filename to save image to. If this is set the + browser will prompt to save to this filename rather + than display the image + + + +============== +General Notes: +============== + +* Always use the local image filename wherever possible + rather than a full http:// URL because performance is + much better, less (or no) use of temp files, and the + last-modified check for cached files doesn't work for + remote files. For example: + good: phpThumb.php?src=/images/nicepic.jpg + bad: phpThumb.php?src=/home/httpd/example/images/nicepic.jpg + worse: phpThumb.php?src=http://example.com/images/nicepic.jpg + +* Thumbnails will be scaled proportionately to fit in a + box of at most (width * height) pixels + (unless "iar" is set) + +* Thumbnail caching for URL or database sources requires + an absolute directory name for $config_cache_directory + Physical file cached thumbnails will be recreated if + the source file changes, but remote/database files + cannot (modification time isn't readily available) + +* If you need a GUI interface to phpThumb(), or for a user + to specify crop settings, or something like that please + see the list of known programs in /demo/readme.demos.txt + +* Cropping images can be specified with either exact pixel + values for sx/sy/sw/sh parameters, or if those are set + to a value >0 and <1 then these are interpreted as a + percentage of the source image width/height. For example, + to crop 25% off all sides, you would specify parameters: + phpThumb.php?src=pic.jpg&sx=.25&sy=.25&sw=.5&sh=.5 + +* phpThumb() may have tempfile access issues on servers + where Safe Mode is enabled, specificly when accessing + a file over HTTP, or when a non-bundled version of GD + is in use. Specifying "config_temp_directory" may help + +* Properly resolving /~user/ style filenames requires + apache_lookup_uri(), which is missing or broken in + Apache2, or if PHP is not installed as an Apache module. + phpThumb() does try and work around this if it is + unavailble, but you may have to specify a full filename + for "src" if you encounter problems. + +* phpThumb() should work with PHP v4.0.6+, but seems to + have a few quirks before v4.1.0 + EXIF thumbnail extraction requires PHP v4.2.0+ + Image rotation requires PHP v4.3.0+. There have been + reports of problems with PHP older than v4.3.3 + Some image filters require PHP v5.0.0+ + Run /demo/phpThumb.demo.check.php to examine your server + +* phpThumb() works better and faster when ImageMagick is + available. Most functions will work with only GD2, but + speed is much faster with ImageMagick, and much larger + images can be processed with ImageMagick than GD. + +* phpThumb() works with GD v1.x, but works better with + GD v2.0+ because of the true-color image support + and ImageCopyResampled(). Also, there appears to be a + bug in ImageCopyResized() which is used with GD v1.x + where the bottom and/or right line of pixels is set + to the background color (due to a rounding error?) + NOTE: Please use the bundled version of GD if at all + possible (with PHP v4.3.0+) because the non-bundled + version has bugs which may cause PHP to crash: + * http://bugs.php.net/bug.php?id=21518 + * http://bugs.php.net/bug.php?id=24174 + phpThumb() has a workaround for the above bug but + there may be other bugs, and the workaround is slow. + Alpha transparent output requires GD >= 2.0.1 and + PHP >= 4.3.2 + Most (if not all) filters require GD v2.x to function + at all. But many filters can be handled by ImageMagick + instead of GD. + +* Filters handled by ImageMagick or GD: + - brit;cont;ds;sat;gray;clr;sep;gam;neg;th;rcd;flip;edge; + emb;lvl;blur;gblr;usm; +* Filters handled only by ImageMagick: + - none yet +* Filters handled only by GD + PHP5: + - sblr;mean;smth; +* Filters handled only by GD2: + - bvl;wmi;wmt;over;wb;hist;fram;drop;mask;elip;ric;bord; diff --git a/site/retailers/phpthumb/fonts/readme.txt b/site/retailers/phpthumb/fonts/readme.txt new file mode 100644 index 0000000..2e5ef72 --- /dev/null +++ b/site/retailers/phpthumb/fonts/readme.txt @@ -0,0 +1,5 @@ +This is the default location for TTF fonts. + +You can safely delete or ignore this directory if you're not using +TTF fonts for text watermarks. You can also specify an alternate +directory in phpThumb.config.php \ No newline at end of file diff --git a/site/retailers/phpthumb/index.php b/site/retailers/phpthumb/index.php new file mode 100644 index 0000000..a722861 --- /dev/null +++ b/site/retailers/phpthumb/index.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/site/retailers/phpthumb/lee.jpg b/site/retailers/phpthumb/lee.jpg new file mode 100644 index 0000000..dcc65fb Binary files /dev/null and b/site/retailers/phpthumb/lee.jpg differ diff --git a/site/retailers/phpthumb/phpThumb.config.php b/site/retailers/phpthumb/phpThumb.config.php new file mode 100644 index 0000000..2a0a8ce --- /dev/null +++ b/site/retailers/phpthumb/phpThumb.config.php @@ -0,0 +1,241 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!file_exists(dirname(__FILE__).'/phpthumb.functions.php') || !include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once(phpthumb.functions.php) - realpath="'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'"'); +} +ob_end_clean(); + +// START USER CONFIGURATION SECTION: + +// * DocumentRoot configuration +// phpThumb() depends on $_SERVER['DOCUMENT_ROOT'] to resolve path/filenames. This value is usually correct, +// but has been known to be broken on some servers. This value allows you to override the default value. +// Do not modify from the auto-detect default value unless you are having problems. +//$PHPTHUMB_CONFIG['document_root'] = '/home/httpd/httpdocs'; +//$PHPTHUMB_CONFIG['document_root'] = 'c:\\webroot\\example.com\\www'; +//$PHPTHUMB_CONFIG['document_root'] = $_SERVER['DOCUMENT_ROOT']; +//$PHPTHUMB_CONFIG['document_root'] = realpath((@$_SERVER['DOCUMENT_ROOT'] && file_exists(@$_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'])) ? $_SERVER['DOCUMENT_ROOT'] : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', realpath('.')))); +$PHPTHUMB_CONFIG['document_root'] = realpath((getenv('DOCUMENT_ROOT') && ereg('^'.preg_quote(realpath(getenv('DOCUMENT_ROOT'))), realpath(__FILE__))) ? getenv('DOCUMENT_ROOT') : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__)))); + +// * Cache directory configuration (choose only one of these - leave the other lines commented-out): +// Note: this directory must be writable (usually chmod 777 is neccesary) for caching to work. +// If the directory is not writable no error will be generated but caching will be disabled. +$PHPTHUMB_CONFIG['cache_directory'] = dirname(__FILE__).'/cache/'; // set the cache directory relative to the phpThumb() installation +//$PHPTHUMB_CONFIG['cache_directory'] = $PHPTHUMB_CONFIG['document_root'].'/phpthumb/cache/'; // set the cache directory to an absolute directory for all source images +//$PHPTHUMB_CONFIG['cache_directory'] = './cache/'; // set the cache directory relative to the source image - must start with '.' (will not work to cache URL- or database-sourced images, please use an absolute directory name) +//$PHPTHUMB_CONFIG['cache_directory'] = null; // disable thumbnail caching (not recommended) + +$PHPTHUMB_CONFIG['cache_disable_warning'] = false; // If [cache_directory] is non-existant or not writable, and [cache_disable_warning] is false, an error image will be generated warning to either set the cache directory or disable the warning (to avoid people not knowing about the cache) + + +// * Cache culling: phpThumb can automatically limit the contents of the cache directory +// based on last-access date and/or number of files and/or total filesize. + +//$PHPTHUMB_CONFIG['cache_maxage'] = null; // never delete cached thumbnails based on last-access time +$PHPTHUMB_CONFIG['cache_maxage'] = 86400 * 30; // delete cached thumbnails that haven't been accessed in more than [30 days] (value is maximum time since last access in seconds to avoid deletion) + +//$PHPTHUMB_CONFIG['cache_maxsize'] = null; // never delete cached thumbnails based on byte size of cache directory +$PHPTHUMB_CONFIG['cache_maxsize'] = 10 * 1024 * 1024; // delete least-recently-accessed cached thumbnails when more than [10MB] of cached files are present (value is maximum bytesize of all cached files) + +//$PHPTHUMB_CONFIG['cache_maxfiles'] = null; // never delete cached thumbnails based on number of cached files +$PHPTHUMB_CONFIG['cache_maxfiles'] = 200; // delete least-recently-accessed cached thumbnails when more than [500] cached files are present (value is maximum number of cached files to keep) + + +// * Source image cache configuration +$PHPTHUMB_CONFIG['cache_source_enabled'] = false; // if true, source images obtained via HTTP are cached to $PHPTHUMB_CONFIG['cache_source_directory'] +$PHPTHUMB_CONFIG['cache_source_directory'] = dirname(__FILE__).'/cache/source/'; // set the cache directory for unprocessed source images + +// * cache source modification date configuration +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_local'] = false; // if true, local source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; // if true, remote source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed. WARNING: cached performance MUCH slower if this is set to false. + + +// * Simplified cache filename configuration +// Instead of creating unique cache filenames for all parameter combinations, create "simple" cache files (eg: "pic_thumb.jpg") +// If cache_default_only_suffix is non-empty, GETstring parameters (except 'src') are ignored and only $PHPTHUMB_DEFAULTS +// parameters (set at the bottom of phpThumb.config.php) are used for processing. +// The '*' character MUST be used to represent the source image name +$PHPTHUMB_CONFIG['cache_default_only_suffix'] = ''; // cached in normal phpThumb manner +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = '*_thumb'; // cache 'pic.jpg' becomes 'pic_thumb.jpg' (or 'pic_thumb.png' if PNG output is selected, etc) +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = 'small-*'; // cache 'pic.jpg' becomes 'small-pic.jpg' (or 'small-pic.png' if PNG output is selected, etc) + +$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache_'.str_replace('www.', '', @$_SERVER['SERVER_NAME']); +//$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache'; // allow phpThumb to share 1 set of cached files even if accessed under different servername/domains on same server + +$PHPTHUMB_CONFIG['cache_force_passthru'] = true; // if true, cached image data will always be passed to browser; if false, HTTP redirect will be used instead + + + +// * Temp directory configuration +// phpThumb() may need to create temp files. Usually the system temp dir is writable and can be used. +// Leave this value as NULL in most cases. If you get errors about "failed to open for writing" +// you should change this to a full pathname to a directory you do have write access to. +//$PHPTHUMB_CONFIG['temp_directory'] = '/tmp/'; +$PHPTHUMB_CONFIG['temp_directory'] = null; + + +// maximum number of pixels in source image to attempt to process entire image. +// If this is zero then no limit on source image dimensions. +// If this is nonzero then this is the maximum number of pixels the source image +// can have to be processed normally, otherwise the embedded EXIF thumbnail will +// be used (if available) or an "image too large" notice will be displayed. +// This is to be used for large source images (> 1600x1200) and low PHP memory +// limits. If PHP runs out of memory the script will usually just die with no output. +// To calculate this number, multiply the dimensions of the largest image +// you can process with your memory limitation (e.g. 1600 * 1200 = 1920000) +// As a general guideline, this number will be about 20% of your PHP memory +// configuration, so 8M = 1,677,722; 16M = 3,355,443; 32M = 6,710,886; etc. +if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && !defined('memory_get_usage') && !@ini_get('memory_limit')) { + // memory_get_usage() will only be defined if your PHP is compiled with the --enable-memory-limit configuration option. + $PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit +} else { + // calculate default max_source_pixels as 20% of memory limit configuration + $PHPTHUMB_CONFIG['max_source_pixels'] = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); + //$PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 1920000; // allow 1600x1200 images (2Mpx), no larger (about 10MB memory required) + //$PHPTHUMB_CONFIG['max_source_pixels'] = 3355443; // 16MB memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 3871488; // allow 2272x1704 images (4Mpx), no larger (about 16MB memory required) +} + + +// ImageMagick configuration +// If source image is larger than available memory limits as defined above in +// 'max_source_pixels' AND ImageMagick's "convert" program is available, phpThumb() +// will call ImageMagick to perform the thumbnailing of the source image to bypass +// the memory limitation. Leaving the value as NULL will cause phpThumb() to +// attempt to detect ImageMagick's presence with `which` +if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + // Windows: set absolute pathname + $PHPTHUMB_CONFIG['imagemagick_path'] = 'C:/Program Files/ImageMagick-6.2.5-Q16/convert.exe'; +} else { + // *nix: set absolute pathname to "convert", or leave as null if "convert" is in the path + //$PHPTHUMB_CONFIG['imagemagick_path'] = '/usr/local/bin/convert'; + $PHPTHUMB_CONFIG['imagemagick_path'] = null; +} + + +// * Default output configuration: +$PHPTHUMB_CONFIG['output_format'] = 'jpeg'; // default output format ('jpeg', 'png' or 'gif') - thumbnail will be output in this format (if available in your version of GD). This is always overridden by ?f=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxwidth'] = 0; // default maximum thumbnail width. If this is zero then default width is the width of the source image. This is always overridden by ?w=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxheight'] = 0; // default maximum thumbnail height. If this is zero then default height is the height of the source image. This is always overridden by ?h=___ GETstring parameter +$PHPTHUMB_CONFIG['output_interlace'] = true; // if true: interlaced output for GIF/PNG, progressive output for JPEG; if false: non-interlaced for GIF/PNG, baseline for JPEG. + +// * Error message configuration +$PHPTHUMB_CONFIG['error_image_width'] = 400; // default width for error images +$PHPTHUMB_CONFIG['error_image_height'] = 100; // default height for error images +$PHPTHUMB_CONFIG['error_message_image_default'] = ''; // Set this to the name of a generic error image (e.g. '/images/error.png') that you want displayed in place of any error message that may occur. This setting is overridden by the 'err' parameter, which does the same thing. +$PHPTHUMB_CONFIG['error_bgcolor'] = 'CCCCFF'; // background color of error message images +$PHPTHUMB_CONFIG['error_textcolor'] = 'FF0000'; // color of text in error messages +$PHPTHUMB_CONFIG['error_fontsize'] = 1; // size of text in error messages, from 1 (smallest) to 5 (largest) +$PHPTHUMB_CONFIG['error_die_on_error'] = true; // die with error message on any fatal error (recommended with standalone phpThumb.php) +$PHPTHUMB_CONFIG['error_silent_die_on_error'] = false; // simply die with no output of any kind on fatal errors (not recommended) +$PHPTHUMB_CONFIG['error_die_on_source_failure'] = true; // die with error message if source image cannot be processed by phpThumb() (usually because source image is corrupt in some way). If false the source image will be passed through unprocessed, if true (default) an error message will be displayed. + +// * Off-server Thumbnailing Configuration: +$PHPTHUMB_CONFIG['nohotlink_enabled'] = true; // If false will allow thumbnailing from any source domain +$PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' +$PHPTHUMB_CONFIG['nohotlink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nohotlink_text_message'] = 'Off-server thumbnailing is not allowed'; // text of error message + +// * Off-server Linking Configuration: +$PHPTHUMB_CONFIG['nooffsitelink_enabled'] = true; // If false will allow thumbnails to be linked to from any domain, if true only domains listed below in 'nooffsitelink_valid_domains' will be allowed. +$PHPTHUMB_CONFIG['nooffsitelink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' +$PHPTHUMB_CONFIG['nooffsitelink_require_refer'] = false; // If false will allow standalone calls to phpThumb(). If true then only requests with a $_SERVER['HTTP_REFERER'] value in 'nooffsitelink_valid_domains' are allowed. +$PHPTHUMB_CONFIG['nooffsitelink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nooffsitelink_text_message'] = 'Image taken from '.@$_SERVER['HTTP_HOST']; // text of error message + + +// * Border & Background default colors +$PHPTHUMB_CONFIG['border_hexcolor'] = '000000'; // Default border color - usual HTML-style hex color notation (overidden with 'bc' parameter) +$PHPTHUMB_CONFIG['background_hexcolor'] = 'FFFFFF'; // Default background color when thumbnail aspect ratio does not match fixed-dimension box - usual HTML-style hex color notation (overridden with 'bg' parameter) + +// * Watermark configuration +$PHPTHUMB_CONFIG['ttf_directory'] = dirname(__FILE__).'/fonts'; // Base directory for TTF font files +//$PHPTHUMB_CONFIG['ttf_directory'] = 'c:/windows/fonts'; + + +// * MySQL configuration +// You may want to pull data from a database rather than a physical file +// If so, modify the $PHPTHUMB_CONFIG['mysql_query'] line to suit your database structure +// Note: the data retrieved must be the actual binary data of the image, not a URL or filename +// see http://www.billy-corgan.com/blog/archive/000143.php for a brief tutorial on this section + +$PHPTHUMB_CONFIG['mysql_query'] = ''; +//$PHPTHUMB_CONFIG['mysql_query'] = 'SELECT `picture` FROM `products` WHERE (`id` = \''.mysql_escape_string(@$_GET['id']).'\')'; + +// These 4 values must be modified if $PHPTHUMB_CONFIG['mysql_query'] is not empty, but may be ignored if $PHPTHUMB_CONFIG['mysql_query'] is blank. +$PHPTHUMB_CONFIG['mysql_hostname'] = 'localhost'; +$PHPTHUMB_CONFIG['mysql_username'] = ''; +$PHPTHUMB_CONFIG['mysql_password'] = ''; +$PHPTHUMB_CONFIG['mysql_database'] = ''; + + +// * Security configuration +$PHPTHUMB_CONFIG['high_security_enabled'] = false; // if enabled, requires 'high_security_password' set to at least 5 characters, and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs +$PHPTHUMB_CONFIG['high_security_password'] = ''; // required if 'high_security_enabled' is true, must be at least 5 characters long +$PHPTHUMB_CONFIG['disable_debug'] = false; // prevent phpThumb from displaying any information about your system. If true, phpThumbDebug and error messages will be disabled +$PHPTHUMB_CONFIG['allow_src_above_docroot'] = false; // if true, allow src to be anywhere in filesystem; if false (default) only allow src within document_root +$PHPTHUMB_CONFIG['allow_src_above_phpthumb'] = true; // if true (default), allow src to be anywhere in filesystem; if false only allow src within sub-directory of phpThumb installation +$PHPTHUMB_CONFIG['allow_parameter_file'] = false; // if true, allow use of 'file' parameter; if false (default) the 'file' parameter is disabled/ignored +$PHPTHUMB_CONFIG['allow_parameter_goto'] = false; // if true, allow use of 'goto' parameter; if false (default) the 'goto' parameter is disabled/ignored + + +// * HTTP UserAgent configuration +//$PHPTHUMB_CONFIG['http_user_agent'] = ''; // PHP default: none +//$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; // Windows XP, Internet Explorer +$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; // Windows XP, Firefox + + +// * Compatability settings +$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] = false; // if true, $_SERVER[PATH_INFO] is not parsed. May be needed on some server configurations to allow normal behavior. +$PHPTHUMB_CONFIG['disable_imagecopyresampled'] = false; // if true, ImageCopyResampled is replaced with ImageCopyResampleBicubic. May be needed for buggy versions of PHP-GD. +$PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] = true; // if true, any image that can be parsed by GetImageSize() can be passed through; if false, only images that can be converted to GD by ImageCreateFrom(JPEG|GIF|PNG) functions are allowed + + +// * Speed optimizations configuration +$PHPTHUMB_CONFIG['prefer_imagemagick'] = true; // If true, use ImageMagick to resize thumbnails if possible, since it is usually faster than GD functions; if false only use ImageMagick if PHP memory limit is too low. +$PHPTHUMB_CONFIG['use_exif_thumbnail_for_speed'] = false; // If true, and EXIF thumbnail is available, and is larger or equal to output image dimensions, use EXIF thumbnail rather than actual source image for generating thumbnail. Benefit is only speed, avoiding resizing large image. + +// END USER CONFIGURATION SECTION + +/////////////////////////////////////////////////////////////////////////////// + +// START DEFAULT PARAMETERS SECTION +// If any parameters are constant across ALL images, you can set them here + +$PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE = true; // if true, any parameters in the URL will override the defaults set here; if false, any parameters set here cannot be overridden in the URL +$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = false; // if true, GETstring parameters will be ignored (except for 'src') and only below default parameters will be used; if false, both default and GETstring parameters will be used (depending on $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE). Will be auto-set true if !empty($PHPTHUMB_CONFIG['cache_default_only_suffix']) + +//$PHPTHUMB_DEFAULTS['w'] = 100; +//$PHPTHUMB_DEFAULTS['fltr'] = array('blur|10'); +//$PHPTHUMB_DEFAULTS['q'] = 90; + + +// END DEFAULT PARAMETERS SECTION + + + +/////////////////////////////////////////////////////////////////////////////// +// Function for generating hashed calls to phpThumb if 'high_security_enabled' +// example: +// require_once('phpThumb.config.php'); +// echo ''; + +function phpThumbURL($ParameterString) { + global $PHPTHUMB_CONFIG; + return 'phpThumb.php?'.$ParameterString.'&hash='.md5($ParameterString.@$PHPTHUMB_CONFIG['high_security_password']); +} + +/////////////////////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/phpThumb.php b/site/retailers/phpthumb/phpThumb.php new file mode 100644 index 0000000..e09a660 --- /dev/null +++ b/site/retailers/phpthumb/phpThumb.php @@ -0,0 +1,585 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.changelog.txt for recent changes // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +error_reporting(E_ALL); +ini_set('display_errors', '1'); +if (!@ini_get('safe_mode')) { + set_time_limit(60); // shouldn't take nearly this long in most cases, but with many filter and/or a slow server... +} +ini_set('magic_quotes_runtime', '0'); +if (@ini_get('magic_quotes_runtime')) { + die('"magic_quotes_runtime" is set in php.ini, cannot run phpThumb with this enabled'); +} +$starttime = array_sum(explode(' ', microtime())); + +// this script relies on the superglobal arrays, fake it here for old PHP versions +if (phpversion() < '4.1.0') { + $_SERVER = $HTTP_SERVER_VARS; + $_GET = $HTTP_GET_VARS; +} + +// instantiate a new phpThumb() object +ob_start(); +if (!include_once(dirname(__FILE__).'/phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.class.php').'")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +$phpThumb->DebugTimingMessage('phpThumb.php start', __FILE__, __LINE__, $starttime); + +// phpThumbDebug[0] used to be here, but may reveal too much +// info when high_security_mode should be enabled (not set yet) + +if (file_exists(dirname(__FILE__).'/phpThumb.config.php')) { + ob_start(); + if (include_once(dirname(__FILE__).'/phpThumb.config.php')) { + // great + } else { + ob_end_flush(); + $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); + } + ob_end_clean(); +} elseif (file_exists(dirname(__FILE__).'/phpThumb.config.php.default')) { + $phpThumb->ErrorImage('Please rename "phpThumb.config.php.default" to "phpThumb.config.php"'); +} else { + $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); +} + +if (!@$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] && empty($_GET) && !empty($_SERVER['PATH_INFO'])) { + $_SERVER['PHP_SELF'] = str_replace($_SERVER['PATH_INFO'], '', @$_SERVER['PHP_SELF']); + + $args = explode(';', substr($_SERVER['PATH_INFO'], 1)); + if (!empty($args)) { + $_GET['src'] = @$args[count($args) - 1]; + } + if (eregi('^([0-9]*)x?([0-9]*)$', @$args[count($args) - 2], $matches)) { + $_GET['w'] = $matches[1]; + $_GET['h'] = $matches[2]; + } + for ($i = 0; $i < count($args) - 2; $i++) { + @list($key, $value) = explode('=', @$args[$i]); + if (substr($key, -2) == '[]') { + $_GET[substr($key, 0, -2)][] = $value; + } else { + $_GET[$key] = $value; + } + } +} + +if (@$PHPTHUMB_CONFIG['high_security_enabled']) { + if (!@$_GET['hash']) { + $phpThumb->ErrorImage('ERROR: missing hash'); + } elseif (strlen($PHPTHUMB_CONFIG['high_security_password']) < 5) { + $phpThumb->ErrorImage('ERROR: strlen($PHPTHUMB_CONFIG[high_security_password]) < 5'); + } elseif ($_GET['hash'] != md5(str_replace('&hash='.$_GET['hash'], '', $_SERVER['QUERY_STRING']).$PHPTHUMB_CONFIG['high_security_password'])) { + $phpThumb->ErrorImage('ERROR: invalid hash'); + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[0]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '0') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +// returned the fixed string if the evil "magic_quotes_gpc" setting is on +if (get_magic_quotes_gpc()) { + $RequestVarsToStripSlashes = array('src', 'wmf', 'file', 'err', 'goto', 'down'); + foreach ($RequestVarsToStripSlashes as $dummy => $key) { + if (isset($_GET[$key])) { + $_GET[$key] = stripslashes($_GET[$key]); + } + } +} + +if (!@$_SERVER['PATH_INFO'] && !@$_SERVER['QUERY_STRING']) { + + echo 'phpThumb() v'.$phpThumb->phpthumb_version.'
    http://phpthumb.sourceforge.net

    ERROR: no parameters specified'; + unset($phpThumb); + exit; + +} + +if (@$_GET['src'] && isset($_GET['md5s']) && empty($_GET['md5s'])) { + if (eregi('^(f|ht)tps?://', $_GET['src'])) { + if ($rawImageData = phpthumb_functions::SafeURLread($_GET['src'], $error)) { + $md5s = md5($rawImageData); + } + } else { + $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($_GET['src']); + if (is_readable($SourceFilename)) { + $md5s = phpthumb_functions::md5_file_safe($SourceFilename); + } else { + $phpThumb->ErrorImage('ERROR: "'.$SourceFilename.'" cannot be read'); + } + } + if (@$_SERVER['HTTP_REFERER']) { + $phpThumb->ErrorImage('&md5s='.$md5s); + } else { + die('&md5s='.$md5s); + } +} + +if (!empty($PHPTHUMB_CONFIG)) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + if (!eregi('password', $key)) { + $phpThumb->DebugMessage('setParameter('.$keyname.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + } + } +} else { + $phpThumb->DebugMessage('$PHPTHUMB_CONFIG is empty', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[1]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '1') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +$parsed_url_referer = parse_url(@$_SERVER['HTTP_REFERER']); +if ($phpThumb->config_nooffsitelink_require_refer && !in_array(@$parsed_url_referer['host'], $phpThumb->config_nohotlink_valid_domains)) { + $phpThumb->ErrorImage('config_nooffsitelink_require_refer enabled and '.(@$parsed_url_referer['host'] ? '"'.$parsed_url_referer['host'].'" is not an allowed referer' : 'no HTTP_REFERER exists')); +} +$parsed_url_src = parse_url(@$_GET['src']); +if ($phpThumb->config_nohotlink_enabled && $phpThumb->config_nohotlink_erase_image && eregi('^(f|ht)tps?://', @$_GET['src']) && !in_array(@$parsed_url_src['host'], $phpThumb->config_nohotlink_valid_domains)) { + $phpThumb->ErrorImage($phpThumb->config_nohotlink_text_message); +} + +if ($phpThumb->config_mysql_query) { + if ($cid = @mysql_connect($phpThumb->config_mysql_hostname, $phpThumb->config_mysql_username, $phpThumb->config_mysql_password)) { + if (@mysql_select_db($phpThumb->config_mysql_database, $cid)) { + if ($result = @mysql_query($phpThumb->config_mysql_query, $cid)) { + if ($row = @mysql_fetch_array($result)) { + + mysql_free_result($result); + mysql_close($cid); + $phpThumb->setSourceData($row[0]); + unset($row); + + } else { + mysql_free_result($result); + mysql_close($cid); + $phpThumb->ErrorImage('no matching data in database.'); + } + } else { + mysql_close($cid); + $phpThumb->ErrorImage('Error in MySQL query: "'.mysql_error($cid).'"'); + } + } else { + mysql_close($cid); + $phpThumb->ErrorImage('cannot select MySQL database: "'.mysql_error($cid).'"'); + } + } else { + $phpThumb->ErrorImage('cannot connect to MySQL server'); + } + unset($_GET['id']); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[2]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '2') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if (@$PHPTHUMB_CONFIG['cache_default_only_suffix'] && (strpos($PHPTHUMB_CONFIG['cache_default_only_suffix'], '*') !== false)) { + $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = true; +} +$allowedGETparameters = array('src', 'new', 'w', 'h', 'wp', 'hp', 'wl', 'hl', 'ws', 'hs', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'zc', 'bc', 'bg', 'bgt', 'fltr', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'far', 'iar', 'maxb', 'down', 'phpThumbDebug', 'hash', 'md5s'); +foreach ($_GET as $key => $value) { + if (@$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS && ($key != 'src')) { + // disabled, do not set parameter + $phpThumb->DebugMessage('ignoring $_GET['.$key.'] because of $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS', __FILE__, __LINE__); + } elseif (in_array($key, $allowedGETparameters)) { + $phpThumb->DebugMessage('setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + $phpThumb->setParameter($key, $value); + } else { + $phpThumb->ErrorImage('Forbidden parameter: '.$key); + } +} + +if (!empty($PHPTHUMB_DEFAULTS) && is_array($PHPTHUMB_DEFAULTS)) { + $phpThumb->DebugMessage('setting $PHPTHUMB_DEFAULTS['.implode(';', array_keys($PHPTHUMB_DEFAULTS)).']', __FILE__, __LINE__); + foreach ($PHPTHUMB_DEFAULTS as $key => $value) { + if ($PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE || !isset($_GET[$key])) { + $phpThumb->DebugMessage('setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + $phpThumb->setParameter($key, $value); + } + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[3]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '3') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +//if (!@$_GET['phpThumbDebug'] && !$phpThumb->sourceFilename && !function_exists('ImageJPEG') && !function_exists('ImagePNG') && !function_exists('ImageGIF')) { +if (!@$_GET['phpThumbDebug'] && !is_file($phpThumb->sourceFilename) && !phpthumb_functions::gd_version()) { + if (!headers_sent()) { + // base64-encoded error image in GIF format + $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; + header('Content-Type: image/gif'); + echo base64_decode($ERROR_NOGD); + } else { + echo '*** ERROR: No PHP-GD support available ***'; + } + exit; +} + +// check to see if file can be output from source with no processing or caching +$CanPassThroughDirectly = true; +if ($phpThumb->rawImageData) { + // data from SQL, should be fine +} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because eregi("^(f|ht)tp\://", '.$phpThumb->src.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} elseif (!@is_file($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_file('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} elseif (!@is_readable($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_readable('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} +foreach ($_GET as $key => $value) { + switch ($key) { + case 'src': + // allowed + break; + + case 'w': + case 'h': + // might be OK if exactly matches original + break; + + case 'phpThumbDebug': + // handled in direct-passthru code + break; + + default: + // all other parameters will cause some processing, + // therefore cannot pass through original image unmodified + $CanPassThroughDirectly = false; + $UnAllowedGET[] = $key; + break; + } +} +if (!empty($UnAllowedGET)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because $_GET['.implode(';', array_unique($UnAllowedGET)).'] are set', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[4]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '4') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +function SendSaveAsFileHeaderIfNeeded() { + if (headers_sent()) { + return false; + } + global $phpThumb; + if (@$_GET['down']) { + $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $_GET['down']); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) { + $downloadfilename = trim($downloadfilename, '.'); + } + if (@$downloadfilename) { + $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: attachment; filename="'.$downloadfilename.'"', __FILE__, __LINE__); + header('Content-Disposition: attachment; filename="'.$downloadfilename.'"'); + return true; + } + } + $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: inline', __FILE__, __LINE__); + header('Content-Disposition: inline'); + return true; +} + +$phpThumb->DebugMessage('$CanPassThroughDirectly="'.intval($CanPassThroughDirectly).'" && $phpThumb->src="'.$phpThumb->src.'"', __FILE__, __LINE__); +while ($CanPassThroughDirectly && $phpThumb->src) { + // no parameters set, passthru + $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($phpThumb->src); + + // security and size checks + if ($phpThumb->getimagesizeinfo = @GetImageSize($SourceFilename)) { + $phpThumb->DebugMessage('Direct passthru GetImageSize() returned [w='.$phpThumb->getimagesizeinfo[0].';h='.$phpThumb->getimagesizeinfo[1].';t='.$phpThumb->getimagesizeinfo[2].']', __FILE__, __LINE__); + + if (!@$_REQUEST['w'] && !@$_REQUEST['wp'] && !@$_REQUEST['wl'] && !@$_REQUEST['ws'] && !@$_REQUEST['h'] && !@$_REQUEST['hp'] && !@$_REQUEST['hl'] && !@$_REQUEST['hs']) { + // no resizing needed + $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'")', __FILE__, __LINE__); + } elseif (($phpThumb->getimagesizeinfo[0] <= @$_REQUEST['w']) && ($phpThumb->getimagesizeinfo[1] <= @$_REQUEST['h']) && ((@$_REQUEST['w'] == $phpThumb->getimagesizeinfo[0]) || (@$_REQUEST['h'] == $phpThumb->getimagesizeinfo[1]))) { + // image fits into 'w'x'h' box, and at least one dimension matches exactly, therefore no resizing needed + $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" fits inside "'.@$_REQUEST['w'].'"x"'.@$_REQUEST['h'].'")', __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because resizing required (from "'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" to "'.@$_REQUEST['w'].'"x"'.@$_REQUEST['h'].'")', __FILE__, __LINE__); + break; + } + switch ($phpThumb->getimagesizeinfo[2]) { + case 1: // GIF + case 2: // JPG + case 3: // PNG + // great, let it through + break; + default: + // browser probably can't handle format, remangle it to JPEG/PNG/GIF + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because $phpThumb->getimagesizeinfo[2] = "'.$phpThumb->getimagesizeinfo[2].'"', __FILE__, __LINE__); + break 2; + } + + $ImageCreateFunctions = array(1=>'ImageCreateFromGIF', 2=>'ImageCreateFromJPEG', 3=>'ImageCreateFromPNG'); + $theImageCreateFunction = @$ImageCreateFunctions[$phpThumb->getimagesizeinfo[2]]; + if ($phpThumb->config_disable_onlycreateable_passthru || (function_exists($theImageCreateFunction) && ($dummyImage = @$theImageCreateFunction($SourceFilename)))) { + + // great + if (@is_resource($dummyImage)) { + unset($dummyImage); + } + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + if (@$_GET['phpThumbDebug']) { + $phpThumb->DebugTimingMessage('skipped direct $SourceFilename passthru', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have passed "'.$SourceFilename.'" through directly, but skipping due to phpThumbDebug', __FILE__, __LINE__); + break; + } + + SendSaveAsFileHeaderIfNeeded(); + header('Last-Modified: '.gmdate('D, d M Y H:i:s', @filemtime($SourceFilename)).' GMT'); + if ($contentType = phpthumb_functions::ImageTypeToMIMEtype(@$phpThumb->getimagesizeinfo[2])) { + header('Content-Type: '.$contentType); + } + @readfile($SourceFilename); + exit; + + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because ($phpThumb->config_disable_onlycreateable_passthru = "'.$phpThumb->config_disable_onlycreateable_passthru.'") and '.$theImageCreateFunction.'() failed', __FILE__, __LINE__); + break; + } + + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because GetImageSize() failed', __FILE__, __LINE__); + break; + } + break; +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[5]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '5') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +function RedirectToCachedFile() { + global $phpThumb, $PHPTHUMB_CONFIG; + + $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $phpThumb->cache_filename); + $nice_docroot = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($PHPTHUMB_CONFIG['document_root'], '/\\')); + + $parsed_url = @parse_url(@$_SERVER['HTTP_REFERER']); + + $nModified = filemtime($phpThumb->cache_filename); + + if ($phpThumb->config_nooffsitelink_enabled && @$_SERVER['HTTP_REFERER'] && !in_array(@$parsed_url['host'], $phpThumb->config_nooffsitelink_valid_domains)) { + + $phpThumb->DebugMessage('Would have used cached (image/'.$phpThumb->thumbnailFormat.') file "'.$phpThumb->cache_filename.'" (Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT), but skipping because $_SERVER[HTTP_REFERER] ('.@$_SERVER['HTTP_REFERER'].') is not in $phpThumb->config_nooffsitelink_valid_domains ('.implode(';', $phpThumb->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + + } elseif ($phpThumb->phpThumbDebug) { + + $phpThumb->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__); + $phpThumb->DebugMessage('* Would have sent headers (1): Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT', __FILE__, __LINE__); + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + $phpThumb->DebugMessage('* Would have sent headers (2): Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__); + } + if (ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { + $phpThumb->DebugMessage('* Would have sent headers (3): Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])), __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('* Would have sent data: readfile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + SendSaveAsFileHeaderIfNeeded(); + + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT'); + if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && @$_SERVER['SERVER_PROTOCOL']) { + header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); + exit; + } + + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2])); + } elseif (eregi('\.ico$', $phpThumb->cache_filename)) { + header('Content-Type: image/x-icon'); + } + if (!@$PHPTHUMB_CONFIG['cache_force_passthru'] && ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { + header('Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1]))); + } else { + @readfile($phpThumb->cache_filename); + } + exit; + + } + return true; +} + +// check to see if file already exists in cache, and output it with no processing if it does +$phpThumb->SetCacheFilename(); +if (@is_file($phpThumb->cache_filename)) { + RedirectToCachedFile(); +} else { + $phpThumb->DebugMessage('Cached file "'.$phpThumb->cache_filename.'" does not exist, processing as normal', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[6]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '6') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if ($phpThumb->rawImageData) { + + // great + +} elseif (@$_GET['new']) { + + // generate a blank image resource of the specified size/background color/opacity + if (($phpThumb->w <= 0) || ($phpThumb->h <= 0)) { + $phpThumb->ErrorImage('"w" and "h" parameters required for "new"'); + } + @list($bghexcolor, $opacity) = explode('|', $_GET['new']); + if (!phpthumb_functions::IsHexColor($bghexcolor)) { + $phpThumb->ErrorImage('BGcolor parameter for "new" is not valid'); + } + $opacity = (strlen($opacity) ? $opacity : 100); + if ($phpThumb->gdimg_source = phpthumb_functions::ImageCreateFunction($phpThumb->w, $phpThumb->h)) { + $alpha = (100 - min(100, max(0, $opacity))) * 1.27; + if ($alpha) { + $phpThumb->setParameter('is_alpha', true); + ImageAlphaBlending($phpThumb->gdimg_source, false); + phpthumb_functions::gd_ImageSaveAlpha($phpThumb->gdimg_source, true); + } + $new_background_color = phpthumb_functions::ImageHexColorAllocate($phpThumb->gdimg_source, $bghexcolor, false, $alpha); + ImageFilledRectangle($phpThumb->gdimg_source, 0, 0, $phpThumb->w, $phpThumb->h, $new_background_color); + } else { + $phpThumb->ErrorImage('failed to create "new" image ('.$phpThumb->w.'x'.$phpThumb->h.')'); + } + +} elseif (!$phpThumb->src) { + + $phpThumb->ErrorImage('Usage: '.$_SERVER['PHP_SELF'].'?src=/path/and/filename.jpg'."\n".'read Usage comments for details'); + +} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { + + if ($phpThumb->config_http_user_agent) { + ini_set('user_agent', $phpThumb->config_http_user_agent); + } + $basename = preg_quote(basename($phpThumb->src)); + $encoded = rawurlencode(basename($phpThumb->src)); + $HTTPurl = ereg_replace('(.*)'.$basename.'$', '\\1'.$encoded, $phpThumb->src); + if ($rawImageData = phpthumb_functions::SafeURLread($HTTPurl, $error)) { + $phpThumb->setSourceData($rawImageData, urlencode($phpThumb->src)); + } else { + $phpThumb->ErrorImage($error); + } + +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[7]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '7') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +$phpThumb->GenerateThumbnail(); + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[8]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '8') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if ($phpThumb->config_allow_parameter_file && $phpThumb->file) { + + $phpThumb->RenderToFile($phpThumb->ResolveFilenameToAbsolute($phpThumb->file)); + if ($phpThumb->config_allow_parameter_goto && $phpThumb->goto && eregi('^(f|ht)tps?://', $phpThumb->goto)) { + // redirect to another URL after image has been rendered to file + header('Location: '.$phpThumb->goto); + exit; + } + +} else { + + if ((file_exists($phpThumb->cache_filename) && is_writable($phpThumb->cache_filename)) || is_writable(dirname($phpThumb->cache_filename))) { + + $phpThumb->CleanUpCacheDirectory(); + if ($phpThumb->RenderToFile($phpThumb->cache_filename) && is_readable($phpThumb->cache_filename)) { + chmod($phpThumb->cache_filename, 0644); + RedirectToCachedFile(); + } else { + $phpThumb->DebugMessage('Failed: RenderToFile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + $phpThumb->DebugMessage('Cannot write to $phpThumb->cache_filename ('.$phpThumb->cache_filename.') because that directory ('.dirname($phpThumb->cache_filename).') is not writable', __FILE__, __LINE__); + + } + +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[9]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '9') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if (!$phpThumb->OutputThumbnail()) { + $phpThumb->ErrorImage('Error in OutputThumbnail():'."\n".$phpThumb->debugmessages[(count($phpThumb->debugmessages) - 1)]); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[10]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '10') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/phpthumb.bmp.php b/site/retailers/phpthumb/phpthumb.bmp.php new file mode 100644 index 0000000..4946226 --- /dev/null +++ b/site/retailers/phpthumb/phpthumb.bmp.php @@ -0,0 +1,874 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.graphic.bmp.php // +// module for analyzing BMP Image files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// +// // +// Modified for use in phpThumb() - James Heinrich 2004.07.27 // +// // +///////////////////////////////////////////////////////////////// + + +class phpthumb_bmp { + + function phpthumb_bmp() { + return true; + } + + function phpthumb_bmp2gd(&$BMPdata, $truecolor=true) { + $ThisFileInfo = array(); + if ($this->getid3_bmp($BMPdata, $ThisFileInfo, true, true)) { + $gd = $this->PlotPixelsGD($ThisFileInfo['bmp'], $truecolor); + return $gd; + } + return false; + } + + function phpthumb_bmpfile2gd($filename, $truecolor=true) { + if ($fp = @fopen($filename, 'rb')) { + $BMPdata = fread($fp, filesize($filename)); + fclose($fp); + return $this->phpthumb_bmp2gd($BMPdata, $truecolor); + } + return false; + } + + function GD2BMPstring(&$gd_image) { + $imageX = ImageSX($gd_image); + $imageY = ImageSY($gd_image); + + $BMP = ''; + for ($y = ($imageY - 1); $y >= 0; $y--) { + $thisline = ''; + for ($x = 0; $x < $imageX; $x++) { + $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); + $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']); + } + while (strlen($thisline) % 4) { + $thisline .= "\x00"; + } + $BMP .= $thisline; + } + + $bmpSize = strlen($BMP) + 14 + 40; + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + $BITMAPFILEHEADER = 'BM'; // WORD bfType; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String($bmpSize, 4); // DWORD bfSize; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved1; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved2; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 54, 4); // DWORD bfOffBits; + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + $BITMAPINFOHEADER = phpthumb_functions::LittleEndian2String( 40, 4); // DWORD biSize; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageX, 4); // LONG biWidth; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageY, 4); // LONG biHeight; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 1, 2); // WORD biPlanes; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 24, 2); // WORD biBitCount; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biCompression; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biSizeImage; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biXPelsPerMeter; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biYPelsPerMeter; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrUsed; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrImportant; + + return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP; + } + + function getid3_bmp(&$BMPdata, &$ThisFileInfo, $ExtractPalette=false, $ExtractData=false) { + + // shortcuts + $ThisFileInfo['bmp']['header']['raw'] = array(); + $thisfile_bmp = &$ThisFileInfo['bmp']; + $thisfile_bmp_header = &$thisfile_bmp['header']; + $thisfile_bmp_header_raw = &$thisfile_bmp_header['raw']; + + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + // all versions + // WORD bfType; + // DWORD bfSize; + // WORD bfReserved1; + // WORD bfReserved2; + // DWORD bfOffBits; + + $offset = 0; + $overalloffset = 0; + $BMPheader = substr($BMPdata, $overalloffset, 14 + 40); + $overalloffset += (14 + 40); + + $thisfile_bmp_header_raw['identifier'] = substr($BMPheader, $offset, 2); + $offset += 2; + + if ($thisfile_bmp_header_raw['identifier'] != 'BM') { + $ThisFileInfo['error'][] = 'Expecting "BM" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$thisfile_bmp_header_raw['identifier'].'"'; + unset($ThisFileInfo['fileformat']); + unset($ThisFileInfo['bmp']); + return false; + } + + $thisfile_bmp_header_raw['filesize'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['reserved2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['header_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + + // check if the hardcoded-to-1 "planes" is at offset 22 or 26 + $planes22 = $this->LittleEndian2Int(substr($BMPheader, 22, 2)); + $planes26 = $this->LittleEndian2Int(substr($BMPheader, 26, 2)); + if (($planes22 == 1) && ($planes26 != 1)) { + $thisfile_bmp['type_os'] = 'OS/2'; + $thisfile_bmp['type_version'] = 1; + } elseif (($planes26 == 1) && ($planes22 != 1)) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 12) { + $thisfile_bmp['type_os'] = 'OS/2'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 40) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 84) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 4; + } elseif ($thisfile_bmp_header_raw['header_size'] == 100) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 5; + } else { + $ThisFileInfo['error'][] = 'Unknown BMP subtype (or not a BMP file)'; + unset($ThisFileInfo['fileformat']); + unset($ThisFileInfo['bmp']); + return false; + } + + $ThisFileInfo['fileformat'] = 'bmp'; + $ThisFileInfo['video']['dataformat'] = 'bmp'; + $ThisFileInfo['video']['lossless'] = true; + $ThisFileInfo['video']['pixel_aspect_ratio'] = (float) 1; + + if ($thisfile_bmp['type_os'] == 'OS/2') { + + // OS/2-format BMP + // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm + + // DWORD Size; /* Size of this structure in bytes */ + // DWORD Width; /* Bitmap width in pixels */ + // DWORD Height; /* Bitmap height in pixel */ + // WORD NumPlanes; /* Number of bit planes (color depth) */ + // WORD BitsPerPixel; /* Number of bits per pixel per plane */ + + $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + + $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; + $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; + $ThisFileInfo['video']['codec'] = 'BI_RGB '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; + + if ($thisfile_bmp['type_version'] >= 2) { + // DWORD Compression; /* Bitmap compression scheme */ + // DWORD ImageDataSize; /* Size of bitmap data in bytes */ + // DWORD XResolution; /* X resolution of display device */ + // DWORD YResolution; /* Y resolution of display device */ + // DWORD ColorsUsed; /* Number of color table indices used */ + // DWORD ColorsImportant; /* Number of important color indices */ + // WORD Units; /* Type of units used to measure resolution */ + // WORD Reserved; /* Pad structure to 4-byte boundary */ + // WORD Recording; /* Recording algorithm */ + // WORD Rendering; /* Halftoning algorithm used */ + // DWORD Size1; /* Reserved for halftoning algorithm use */ + // DWORD Size2; /* Reserved for halftoning algorithm use */ + // DWORD ColorEncoding; /* Color model used in bitmap */ + // DWORD Identifier; /* Reserved for application use */ + + $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_units'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['recording'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['rendering'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['size1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['size2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['color_encoding'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['identifier'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['compression'] = $this->BMPcompressionOS2Lookup($thisfile_bmp_header_raw['compression']); + + $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + } + + } elseif ($thisfile_bmp['type_os'] == 'Windows') { + + // Windows-format BMP + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + // all versions + // DWORD biSize; + // LONG biWidth; + // LONG biHeight; + // WORD biPlanes; + // WORD biBitCount; + // DWORD biCompression; + // DWORD biSizeImage; + // LONG biXPelsPerMeter; + // LONG biYPelsPerMeter; + // DWORD biClrUsed; + // DWORD biClrImportant; + + $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['compression'] = $this->BMPcompressionWindowsLookup($thisfile_bmp_header_raw['compression']); + $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; + $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; + $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; + + if (($thisfile_bmp['type_version'] >= 4) || ($thisfile_bmp_header_raw['compression'] == 3)) { + // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen + $BMPheader .= substr($BMPdata, $overalloffset, 44); + $overalloffset += 44; + + // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp + // Win95+, WinNT4.0+ + // DWORD bV4RedMask; + // DWORD bV4GreenMask; + // DWORD bV4BlueMask; + // DWORD bV4AlphaMask; + // DWORD bV4CSType; + // CIEXYZTRIPLE bV4Endpoints; + // DWORD bV4GammaRed; + // DWORD bV4GammaGreen; + // DWORD bV4GammaBlue; + $thisfile_bmp_header_raw['red_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['green_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['blue_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['alpha_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['cs_type'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_red'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_green'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_blue'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['gamma_red'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['gamma_green'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['gamma_blue'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['ciexyz_red'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_red'])); + $thisfile_bmp_header['ciexyz_green'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_green'])); + $thisfile_bmp_header['ciexyz_blue'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_blue'])); + } + + if ($thisfile_bmp['type_version'] >= 5) { + $BMPheader .= substr($BMPdata, $overalloffset, 16); + $overalloffset += 16; + + // BITMAPV5HEADER - [16 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_7c36.asp + // Win98+, Win2000+ + // DWORD bV5Intent; + // DWORD bV5ProfileData; + // DWORD bV5ProfileSize; + // DWORD bV5Reserved; + $thisfile_bmp_header_raw['intent'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['profile_data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['profile_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['reserved3'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + } + + } else { + + $ThisFileInfo['error'][] = 'Unknown BMP format in header.'; + return false; + + } + + if ($ExtractPalette || $ExtractData) { + $PaletteEntries = 0; + if ($thisfile_bmp_header_raw['bits_per_pixel'] < 16) { + $PaletteEntries = pow(2, $thisfile_bmp_header_raw['bits_per_pixel']); + } elseif (isset($thisfile_bmp_header_raw['colors_used']) && ($thisfile_bmp_header_raw['colors_used'] > 0) && ($thisfile_bmp_header_raw['colors_used'] <= 256)) { + $PaletteEntries = $thisfile_bmp_header_raw['colors_used']; + } + if ($PaletteEntries > 0) { + $BMPpalette = substr($BMPdata, $overalloffset, 4 * $PaletteEntries); + $overalloffset += 4 * $PaletteEntries; + + $paletteoffset = 0; + for ($i = 0; $i < $PaletteEntries; $i++) { + // RGBQUAD - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_5f8y.asp + // BYTE rgbBlue; + // BYTE rgbGreen; + // BYTE rgbRed; + // BYTE rgbReserved; + $blue = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + $green = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + $red = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + if (($thisfile_bmp['type_os'] == 'OS/2') && ($thisfile_bmp['type_version'] == 1)) { + // no padding byte + } else { + $paletteoffset++; // padding byte + } + $thisfile_bmp['palette'][$i] = (($red << 16) | ($green << 8) | ($blue)); + } + } + } + + if ($ExtractData) { + $RowByteLength = ceil(($thisfile_bmp_header_raw['width'] * ($thisfile_bmp_header_raw['bits_per_pixel'] / 8)) / 4) * 4; // round up to nearest DWORD boundry + + $BMPpixelData = substr($BMPdata, $thisfile_bmp_header_raw['data_offset'], $thisfile_bmp_header_raw['height'] * $RowByteLength); + $overalloffset = $thisfile_bmp_header_raw['data_offset'] + ($thisfile_bmp_header_raw['height'] * $RowByteLength); + + $pixeldataoffset = 0; + switch (@$thisfile_bmp_header_raw['compression']) { + + case 0: // BI_RGB + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 1: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { + $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); + for ($i = 7; $i >= 0; $i--) { + $paletteindex = ($paletteindexbyte & (0x01 << $i)) >> $i; + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $col++; + } + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 4: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { + $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); + for ($i = 1; $i >= 0; $i--) { + $paletteindex = ($paletteindexbyte & (0x0F << (4 * $i))) >> (4 * $i); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $col++; + } + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 8: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $paletteindex = ord($BMPpixelData{$pixeldataoffset++}); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 24: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); + $pixeldataoffset += 3; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 32: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+3}) << 24) | (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); + $pixeldataoffset += 4; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 16: + // ? + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + case 1: // BI_RLE8 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 8: + $pixelcounter = 0; + while ($pixeldataoffset < strlen($BMPpixelData)) { + $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + if ($firstbyte == 0) { + + // escaped/absolute mode - the first byte of the pair can be set to zero to + // indicate an escape character that denotes the end of a line, the end of + // a bitmap, or a delta, depending on the value of the second byte. + switch ($secondbyte) { + case 0: + // end of line + // no need for special processing, just ignore + break; + + case 1: + // end of bitmap + $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case + break; + + case 2: + // delta - The 2 bytes following the escape contain unsigned values + // indicating the horizontal and vertical offsets of the next pixel + // from the current position. + $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; + $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; + $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; + break; + + default: + // In absolute mode, the first byte is zero and the second byte is a + // value in the range 03H through FFH. The second byte represents the + // number of bytes that follow, each of which contains the color index + // of a single pixel. Each run must be aligned on a word boundary. + for ($i = 0; $i < $secondbyte; $i++) { + $paletteindex = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $pixelcounter++; + } + while (($pixeldataoffset % 2) != 0) { + // Each run must be aligned on a word boundary. + $pixeldataoffset++; + } + break; + } + + } else { + + // encoded mode - the first byte specifies the number of consecutive pixels + // to be drawn using the color index contained in the second byte. + for ($i = 0; $i < $firstbyte; $i++) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$secondbyte]; + $pixelcounter++; + } + + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + + case 2: // BI_RLE4 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 4: + $pixelcounter = 0; + while ($pixeldataoffset < strlen($BMPpixelData)) { + $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + if ($firstbyte == 0) { + + // escaped/absolute mode - the first byte of the pair can be set to zero to + // indicate an escape character that denotes the end of a line, the end of + // a bitmap, or a delta, depending on the value of the second byte. + switch ($secondbyte) { + case 0: + // end of line + // no need for special processing, just ignore + break; + + case 1: + // end of bitmap + $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case + break; + + case 2: + // delta - The 2 bytes following the escape contain unsigned values + // indicating the horizontal and vertical offsets of the next pixel + // from the current position. + $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; + $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; + $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; + break; + + default: + // In absolute mode, the first byte is zero. The second byte contains the number + // of color indexes that follow. Subsequent bytes contain color indexes in their + // high- and low-order 4 bits, one color index for each pixel. In absolute mode, + // each run must be aligned on a word boundary. + unset($paletteindexes); + for ($i = 0; $i < ceil($secondbyte / 2); $i++) { + $paletteindexbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $paletteindexes[] = ($paletteindexbyte & 0xF0) >> 4; + $paletteindexes[] = ($paletteindexbyte & 0x0F); + } + while (($pixeldataoffset % 2) != 0) { + // Each run must be aligned on a word boundary. + $pixeldataoffset++; + } + + foreach ($paletteindexes as $dummy => $paletteindex) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $pixelcounter++; + } + break; + } + + } else { + + // encoded mode - the first byte of the pair contains the number of pixels to be + // drawn using the color indexes in the second byte. The second byte contains two + // color indexes, one in its high-order 4 bits and one in its low-order 4 bits. + // The first of the pixels is drawn using the color specified by the high-order + // 4 bits, the second is drawn using the color in the low-order 4 bits, the third + // is drawn using the color in the high-order 4 bits, and so on, until all the + // pixels specified by the first byte have been drawn. + $paletteindexes[0] = ($secondbyte & 0xF0) >> 4; + $paletteindexes[1] = ($secondbyte & 0x0F); + for ($i = 0; $i < $firstbyte; $i++) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindexes[($i % 2)]]; + $pixelcounter++; + } + + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + case 3: // BI_BITFIELDS + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 16: + case 32: + $redshift = 0; + $greenshift = 0; + $blueshift = 0; + if (!$thisfile_bmp_header_raw['red_mask'] || !$thisfile_bmp_header_raw['green_mask'] || !$thisfile_bmp_header_raw['blue_mask']) { + $ThisFileInfo['error'][] = 'missing $thisfile_bmp_header_raw[(red|green|blue)_mask]'; + return false; + } + while ((($thisfile_bmp_header_raw['red_mask'] >> $redshift) & 0x01) == 0) { + $redshift++; + } + while ((($thisfile_bmp_header_raw['green_mask'] >> $greenshift) & 0x01) == 0) { + $greenshift++; + } + while ((($thisfile_bmp_header_raw['blue_mask'] >> $blueshift) & 0x01) == 0) { + $blueshift++; + } + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $pixelvalue = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset, $thisfile_bmp_header_raw['bits_per_pixel'] / 8)); + $pixeldataoffset += $thisfile_bmp_header_raw['bits_per_pixel'] / 8; + + $red = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['red_mask']) >> $redshift) / ($thisfile_bmp_header_raw['red_mask'] >> $redshift)) * 255)); + $green = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['green_mask']) >> $greenshift) / ($thisfile_bmp_header_raw['green_mask'] >> $greenshift)) * 255)); + $blue = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['blue_mask']) >> $blueshift) / ($thisfile_bmp_header_raw['blue_mask'] >> $blueshift)) * 255)); + $thisfile_bmp['data'][$row][$col] = (($red << 16) | ($green << 8) | ($blue)); + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + default: // unhandled compression type + $ThisFileInfo['error'][] = 'Unknown/unhandled compression type value ('.$thisfile_bmp_header_raw['compression'].') - cannot decompress pixel data'; + break; + } + } + + return true; + } + + function IntColor2RGB($color) { + $red = ($color & 0x00FF0000) >> 16; + $green = ($color & 0x0000FF00) >> 8; + $blue = ($color & 0x000000FF); + return array($red, $green, $blue); + } + + function PlotPixelsGD(&$BMPdata, $truecolor=true) { + $imagewidth = $BMPdata['header']['raw']['width']; + $imageheight = $BMPdata['header']['raw']['height']; + + if ($truecolor) { + + $gd = @ImageCreateTrueColor($imagewidth, $imageheight); + + } else { + + $gd = @ImageCreate($imagewidth, $imageheight); + if (!empty($BMPdata['palette'])) { + // create GD palette from BMP palette + foreach ($BMPdata['palette'] as $dummy => $color) { + list($r, $g, $b) = $this->IntColor2RGB($color); + ImageColorAllocate($gd, $r, $g, $b); + } + } else { + // create 216-color websafe palette + for ($r = 0x00; $r <= 0xFF; $r += 0x33) { + for ($g = 0x00; $g <= 0xFF; $g += 0x33) { + for ($b = 0x00; $b <= 0xFF; $b += 0x33) { + ImageColorAllocate($gd, $r, $g, $b); + } + } + } + } + + } + if (!is_resource($gd)) { + return false; + } + + foreach ($BMPdata['data'] as $row => $colarray) { + @set_time_limit(30); + foreach ($colarray as $col => $color) { + list($red, $green, $blue) = $this->IntColor2RGB($color); + if ($truecolor) { + $pixelcolor = ImageColorAllocate($gd, $red, $green, $blue); + } else { + $pixelcolor = ImageColorClosest($gd, $red, $green, $blue); + } + ImageSetPixel($gd, $col, $row, $pixelcolor); + } + } + return $gd; + } + + function PlotBMP(&$BMPinfo) { + $starttime = time(); + if (!isset($BMPinfo['bmp']['data']) || !is_array($BMPinfo['bmp']['data'])) { + echo 'ERROR: no pixel data
    '; + return false; + } + set_time_limit(intval(round($BMPinfo['resolution_x'] * $BMPinfo['resolution_y'] / 10000))); + $im = $this->PlotPixelsGD($BMPinfo['bmp']); + if (headers_sent()) { + echo 'plotted '.($BMPinfo['resolution_x'] * $BMPinfo['resolution_y']).' pixels in '.(time() - $starttime).' seconds
    '; + ImageDestroy($im); + exit; + } else { + header('Content-Type: image/png'); + ImagePNG($im); + ImageDestroy($im); + return true; + } + return false; + } + + function BMPcompressionWindowsLookup($compressionid) { + static $BMPcompressionWindowsLookup = array( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'BI_BITFIELDS', + 4 => 'BI_JPEG', + 5 => 'BI_PNG' + ); + return (isset($BMPcompressionWindowsLookup[$compressionid]) ? $BMPcompressionWindowsLookup[$compressionid] : 'invalid'); + } + + function BMPcompressionOS2Lookup($compressionid) { + static $BMPcompressionOS2Lookup = array( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'Huffman 1D', + 4 => 'BI_RLE24', + ); + return (isset($BMPcompressionOS2Lookup[$compressionid]) ? $BMPcompressionOS2Lookup[$compressionid] : 'invalid'); + } + + + // from getid3.lib.php + + function trunc($floatnumber) { + // truncates a floating-point number at the decimal point + // returns int (if possible, otherwise float) + if ($floatnumber >= 1) { + $truncatednumber = floor($floatnumber); + } elseif ($floatnumber <= -1) { + $truncatednumber = ceil($floatnumber); + } else { + $truncatednumber = 0; + } + if ($truncatednumber <= 1073741824) { // 2^30 + $truncatednumber = (int) $truncatednumber; + } + return $truncatednumber; + } + + function LittleEndian2Int($byteword) { + $intvalue = 0; + $byteword = strrev($byteword); + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i)); + } + return $intvalue; + } + + function BigEndian2Int($byteword) { + return $this->LittleEndian2Int(strrev($byteword)); + } + + function BigEndian2Bin($byteword) { + $binvalue = ''; + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT); + } + return $binvalue; + } + + function FixedPoint2_30($rawdata) { + $binarystring = $this->BigEndian2Bin($rawdata); + return $this->Bin2Dec(substr($binarystring, 0, 2)) + (float) ($this->Bin2Dec(substr($binarystring, 2, 30)) / 1073741824); + } + + function Bin2Dec($binstring, $signed=false) { + $signmult = 1; + if ($signed) { + if ($binstring{0} == '1') { + $signmult = -1; + } + $binstring = substr($binstring, 1); + } + $decvalue = 0; + for ($i = 0; $i < strlen($binstring); $i++) { + $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i); + } + return $this->CastAsInt($decvalue * $signmult); + } + + function CastAsInt($floatnum) { + // convert to float if not already + $floatnum = (float) $floatnum; + + // convert a float to type int, only if possible + if ($this->trunc($floatnum) == $floatnum) { + // it's not floating point + if ($floatnum <= 1073741824) { // 2^30 + // it's within int range + $floatnum = (int) $floatnum; + } + } + return $floatnum; + } + +} + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/phpthumb.class.php b/site/retailers/phpthumb/phpthumb.class.php new file mode 100644 index 0000000..14865fd --- /dev/null +++ b/site/retailers/phpthumb/phpthumb.class.php @@ -0,0 +1,3170 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'")'); +} +ob_end_clean(); + +class phpthumb { + + // public: + // START PARAMETERS (for object mode and phpThumb.php) + // See phpthumb.readme.txt for descriptions of what each of these values are + var $src = null; // SouRCe filename + var $new = null; // NEW image (phpThumb.php only) + var $w = null; // Width + var $h = null; // Height + var $wp = null; // Width (Portrait Images Only) + var $hp = null; // Height (Portrait Images Only) + var $wl = null; // Width (Landscape Images Only) + var $hl = null; // Height (Landscape Images Only) + var $ws = null; // Width (Square Images Only) + var $hs = null; // Height (Square Images Only) + var $f = null; // Format + var $q = 75; // jpeg output Quality + var $sx = null; // Source crop top-left X position + var $sy = null; // Source crop top-left Y position + var $sw = null; // Source crop Width + var $sh = null; // Source crop Height + var $zc = null; // Zoom Crop + var $bc = null; // Border Color + var $bg = null; // BackGround color + var $fltr = array(); // FiLTeRs + var $goto = null; // GO TO url after processing + var $err = null; // default ERRor image filename + var $xto = null; // extract eXif Thumbnail Only + var $ra = null; // Rotate by Angle + var $ar = null; // Auto Rotate + var $aoe = null; // Allow Output Enlargement + var $far = null; // Fixed Aspect Ratio + var $iar = null; // Ignore Aspect Ratio + var $maxb = null; // MAXimum Bytes + var $down = null; // DOWNload thumbnail filename + var $md5s = null; // MD5 hash of Source image + var $file = null; // >>deprecated, do not use<< + + var $phpThumbDebug = null; + // END PARAMETERS + + + // public: + // START CONFIGURATION OPTIONS (for object mode only) + // See phpThumb.config.php for descriptions of what each of these settings do + + // * Directory Configuration + var $config_cache_directory = null; + var $config_cache_disable_warning = true; + var $config_cache_source_enabled = false; + var $config_cache_source_directory = null; + var $config_temp_directory = null; + var $config_document_root = null; + + // * Default output configuration: + var $config_output_format = 'jpeg'; + var $config_output_maxwidth = 0; + var $config_output_maxheight = 0; + var $config_output_interlace = true; + + // * Error message configuration + var $config_error_image_width = 400; + var $config_error_image_height = 100; + var $config_error_message_image_default = ''; + var $config_error_bgcolor = 'CCCCFF'; + var $config_error_textcolor = 'FF0000'; + var $config_error_fontsize = 1; + var $config_error_die_on_error = true; + var $config_error_silent_die_on_error = false; + var $config_error_die_on_source_failure = true; + + // * Anti-Hotlink Configuration: + var $config_nohotlink_enabled = true; + var $config_nohotlink_valid_domains = array(); + var $config_nohotlink_erase_image = true; + var $config_nohotlink_text_message = 'Off-server thumbnailing is not allowed'; + // * Off-server Linking Configuration: + var $config_nooffsitelink_enabled = false; + var $config_nooffsitelink_valid_domains = array(); + var $config_nooffsitelink_require_refer = false; + var $config_nooffsitelink_erase_image = true; + var $config_nooffsitelink_text_message = 'Off-server linking is not allowed'; + + // * Border & Background default colors + var $config_border_hexcolor = '000000'; + var $config_background_hexcolor = 'FFFFFF'; + + // * TrueType Fonts + var $config_ttf_directory = '.'; + + var $config_max_source_pixels = null; + var $config_use_exif_thumbnail_for_speed = false; + + var $config_imagemagick_path = null; + var $config_prefer_imagemagick = true; + + var $config_cache_maxage = null; + var $config_cache_maxsize = null; + var $config_cache_maxfiles = null; + var $config_cache_source_filemtime_ignore_local = false; + var $config_cache_source_filemtime_ignore_remote = true; + var $config_cache_default_only_suffix = false; + var $config_cache_force_passthru = true; + var $config_cache_prefix = ''; // default value set in the constructor below + + // * MySQL + var $config_mysql_query = null; + var $config_mysql_hostname = null; + var $config_mysql_username = null; + var $config_mysql_password = null; + var $config_mysql_database = null; + + // * Security + var $config_high_security_enabled = false; + var $config_config_high_security_password = null; + var $config_disable_debug = false; + var $config_allow_src_above_docroot = false; + var $config_allow_src_above_phpthumb = true; + var $config_allow_parameter_file = false; + var $config_allow_parameter_goto = false; + + // * Compatability + var $config_disable_pathinfo_parsing = false; + var $config_disable_imagecopyresampled = false; + var $config_disable_onlycreateable_passthru = false; + + var $config_http_user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; + + // END CONFIGURATION OPTIONS + + + // public: error messages (read-only) + var $debugmessages = array(); + var $debugtiming = array(); + var $fatalerror = null; + + + // private: (should not be modified directly) + var $thumbnailQuality = 75; + var $thumbnailFormat = null; + + var $sourceFilename = null; + var $rawImageData = null; + var $IMresizedData = null; + + var $useRawIMoutput = false; + + var $gdimg_output = null; + var $gdimg_source = null; + + var $getimagesizeinfo = null; + + var $source_width = null; + var $source_height = null; + + var $thumbnailCropX = null; + var $thumbnailCropY = null; + var $thumbnailCropW = null; + var $thumbnailCropH = null; + + var $exif_thumbnail_width = null; + var $exif_thumbnail_height = null; + var $exif_thumbnail_type = null; + var $exif_thumbnail_data = null; + + var $thumbnail_width = null; + var $thumbnail_height = null; + var $thumbnail_image_width = null; + var $thumbnail_image_height = null; + + var $cache_filename = null; + + var $AlphaCapableFormats = array('png', 'ico', 'gif'); + var $is_alpha = false; + + var $iswindows = null; + + var $phpthumb_version = '1.7.0-200602150817'; + + ////////////////////////////////////////////////////////////////////// + + // public: constructor + function phpThumb() { + $this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__); + $this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__); + $this->config_max_source_pixels = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); // 20% of memory_limit + + //if (phpthumb_functions::gd_version() < 1) { + // die('No GD support detected'); + //} + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + $this->iswindows = true; + } else { + $this->iswindows = false; + } + if (@$_SERVER['DOCUMENT_ROOT']) { + $this->config_document_root = $_SERVER['DOCUMENT_ROOT']; + } + $this->config_cache_prefix = 'phpThumb_cache_'.@$_SERVER['SERVER_NAME']; + } + + // public: + function setSourceFilename($sourceFilename) { + $this->rawImageData = null; + $this->sourceFilename = $sourceFilename; + $this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->sourceFilename to "'.$this->sourceFilename.'"', __FILE__, __LINE__); + return true; + } + + // public: + function setSourceData($rawImageData, $sourceFilename='') { + $this->sourceFilename = null; + $this->rawImageData = $rawImageData; + $this->DebugMessage('setSourceData() setting $this->rawImageData ('.strlen($this->rawImageData).' bytes)', __FILE__, __LINE__); + if ($this->config_cache_source_enabled) { + $sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData)); + if (!is_dir($this->config_cache_source_directory)) { + $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory'); + } elseif (!is_writable($this->config_cache_source_directory)) { + $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable'); + } + $this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).'"', __FILE__, __LINE__); + if ($fp = @fopen($this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename), 'wb')) { + fwrite($fp, $rawImageData); + fclose($fp); + } elseif (!$this->phpThumbDebug) { + $this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).')'); + } + } + return true; + } + + // public: + function setSourceImageResource($gdimg) { + $this->gdimg_source = $gdimg; + return true; + } + + // public: + function setParameter($param, $value) { + switch ($param) { + case 'src': + $this->setSourceFilename($this->ResolveFilenameToAbsolute($value)); + break; + + default: + $this->$param = $value; + break; + } + $this->$param = $value; + return true; + } + + // public: + function getParameter($param) { + //if (property_exists('phpThumb', $param)) { + return $this->$param; + //} + //$this->DebugMessage('setParameter() attempting to set non-existant parameter "'.$param.'"', __FILE__, __LINE__); + //return false; + } + + + // public: + function GenerateThumbnail() { + + $this->setOutputFormat(); + $this->ResolveSource(); + $this->SetCacheFilename(); + $this->ExtractEXIFgetImageSize(); + if ($this->useRawIMoutput) { + $this->DebugMessage('Skipping rest of GenerateThumbnail() because $this->useRawIMoutput', __FILE__, __LINE__); + return true; + } + if (!$this->SourceImageToGD()) { + $this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__); + return false; + } + $this->Rotate(); + $this->CreateGDoutput(); + + switch ($this->far) { + case 'L': + case 'TL': + case 'BL': + $destination_offset_x = 0; + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + break; + case 'R': + case 'TR': + case 'BR': + $destination_offset_x = round($this->thumbnail_width - $this->thumbnail_image_width); + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + break; + case 'T': + case 'TL': + case 'TR': + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = 0; + break; + case 'B': + case 'BL': + case 'BR': + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = round($this->thumbnail_height - $this->thumbnail_image_height); + break; + case 'C': + default: + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + } + + // copy/resize image to appropriate dimensions + $this->DebugMessage('ImageResizeFunction($o, $s, '.$destination_offset_x.', '.$destination_offset_y.', '.$this->thumbnailCropX.', '.$this->thumbnailCropY.', '.$this->thumbnail_image_width.', '.$this->thumbnail_image_height.', '.$this->thumbnailCropW.', '.$this->thumbnailCropH.')', __FILE__, __LINE__); + $this->ImageResizeFunction( + $this->gdimg_output, + $this->gdimg_source, + $destination_offset_x, + $destination_offset_y, + $this->thumbnailCropX, + $this->thumbnailCropY, + $this->thumbnail_image_width, + $this->thumbnail_image_height, + $this->thumbnailCropW, + $this->thumbnailCropH + ); + + $this->DebugMessage('memory_get_usage() after copy-resize = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); + ImageDestroy($this->gdimg_source); + $this->DebugMessage('memory_get_usage() after ImageDestroy = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); + + $this->AntiOffsiteLinking(); + $this->ApplyFilters(); + $this->AlphaChannelFlatten(); + $this->MaxFileSize(); + + $this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__); + return true; + } + + + // public: + function RenderToFile($filename) { + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { + $this->DebugMessage('RenderToFile('.$filename.') failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); + return false; + } + if (!$this->thumbnailFormat) { + $this->DebugMessage('RenderToFile() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__); + return false; + } + // render thumbnail to this file only, do not cache, do not output to browser + //$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename); + $renderfilename = $filename; + if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) { + $renderfilename = $this->ResolveFilenameToAbsolute($renderfilename); + } + if (!is_writable(dirname($renderfilename))) { + $this->DebugMessage('RenderToFile() failed because "'.dirname($renderfilename).'/" is not writable', __FILE__, __LINE__); + return false; + } + if (is_file($renderfilename) && !is_writable($renderfilename)) { + $this->DebugMessage('RenderToFile() failed because "'.$renderfilename.'" is not writable', __FILE__, __LINE__); + return false; + } + + if ($this->useRawIMoutput) { + + $this->DebugMessage('RenderToFile copying $this->IMresizedData ('.strlen($this->IMresizedData).' bytes) to "'.$renderfilename.'"', __FILE__, __LINE__); + return file_put_contents($renderfilename, $this->IMresizedData); + + } else { + + $this->DebugMessage('RenderToFile('.$filename.') attempting Image'.strtoupper(@$this->thumbnailFormat).'($this->gdimg_output, '.$renderfilename.')', __FILE__, __LINE__); + ob_start(); + switch ($this->thumbnailFormat) { + case 'jpeg': + $ImageOutFunction = 'image'.$this->thumbnailFormat; + $ImageOutFunction($this->gdimg_output, $renderfilename, $this->thumbnailQuality); + break; + + case 'png': + case 'gif': + $ImageOutFunction = 'image'.$this->thumbnailFormat; + $ImageOutFunction($this->gdimg_output, $renderfilename); + break; + + case 'bmp': + $ImageOutFunction = '"builtin BMP output"'; + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $phpthumb_bmp = new phpthumb_bmp(); + $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); + unset($phpthumb_bmp); + if (!$bmp_data) { + $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + if (!file_put_contents($renderfilename, $bmp_data)) { + $this->DebugMessage('file_put_contents('.$renderfilename.', ['.strlen($bmp_data).' bytes]) failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + break; + + case 'ico': + $ImageOutFunction = '"builtin ICO output"'; + if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $phpthumb_ico = new phpthumb_ico(); + $arrayOfOutputImages = array($this->gdimg_output); + $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); + unset($phpthumb_ico); + if (!$ico_data) { + $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + if (!file_put_contents($renderfilename, $ico_data)) { + $this->DebugMessage('file_put_contents('.$renderfilename.', ['.strlen($ico_data).' bytes]) failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + break; + + default: + $this->DebugMessage('RenderToFile failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $errormessage = strip_tags(ob_get_contents()); + ob_end_clean(); + if ($errormessage) { + $this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] failed with message "'.$errormessage.'"', __FILE__, __LINE__); + return false; + } elseif (!file_exists($renderfilename)) { + $this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__); + } + + } + return true; + } + + + // public: + function OutputThumbnail() { + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { + $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); + return false; + } + if (headers_sent()) { + return $this->ErrorImage('OutputThumbnail() failed - headers already sent'); + exit; + } + + if ($this->down) { + $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $this->down); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) { + $downloadfilename = trim($downloadfilename, '.'); + } + if ($downloadfilename != $this->down) { + $this->DebugMessage('renaming output file for "down" from "'.$this->down.'" to "'.$downloadfilename.'"', __FILE__, __LINE__); + } + if ($downloadfilename) { + header('Content-Disposition: attachment; filename="'.$downloadfilename.'"'); + } else { + $this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__); + } + } + + if ($this->useRawIMoutput) { + + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $this->IMresizedData; + + } else { + + $this->DebugMessage('ImageInterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__); + ImageInterlace($this->gdimg_output, intval($this->config_output_interlace)); + switch ($this->thumbnailFormat) { + case 'jpeg': + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + $ImageOutFunction = 'image'.$this->thumbnailFormat; + @$ImageOutFunction($this->gdimg_output, '', $this->thumbnailQuality); + break; + + case 'png': + case 'gif': + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + $ImageOutFunction = 'image'.$this->thumbnailFormat; + @$ImageOutFunction($this->gdimg_output); + break; + + case 'bmp': + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); + return false; + } + $phpthumb_bmp = new phpthumb_bmp(); + if (is_object($phpthumb_bmp)) { + $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); + unset($phpthumb_bmp); + if (!$bmp_data) { + $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); + return false; + } + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $bmp_data; + } else { + $this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__); + return false; + } + break; + + case 'ico': + if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); + return false; + } + $phpthumb_ico = new phpthumb_ico(); + if (is_object($phpthumb_ico)) { + $arrayOfOutputImages = array($this->gdimg_output); + $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); + unset($phpthumb_ico); + if (!$ico_data) { + $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); + return false; + } + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $ico_data; + } else { + $this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__); + return false; + } + break; + + default: + $this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); + return false; + break; + } + + } + return true; + } + + + // public: + function CleanUpCacheDirectory() { + if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) { + $CacheDirOldFilesAge = array(); + $CacheDirOldFilesSize = array(); + if ($dirhandle = opendir($this->config_cache_directory)) { + while ($oldcachefile = readdir($dirhandle)) { + if (eregi('^phpThumb_cache_', $oldcachefile)) { + $CacheDirOldFilesAge[$oldcachefile] = fileatime($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + if ($CacheDirOldFilesAge[$oldcachefile] == 0) { + $CacheDirOldFilesAge[$oldcachefile] = filemtime($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + } + + $CacheDirOldFilesSize[$oldcachefile] = filesize($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + } + } + } + asort($CacheDirOldFilesAge); + + if ($this->config_cache_maxfiles > 0) { + $TotalCachedFiles = count($CacheDirOldFilesAge); + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($TotalCachedFiles > $this->config_cache_maxfiles) { + $TotalCachedFiles--; + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // there are few enough files to keep the rest + break; + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + if ($this->config_cache_maxage > 0) { + $mindate = time() - $this->config_cache_maxage; + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($filedate > 0) { + if ($filedate < $mindate) { + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // the rest of the files are new enough to keep + break; + } + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + if ($this->config_cache_maxsize > 0) { + $TotalCachedFileSize = array_sum($CacheDirOldFilesSize); + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($TotalCachedFileSize > $this->config_cache_maxsize) { + $TotalCachedFileSize -= $CacheDirOldFilesSize[$oldcachefile]; + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // the total filesizes are small enough to keep the rest of the files + break; + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + } + return true; + } + + ////////////////////////////////////////////////////////////////////// + + function ResolveSource() { + if (is_resource($this->gdimg_source)) { + $this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__); + return true; + } + if ($this->rawImageData) { + $this->sourceFilename = null; + $this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set', __FILE__, __LINE__); + return true; + } + if ($this->sourceFilename) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename); + $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'"', __FILE__, __LINE__); + } else { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); + $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'" from $this->src ('.$this->src.')', __FILE__, __LINE__); + } + if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) { + // Windows \\share\filename.ext + } elseif (eregi('^(f|ht)tps?://', $this->sourceFilename)) { + // URL + if ($this->config_http_user_agent) { + ini_set('user_agent', $this->config_http_user_agent); + } + } elseif (!file_exists($this->sourceFilename)) { + return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist'); + } elseif (!is_file($this->sourceFilename)) { + return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file'); + } + return true; + } + + function setOutputFormat() { + static $alreadyCalled = false; + if ($this->thumbnailFormat && $alreadyCalled) { + return true; + } + $alreadyCalled = true; + + $AvailableImageOutputFormats = array(); + $AvailableImageOutputFormats[] = 'text'; + if (is_readable(dirname(__FILE__).'/phpthumb.ico.php')) { + $AvailableImageOutputFormats[] = 'ico'; + } + if (is_readable(dirname(__FILE__).'/phpthumb.bmp.php')) { + $AvailableImageOutputFormats[] = 'bmp'; + } + + $this->thumbnailFormat = 'ico'; + + // Set default output format based on what image types are available + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_WBMP) { + $this->thumbnailFormat = 'wbmp'; + $AvailableImageOutputFormats[] = 'wbmp'; + } + if ($imagetypes & IMG_GIF) { + $this->thumbnailFormat = 'gif'; + $AvailableImageOutputFormats[] = 'gif'; + } + if ($imagetypes & IMG_PNG) { + $this->thumbnailFormat = 'png'; + $AvailableImageOutputFormats[] = 'png'; + } + if ($imagetypes & IMG_JPG) { + $this->thumbnailFormat = 'jpeg'; + $AvailableImageOutputFormats[] = 'jpeg'; + } + } else { + //return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?'); + $this->DebugMessage('ImageTypes() does not exist - GD support might not be enabled?', __FILE__, __LINE__); + } + if ($this->ImageMagickVersion()) { + $IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico'); + $this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats ('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); + foreach ($IMformats as $key => $format) { + $AvailableImageOutputFormats[] = $format; + } + } + $AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats); + $this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); + + if (strtolower($this->config_output_format) == 'jpg') { + $this->config_output_format = 'jpeg'; + } + if (strtolower($this->f) == 'jpg') { + $this->f = 'jpeg'; + } + if (in_array(strtolower($this->config_output_format), $AvailableImageOutputFormats)) { + // set output format to config default if that format is available + $this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__); + $this->thumbnailFormat = strtolower($this->config_output_format); + } elseif ($this->config_output_format) { + $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->config_output_format ('.strtolower($this->config_output_format).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); + } + if ($this->f && (in_array(strtolower($this->f), $AvailableImageOutputFormats))) { + // override output format if $this->f is set and that format is available + $this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__); + $this->thumbnailFormat = strtolower($this->f); + } elseif ($this->f) { + $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->f ('.strtolower($this->f).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); + } + + // for JPEG images, quality 1 (worst) to 99 (best) + // quality < 25 is nasty, with not much size savings - not recommended + // problems with 100 - invalid JPEG? + $this->thumbnailQuality = max(1, min(99, ($this->q ? $this->q : 75))); + $this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__); + + return true; + } + + function setCacheDirectory() { + // resolve cache directory to absolute pathname + $this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__); + if (substr($this->config_cache_directory, 0, 1) == '.') { + if (eregi('^(f|ht)tps?://', $this->src)) { + if (!$this->config_cache_disable_warning) { + $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); + } + } elseif ($this->src) { + // resolve relative cache directory to source image + $this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory; + } else { + // $this->new is probably set + } + } + if (substr($this->config_cache_directory, -1) == '/') { + $this->config_cache_directory = substr($this->config_cache_directory, 0, -1); + } + if ($this->iswindows) { + $this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory); + } + if ($this->config_cache_directory) { + $real_cache_path = realpath($this->config_cache_directory); + if (!$real_cache_path) { + $this->DebugMessage('realpath($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__); + if (!is_dir($this->config_cache_directory)) { + $this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__); + } + } + if ($real_cache_path) { + $this->DebugMessage('setting config_cache_directory to realpath('.$this->config_cache_directory.') = "'.$real_cache_path.'"', __FILE__, __LINE__); + $this->config_cache_directory = $real_cache_path; + } + } + if (!is_dir($this->config_cache_directory)) { + if (!$this->config_cache_disable_warning) { + $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); + } + $this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__); + $this->config_cache_directory = null; + } elseif (!is_writable($this->config_cache_directory)) { + $this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__); + } + return true; + } + + + function ResolveFilenameToAbsolute($filename) { + if (eregi('^(f|ht)tps?://', $filename)) { + + // URL + //$AbsoluteFilename = $filename; + return $filename; + + } elseif ($this->iswindows && ($filename{1} == ':')) { + + // absolute pathname (Windows) + $AbsoluteFilename = $filename; + + } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) { + + // absolute pathname (Windows) + $AbsoluteFilename = $filename; + + } elseif ($filename{0} == '/') { + + if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) { + + // absolute filename (*nix) + $AbsoluteFilename = $filename; + + } elseif ($filename{1} == '~') { + + // /~user/path + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) { + $AbsoluteFilename = $ApacheLookupURIarray['filename']; + } else { + $AbsoluteFilename = realpath($filename); + if (@is_readable($AbsoluteFilename)) { + $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__); + } else { + return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image'); + } + } + + } else { + + // relative filename (any OS) + if (ereg('^'.preg_quote($this->config_document_root), $filename)) { + $AbsoluteFilename = $filename; + $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); + } else { + $AbsoluteFilename = $this->config_document_root.$filename; + $this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); + } + + } + + } else { + + // relative to current directory (any OS) + $AbsoluteFilename = $this->config_document_root.dirname(@$_SERVER['PHP_SELF']).DIRECTORY_SEPARATOR.$filename; + //if (!file_exists($AbsoluteFilename) && file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) { + // $AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename)); + //} + + if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') { + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { + $AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename; + } else { + $AbsoluteFilename = realpath('.').DIRECTORY_SEPARATOR.$filename; + if (@is_readable($AbsoluteFilename)) { + $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__); + } else { + return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image'); + } + } + } + + } + if (is_link($AbsoluteFilename)) { + $this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__); + $AbsoluteFilename = readlink($AbsoluteFilename); + } + if (realpath($AbsoluteFilename)) { + $AbsoluteFilename = realpath($AbsoluteFilename); + } + if ($this->iswindows) { + $AbsoluteFilename = eregi_replace('^'.preg_quote(realpath($this->config_document_root)), realpath($this->config_document_root), $AbsoluteFilename); + $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename); + } + if (!$this->config_allow_src_above_docroot && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))), $AbsoluteFilename)) { + $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.realpath($this->config_document_root).'") to null', __FILE__, __LINE__); + return false; + } + if (!$this->config_allow_src_above_phpthumb && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))), $AbsoluteFilename)) { + $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__); + return false; + } + return $AbsoluteFilename; + } + + function ImageMagickWhichConvert() { + static $WhichConvert = null; + if (is_null($WhichConvert)) { + if ($this->iswindows) { + $WhichConvert = false; + } else { + $WhichConvert = trim(phpthumb_functions::SafeExec('which convert')); + } + } + return $WhichConvert; + } + + function ImageMagickCommandlineBase() { + static $commandline = null; + if (is_null($commandline)) { + $commandline = $this->config_imagemagick_path; + $commandline = (!is_null($commandline) ? $commandline : ''); + + $which_convert = $this->ImageMagickWhichConvert(); + $IMversion = $this->ImageMagickVersion(); + + if ($this->config_imagemagick_path && ($this->config_imagemagick_path != realpath($this->config_imagemagick_path))) { + if (@is_executable(realpath($this->config_imagemagick_path))) { + $this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to realpath($this->config_imagemagick_path) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); + $this->config_imagemagick_path = realpath($this->config_imagemagick_path); + } else { + $this->DebugMessage('Leaving $this->config_imagemagick_path as ('.$this->config_imagemagick_path.') because !is_execuatable(realpath($this->config_imagemagick_path)) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); + } + } + $this->DebugMessage(' file_exists('.$this->config_imagemagick_path.') = '.intval( @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__); + $this->DebugMessage('is_executable('.$this->config_imagemagick_path.') = '.intval(@is_executable($this->config_imagemagick_path)), __FILE__, __LINE__); + if (@file_exists($this->config_imagemagick_path)) { + + $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__); + if ($this->iswindows) { + $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.substr(dirname($this->config_imagemagick_path), 2).'" && '.basename($this->config_imagemagick_path); + } else { + $commandline = '"'.$this->config_imagemagick_path.'"'; + } + + } elseif ($which_convert && ($which_convert{0} == '/') && @file_exists($which_convert)) { + + // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't + // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin" + // so only do this if the value returned exists as a file + $this->DebugMessage('using ImageMagick path from `which convert` ('.$which_convert.')', __FILE__, __LINE__); + $commandline = 'convert'; + + } elseif ($IMversion) { + + $this->DebugMessage('setting ImageMagick path to $this->config_imagemagick_path ('.$this->config_imagemagick_path.') ['.$IMversion.']', __FILE__, __LINE__); + $commandline = $this->config_imagemagick_path; + + } else { + + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path ('.$this->config_imagemagick_path.'), and `which convert` returned ('.$which_convert.')', __FILE__, __LINE__); + $commandline = ''; + + } + } + return $commandline; + } + + function ImageMagickVersion() { + static $versionstring = null; + if (is_null($versionstring)) { + $commandline = $this->ImageMagickCommandlineBase(); + $commandline = (!is_null($commandline) ? $commandline : ''); + + if ($commandline) { + $commandline .= ' -version'; + $versionstring = phpthumb_functions::SafeExec($commandline); + if (eregi('^Version: (.*) http', $versionstring, $matches)) { + $versionstring = $matches[1]; + } else { + $versionstring = false; + $this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring.')', __FILE__, __LINE__); + } + } + } + return $versionstring; + } + + function ImageMagickThumbnailToGD() { + // http://www.imagemagick.org/script/command-line-options.php + + $this->useRawIMoutput = true; + if (phpthumb_functions::gd_version()) { + //$UnAllowedParameters = array('sx', 'sy', 'sw', 'sh', 'xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); + $UnAllowedParameters = array('xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); + foreach ($UnAllowedParameters as $dummy => $parameter) { + if ($this->$parameter) { + $this->DebugMessage('$this->useRawIMoutput=false because "'.$parameter.'" is set', __FILE__, __LINE__); + $this->useRawIMoutput = false; + break; + } + } + } + $outputFormat = $this->thumbnailFormat; + if (phpthumb_functions::gd_version()) { + if ($this->useRawIMoutput) { + switch ($this->thumbnailFormat) { + case 'gif': + $ImageCreateFunction = 'ImageCreateFromGIF'; + $this->is_alpha = true; + break; + case 'png': + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + break; + case 'jpg': + case 'jpeg': + $ImageCreateFunction = 'ImageCreateFromJPEG'; + break; + default: + $outputFormat = 'png'; + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + $this->useRawIMoutput = false; + break; + } + if (!function_exists(@$ImageCreateFunction)) { + // ImageMagickThumbnailToGD() depends on ImageCreateFromPNG/ImageCreateFromGIF + //$this->DebugMessage('ImageMagickThumbnailToGD() aborting because '.@$ImageCreateFunction.'() is not available', __FILE__, __LINE__); + $this->useRawIMoutput = true; + //return false; + } + } else { + $outputFormat = 'png'; + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + $this->useRawIMoutput = false; + } + } + + // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html + if (!$this->sourceFilename) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } + if (ini_get('safe_mode')) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } + + $commandline = $this->ImageMagickCommandlineBase(); + if ($commandline) { + if ($IMtempfilename = $this->phpThumb_tempnam()) { + + if (!eregi('('.implode('|', $this->AlphaCapableFormats).')', $outputFormat)) { + // not a transparency-capable format + $commandline .= ' -background "#'.($this->bg ? $this->bg : 'FFFFFF').'"'; + $commandline .= ' -flatten'; + } + $IMtempfilename = realpath($IMtempfilename); + if ($getimagesize = GetImageSize($this->sourceFilename)) { + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') returned [w='.$getimagesize[0].';h='.$getimagesize[1].';f='.$getimagesize[2].']', __FILE__, __LINE__); + $this->source_width = $getimagesize[0]; + $this->source_height = $getimagesize[1]; + $this->DebugMessage('source dimensions set to '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__); + $this->SetOrientationDependantWidthHeight(); + + $commandline .= ' -coalesce'; // may be needed for animated GIFs + if ($this->source_width || $this->source_height) { + if ($this->zc) { + + $side = min($this->source_width, $this->source_height, max($this->w, $this->wp, $this->wl, $this->ws, $this->h, $this->hp, $this->hl, $this->hs)); + if ($getimagesize[0] > $getimagesize[1]) { + $commandline .= ' -thumbnail x'.$side; + } else { + $commandline .= ' -thumbnail '.$side.'x'; + } + $commandline .= ' -gravity center'; + $commandline .= ' -crop '.$side.'x'.$side.'+0+0'; + $commandline .= ' +repage'; + + } elseif ($this->sw || $this->sh || $this->sx || $this->sy) { + + $commandline .= ' -crop '.($this->sw ? $this->sw : $this->source_width).'x'.($this->sh ? $this->sh : $this->source_height).'+'.$this->sx.'+'.$this->sy; + // this is broken for aoe=1, but unsure how to fix. Send advice to info@silisoftware.com + + } else { + + $this->w = (($this->aoe && $this->w) ? max($this->w, $getimagesize[0]) : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : '')); + $this->h = (($this->aoe && $this->h) ? max($this->h, $getimagesize[1]) : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : '')); + if ($this->w || $this->h) { + $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; + if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { + $commandline .= '!'; + } + } + } + } + + } else { + + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') failed', __FILE__, __LINE__); + $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; + if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { + $commandline .= '!'; + } + + } + foreach ($this->fltr as $filterkey => $filtercommand) { + @list($command, $parameter) = explode('|', $filtercommand, 2); + switch ($command) { + case 'brit': + $commandline .= ' -modulate '.(100 + $parameter).',100,100'; + unset($this->fltr[$filterkey]); + break; + + case 'cont': + $contDiv10 = round($parameter / 10); + if ($contDiv10 > 0) { + for ($i = 0; $i < $contDiv10; $i++) { + $commandline .= ' -contrast'; // increase contrast by 10% + } + } elseif ($contDiv10 < 0) { + for ($i = $contDiv10; $i < 0; $i++) { + $commandline .= ' +contrast'; // decrease contrast by 10% + } + } else { + // do nothing + } + unset($this->fltr[$filterkey]); + break; + + case 'ds': + if ($parameter == 100) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + } else { + $commandline .= ' -modulate 100,'.(100 - $parameter).',100'; + } + unset($this->fltr[$filterkey]); + break; + + case 'sat': + if ($parameter == -100) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + } else { + $commandline .= ' -modulate 100,'.(100 + $parameter).',100'; + } + unset($this->fltr[$filterkey]); + break; + + case 'gray': + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + //$commandline .= ' -colorspace GRAY'; + unset($this->fltr[$filterkey]); + break; + + case 'clr': + @list($amount, $color) = explode('|', $parameter); + $commandline .= ' -fill #'.$color.' -colorize '.$amount; + break; + + case 'sep': + @list($amount, $color) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + if (!$color) { + $commandline .= ' -sepia-tone '.$amount.'%'; + unset($this->fltr[$filterkey]); + } + break; + + case 'gam': + $commandline .= ' -gamma '.$parameter; + unset($this->fltr[$filterkey]); + break; + + case 'neg': + $commandline .= ' -negate'; + unset($this->fltr[$filterkey]); + break; + + case 'th': + $commandline .= ' -threshold '.round($parameter / 2.55).'% -dither -monochrome'; + unset($this->fltr[$filterkey]); + break; + + case 'rcd': + @list($colors, $dither) = explode('|', $parameter); + $colors = ($colors ? (int) $colors : 256); + $dither = ((strlen($dither) > 0) ? (bool) $dither : true); + $commandline .= ' -colors '.max($colors, 8); // ImageMagick will otherwise fail with "cannot quantize to fewer than 8 colors" + $commandline .= ($dither ? ' -dither' : ' +dither'); + unset($this->fltr[$filterkey]); + break; + + case 'flip': + if (strpos(strtolower($parameter), 'x') !== false) { + $commandline .= ' -flop'; + } + if (strpos(strtolower($parameter), 'y') !== false) { + $commandline .= ' -flip'; + } + unset($this->fltr[$filterkey]); + break; + + case 'edge': + $parameter = ($parameter ? $parameter : 2); + $commandline .= ' -edge '.($parameter ? $parameter : 1); + unset($this->fltr[$filterkey]); + break; + + case 'emb': + $parameter = ($parameter ? $parameter : 2); + $commandline .= ' -emboss '.$parameter; + if ($parameter < 2) { + $commandline .= ' -negate'; // ImageMagick negates the image for some reason with '-emboss 1'; + } + unset($this->fltr[$filterkey]); + break; + + case 'lvl': + @list($band, $min, $max) = explode('|', $parameter); + $band = ($band ? $band : '*'); + $min = ((strlen($min) > 0) ? $min : '-1'); + $max = ((strlen($max) > 0) ? $max : '-1'); + if ($band == '*') { + if (($min == -1) && ($max == -1)) { + $commandline .= ' -normalize'; + unset($this->fltr[$filterkey]); + } elseif (($min == -1) || ($max == -1)) { + // + } else { + $commandline .= ' -level '.$min.'%,'.$max.'%'; + unset($this->fltr[$filterkey]); + } + } + break; + + case 'blur': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + $commandline .= ' -blur '.$radius; + unset($this->fltr[$filterkey]); + break; + + case 'gblr': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + $commandline .= ' -gaussian '.$radius; + unset($this->fltr[$filterkey]); + break; + + case 'usm': + @list($amount, $radius, $threshold) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + $radius = ($radius ? $radius : 0.5); + $threshold = (strlen($threshold) ? $threshold : 3); + $commandline .= ' -unsharp '.number_format(($radius * 2) - 1, 2).'x1+'.number_format($amount / 100, 2).'+'.number_format($threshold / 100, 2); + unset($this->fltr[$filterkey]); + break; + + case 'sblr': + break; + + case 'mean': + break; + + case 'smth': + break; + + case 'bvl': + break; + + case 'wmi': + break; + + case 'wmt': + break; + + case 'over': + break; + + case 'wb': + break; + + case 'hist': + break; + + case 'fram': + break; + + case 'drop': + break; + + case 'mask': + break; + + case 'elip': + break; + + case 'ric': + break; + + case 'bord': + break; + + } + if (!isset($this->fltr[$filterkey])) { + $this->DebugMessage('Processed $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); + } else { + $this->DebugMessage('Skipping $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); + } + } + $this->DebugMessage('Remaining $this->fltr after ImageMagick: ('.$this->phpThumbDebugVarDump($this->fltr).')', __FILE__, __LINE__); + + if (eregi('jpe?g', $outputFormat) && $this->q) { + $commandline .= ' -quality '.$this->thumbnailQuality; + if ($this->config_output_interlace) { + // causes weird things with animated GIF... leave for JPEG only + $commandline .= ' -interlace line '; // Use Line or Plane to create an interlaced PNG or GIF or progressive JPEG image + } + } + $commandline .= ' "'.str_replace('/', DIRECTORY_SEPARATOR, $this->sourceFilename).(($outputFormat == 'gif') ? '' : '[0]').'"'; // [0] means first frame of (GIF) animation, can be ignored + $commandline .= ' '.$outputFormat.':"'.$IMtempfilename.'"'; + $commandline .= ' 2>&1'; + $this->DebugMessage('ImageMagick called as ('.$commandline.')', __FILE__, __LINE__); + $IMresult = phpthumb_functions::SafeExec($commandline); +//var_Dump($commandline); +//var_dump($ImageCreateFunction); +//exit; + clearstatcache(); + if (!file_exists($IMtempfilename) || !filesize($IMtempfilename)) { + + $this->DebugMessage('ImageMagick failed with message ('.$IMresult.')', __FILE__, __LINE__); + + } else { + + $this->IMresizedData = file_get_contents($IMtempfilename); + if (function_exists(@$ImageCreateFunction) && ($this->gdimg_source = @$ImageCreateFunction($IMtempfilename))) { +//header('Content-Type: image/png'); +//phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_source, true); +//ImagePNG($this->gdimg_source); +//exit; + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $this->DebugMessage('ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() succeeded, $this->gdimg_source is now ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); + $this->DebugMessage('ImageMagickThumbnailToGD() returning $IMresizedData ('.strlen($this->IMresizedData).' bytes)', __FILE__, __LINE__); + } else { + $this->useRawIMoutput = true; + $this->DebugMessage('$this->useRawIMoutput set to TRUE because '.@$ImageCreateFunction.'('.$IMtempfilename.') failed', __FILE__, __LINE__); + } + @unlink($IMtempfilename); + return true; + + } + unlink($IMtempfilename); + + } else { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpThumb_tempnam() failed', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__); + } + $this->useRawIMoutput = false; + return false; + } + + + function Rotate() { + if ($this->ra || $this->ar) { + if (!function_exists('ImageRotate')) { + $this->DebugMessage('!function_exists(ImageRotate)', __FILE__, __LINE__); + return false; + } + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); + return false; + } + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + + $rotate_angle = 0; + if ($this->ra) { + + $rotate_angle = floatval($this->ra); + + } else { + + if ($this->ar == 'x') { + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=')) { + if ($this->sourceFilename) { + if (function_exists('exif_read_data')) { + if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) { + // http://sylvana.net/jpegcrop/exif_orientation.html + switch (@$exif_data['Orientation']) { + case 1: + $rotate_angle = 0; + break; + case 3: + $rotate_angle = 180; + break; + case 6: + $rotate_angle = 270; + break; + case 8: + $rotate_angle = 90; + break; + + default: + $this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "'.@$exif_data['Orientation'].'"', __FILE__, __LINE__); + return false; + break; + } + $this->DebugMessage('EXIF auto-rotate set to '.$rotate_angle.' degrees ($exif_data[Orientation] = "'.@$exif_data['Orientation'].'")', __FILE__, __LINE__); + } else { + $this->DebugMessage('failed: exif_read_data('.$this->sourceFilename.')', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 ('.phpversion().')', __FILE__, __LINE__); + return false; + } + } elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) { + $rotate_angle = 270; + } elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) { + $rotate_angle = 90; + } elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) { + $rotate_angle = 90; + } elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) { + $rotate_angle = 270; + } + + } + while ($rotate_angle < 0) { + $rotate_angle += 360; + } + $rotate_angle = $rotate_angle % 360; + if ($rotate_angle != 0) { + + if ($rotate_angle % 90) { + $this->is_alpha = true; + } + + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_source, $this->config_background_hexcolor); + + //if ((phpthumb_functions::gd_version() >= 2) && in_array($this->thumbnailFormat, $this->AlphaCapableFormats) && !$this->bg && ($rotate_angle % 90)) { + if ((phpthumb_functions::gd_version() >= 2) && !$this->bg && ($rotate_angle % 90)) { + + $this->DebugMessage('Using alpha rotate', __FILE__, __LINE__); + if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_source), ImageSY($this->gdimg_source))) { + + for ($i = 0; $i <= 255; $i++) { + $color_mask[$i] = ImageColorAllocate($gdimg_rotate_mask, $i, $i, $i); + } + ImageFilledRectangle($gdimg_rotate_mask, 0, 0, ImageSX($gdimg_rotate_mask), ImageSY($gdimg_rotate_mask), $color_mask[255]); + $imageX = ImageSX($this->gdimg_source); + $imageY = ImageSY($this->gdimg_source); + for ($x = 0; $x < $imageX; $x++) { + for ($y = 0; $y < $imageY; $y++) { + $pixelcolor = phpthumb_functions::GetPixelColor($this->gdimg_source, $x, $y); + ImageSetPixel($gdimg_rotate_mask, $x, $y, $color_mask[255 - round($pixelcolor['alpha'] * 255 / 127)]); + } + } + $gdimg_rotate_mask = ImageRotate($gdimg_rotate_mask, $rotate_angle, $color_mask[0]); + $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color); + + ImageAlphaBlending($this->gdimg_source, false); + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_source, true); + $this->is_alpha = true; + $phpThumbFilters = new phpthumb_filters(); + $phpThumbFilters->phpThumbObject = $this; + $phpThumbFilters->ApplyMask($gdimg_rotate_mask, $this->gdimg_source); + + ImageDestroy($gdimg_rotate_mask); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + + } else { + + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + } elseif ($this->bg) { + $this->DebugMessage('Using non-alpha rotate because $this->bg is "'.$this->bg.'"', __FILE__, __LINE__); + } elseif ($this->bg) { + $this->DebugMessage('Using non-alpha rotate because ($rotate_angle % 90) = "'.($rotate_angle % 90).'"', __FILE__, __LINE__); + } else { + $this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); + } + + if (ImageColorTransparent($this->gdimg_source) >= 0) { + // ImageRotate() forgets all about an image's transparency and sets the transparent color to black + // To compensate, flood-fill the transparent color of the source image with the specified background color first + // then rotate and the colors should match + + if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($this->gdimg_source)) { + // convert paletted image to true-color before rotating to prevent nasty aliasing artifacts + + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $gdimg_newsrc = phpthumb_functions::ImageCreateFunction($this->source_width, $this->source_height); + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor); + ImageFilledRectangle($gdimg_newsrc, 0, 0, $this->source_width, $this->source_height, phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor)); + ImageCopy($gdimg_newsrc, $this->gdimg_source, 0, 0, 0, 0, $this->source_width, $this->source_height); + ImageDestroy($this->gdimg_source); + unset($this->gdimg_source); + $this->gdimg_source = $gdimg_newsrc; + unset($gdimg_newsrc); + + } else { + + ImageColorSet( + $this->gdimg_source, + ImageColorTransparent($this->gdimg_source), + hexdec(substr($this->config_background_hexcolor, 0, 2)), + hexdec(substr($this->config_background_hexcolor, 2, 2)), + hexdec(substr($this->config_background_hexcolor, 4, 2))); + + ImageColorTransparent($this->gdimg_source, -1); + + } + } + + $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + } + } + } + return true; + } + + + function FixedAspectRatio() { + // optional fixed-dimension images (regardless of aspect ratio) + + if (!$this->far) { + // do nothing + return true; + } + + if (!$this->w || !$this->h) { + return false; + } + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->is_alpha = true; + if ($this->thumbnail_image_width >= $this->thumbnail_width) { + + if ($this->w) { + $aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width; + $this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio); + if (!$this->h) { + $this->thumbnail_height = $this->thumbnail_image_height; + } + } elseif ($this->thumbnail_image_height < $this->thumbnail_height) { + $this->thumbnail_image_height = $this->thumbnail_height; + $this->thumbnail_image_width = round($this->thumbnail_image_height / $aspectratio); + } + + } else { + + if ($this->h) { + $aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height; + $this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio); + } elseif ($this->thumbnail_image_width < $this->thumbnail_width) { + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = round($this->thumbnail_image_width / $aspectratio); + } + + } + return true; + } + + + function AntiOffsiteLinking() { + // Optional anti-offsite hijacking of the thumbnail script + $allow = true; + if ($allow && $this->config_nooffsitelink_enabled && (@$_SERVER['HTTP_REFERER'] || $this->config_nooffsitelink_require_refer)) { + $this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "'.@$_SERVER['HTTP_REFERER'].'"', __FILE__, __LINE__); + $parsed_url = parse_url(@$_SERVER['HTTP_REFERER']); + if (!in_array(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) { + $allow = false; + $erase = $this->config_nooffsitelink_erase_image; + $message = $this->config_nooffsitelink_text_message; + $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + } else { + $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + } + } + + if ($allow && $this->config_nohotlink_enabled && eregi('^(f|ht)tps?://', $this->src)) { + $parsed_url = parse_url($this->src); + if (!in_array(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) { + // This domain is not allowed + $allow = false; + $erase = $this->config_nohotlink_erase_image; + $message = $this->config_nohotlink_text_message; + $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is NOT in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); + } else { + $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); + } + } + + if ($allow) { + $this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__); + return true; + } + + if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_error_bgcolor.'" for $this->config_error_bgcolor'); + } + if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_error_textcolor.'" for $this->config_error_textcolor'); + } + if ($erase) { + + return $this->ErrorImage($message, $this->thumbnail_width, $this->thumbnail_height, $this->config_error_bgcolor, $this->config_error_textcolor, $this->config_error_fontsize); + + } else { + + $nohotlink_text_array = explode("\n", wordwrap($message, floor($this->thumbnail_width / ImageFontWidth($this->config_error_fontsize)), "\n")); + $nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor); + + $topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * ImageFontHeight($this->config_error_fontsize))) / 2); + + $rowcounter = 0; + $this->DebugMessage('AntiOffsiteLinking() writing '.count($nohotlink_text_array).' lines of text "'.$message.'" (in #'.$this->config_error_textcolor.') on top of image', __FILE__, __LINE__); + foreach ($nohotlink_text_array as $dummy => $textline) { + $leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * ImageFontWidth($this->config_error_fontsize))) / 2)); + ImageString($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * ImageFontHeight($this->config_error_fontsize)), $textline, $nohotlink_text_color); + } + + } + return true; + } + + + function AlphaChannelFlatten() { + if (!$this->is_alpha) { + // image doesn't have alpha transparency, no need to flatten + $this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__); + return false; + } + switch ($this->thumbnailFormat) { + case 'png': + case 'ico': + // image has alpha transparency, but output as PNG or ICO which can handle it + $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'")', __FILE__, __LINE__); + return false; + break; + + case 'gif': + // image has alpha transparency, but output as GIF which can handle only single-color transparency + $CurrentImageColorTransparent = ImageColorTransparent($this->gdimg_output); + if ($CurrentImageColorTransparent == -1) { + // no transparent color defined + + if (phpthumb_functions::gd_version() < 2.0) { + $this->DebugMessage('AlphaChannelFlatten() failed because GD version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + + if ($img_alpha_mixdown_dither = @ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { + + for ($i = 0; $i <= 255; $i++) { + $dither_color[$i] = ImageColorAllocate($img_alpha_mixdown_dither, $i, $i, $i); + } + + // scan through current truecolor image copy alpha channel to temp image as grayscale + for ($x = 0; $x < $this->thumbnail_width; $x++) { + for ($y = 0; $y < $this->thumbnail_height; $y++) { + $PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y); + ImageSetPixel($img_alpha_mixdown_dither, $x, $y, $dither_color[($PixelColor['alpha'] * 2)]); + } + } + + // dither alpha channel grayscale version down to 2 colors + ImageTrueColorToPalette($img_alpha_mixdown_dither, true, 2); + + // reduce color palette to 256-1 colors (leave one palette position for transparent color) + ImageTrueColorToPalette($this->gdimg_output, true, 255); + + // allocate a new color for transparent color index + $TransparentColor = ImageColorAllocate($this->gdimg_output, 1, 254, 253); + ImageColorTransparent($this->gdimg_output, $TransparentColor); + + // scan through alpha channel image and note pixels with >50% transparency + $TransparentPixels = array(); + for ($x = 0; $x < $this->thumbnail_width; $x++) { + for ($y = 0; $y < $this->thumbnail_height; $y++) { + $AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y); + if ($AlphaChannelPixel['red'] > 127) { + ImageSetPixel($this->gdimg_output, $x, $y, $TransparentColor); + } + } + } + ImageDestroy($img_alpha_mixdown_dither); + + $this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__); + return true; + + } else { + $this->DebugMessage('AlphaChannelFlatten() failed ImageCreate('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); + return false; + } + + } else { + // a single transparent color already defined, leave as-is + $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'") and ImageColorTransparent returned "'.$CurrentImageColorTransparent.'"', __FILE__, __LINE__); + return true; + } + break; + } + $this->DebugMessage('continuing AlphaChannelFlatten() for output format "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); + + // image has alpha transparency, and is being output in a format that doesn't support it -- flatten + if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) { + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); + ImageFilledRectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); + ImageCopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); + + ImageAlphaBlending($this->gdimg_output, true); + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_output, false); + ImageColorTransparent($this->gdimg_output, -1); + ImageCopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); + + ImageDestroy($gdimg_flatten_temp); + return true; + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + return false; + } + + + function ApplyFilters() { + if ($this->fltr && is_array($this->fltr)) { + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); + return false; + } + $phpthumbFilters = new phpthumb_filters(); + $phpthumbFilters->phpThumbObject = $this; + foreach ($this->fltr as $dummy => $filtercommand) { + @list($command, $parameter) = explode('|', $filtercommand, 2); + $this->DebugMessage('Attempting to process filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__); + switch ($command) { + case 'brit': + $phpthumbFilters->Brightness($this->gdimg_output, $parameter); + break; + + case 'cont': + $phpthumbFilters->Contrast($this->gdimg_output, $parameter); + break; + + case 'ds': + $phpthumbFilters->Desaturate($this->gdimg_output, $parameter, ''); + break; + + case 'sat': + $phpthumbFilters->Saturation($this->gdimg_output, $parameter, ''); + break; + + case 'gray': + $phpthumbFilters->Grayscale($this->gdimg_output); + break; + + case 'clr': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Colorize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($amount, $color) = explode('|', $parameter); + $phpthumbFilters->Colorize($this->gdimg_output, $amount, $color); + break; + + case 'sep': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Sepia() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($amount, $color) = explode('|', $parameter); + $phpthumbFilters->Sepia($this->gdimg_output, $amount, $color); + break; + + case 'gam': + $phpthumbFilters->Gamma($this->gdimg_output, $parameter); + break; + + case 'neg': + $phpthumbFilters->Negative($this->gdimg_output); + break; + + case 'th': + $phpthumbFilters->Threshold($this->gdimg_output, $parameter); + break; + + case 'rcd': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping ReduceColorDepth() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($colors, $dither) = explode('|', $parameter); + $colors = ($colors ? (int) $colors : 256); + $dither = ((strlen($dither) > 0) ? (bool) $dither : true); + $phpthumbFilters->ReduceColorDepth($this->gdimg_output, $colors, $dither); + break; + + case 'flip': + $phpthumbFilters->Flip($this->gdimg_output, (strpos(strtolower($parameter), 'x') !== false), (strpos(strtolower($parameter), 'y') !== false)); + break; + + case 'edge': + $phpthumbFilters->EdgeDetect($this->gdimg_output); + break; + + case 'emb': + $phpthumbFilters->Emboss($this->gdimg_output); + break; + + case 'bvl': + @list($width, $color1, $color2) = explode('|', $parameter); + $phpthumbFilters->Bevel($this->gdimg_output, $width, $color1, $color2); + break; + + case 'lvl': + @list($band, $min, $max) = explode('|', $parameter); + $band = ($band ? $band : '*'); + $min = ((strlen($min) > 0) ? $min : '-1'); + $max = ((strlen($max) > 0) ? $max : '-1'); + $phpthumbFilters->HistogramStretch($this->gdimg_output, $band, $min, $max); + break; + + case 'wb': + $phpthumbFilters->WhiteBalance($this->gdimg_output, $parameter); + break; + + case 'hist': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping HistogramOverlay() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($bands, $colors, $width, $height, $alignment, $opacity, $margin) = explode('|', $parameter); + $bands = ($bands ? $bands : '*'); + $colors = ($colors ? $colors : ''); + $width = ($width ? $width : 0.25); + $height = ($height ? $height : 0.25); + $alignment = ($alignment ? $alignment : 'BR'); + $opacity = ($opacity ? $opacity : 50); + $margin = ($margin ? $margin : 5); + $phpthumbFilters->HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin); + break; + + case 'fram': + @list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter); + $phpthumbFilters->Frame($this->gdimg_output, $frame_width, $edge_width, $color_frame, $color1, $color2); + break; + + case 'drop': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping DropShadow() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $this->is_alpha = true; + @list($distance, $width, $color, $angle, $fade) = explode('|', $parameter); + $phpthumbFilters->DropShadow($this->gdimg_output, $distance, $width, $color, $angle, $fade); + break; + + case 'mask': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Mask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $mask_filename = $this->ResolveFilenameToAbsolute($parameter); + if (@is_readable($mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) { + $MaskImageData = fread($fp_mask, filesize($mask_filename)); + fclose($fp_mask); + if ($gdimg_mask = $this->ImageCreateFromStringReplacement($MaskImageData)) { + $this->is_alpha = true; + $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output); + ImageDestroy($gdimg_mask); + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$mask_filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('Cannot open mask file "'.$mask_filename.'"', __FILE__, __LINE__); + } + break; + + case 'elip': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Elipse() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $this->is_alpha = true; + $phpthumbFilters->Elipse($this->gdimg_output); + break; + + case 'ric': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping RoundedImageCorners() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + @list($radius_x, $radius_y) = explode('|', $parameter); + if (($radius_x < 1) || ($radius_y < 1)) { + $this->DebugMessage('Skipping RoundedImageCorners('.$radius_x.', '.$radius_y.') because x/y radius is less than 1', __FILE__, __LINE__); + break; + } + $this->is_alpha = true; + $phpthumbFilters->RoundedImageCorners($this->gdimg_output, $radius_x, $radius_y); + break; + + case 'bord': + @list($border_width, $radius_x, $radius_y, $hexcolor_border) = explode('|', $parameter); + $this->is_alpha = true; + $phpthumbFilters->ImageBorder($this->gdimg_output, $border_width, $radius_x, $radius_y, $hexcolor_border); + break; + + case 'over': + @list($filename, $underlay, $margin, $opacity) = explode('|', $parameter); + $underlay = (bool) ($underlay ? $underlay : false); + $margin = ((strlen($margin) > 0) ? $margin : ($underlay ? 0.1 : 0.0)); + $opacity = ((strlen($opacity) > 0) ? $opacity : 100); + if (($margin > 0) && ($margin < 1)) { + $margin = min(0.499, $margin); + } elseif (($margin > -1) && ($margin < 0)) { + $margin = max(-0.499, $margin); + } + + $filename = $this->ResolveFilenameToAbsolute($filename); + if (@is_readable($filename) && ($fp_watermark = @fopen($filename, 'rb'))) { + $WatermarkImageData = fread($fp_watermark, filesize($filename)); + fclose($fp_watermark); + if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) { + if ($margin < 1) { + $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * (ImageSX($this->gdimg_output) * $margin))); + $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * (ImageSY($this->gdimg_output) * $margin))); + } else { + $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * $margin)); + $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * $margin)); + } + + if ($underlay) { + + if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { + ImageAlphaBlending($img_watermark_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark_resized, true); + $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); + if ($img_source_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { + ImageAlphaBlending($img_source_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_source_resized, true); + $this->ImageResizeFunction($img_source_resized, $this->gdimg_output, 0, 0, 0, 0, ImageSX($img_source_resized), ImageSY($img_source_resized), ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + $phpthumbFilters->WatermarkOverlay($img_watermark_resized, $img_source_resized, 'C', $opacity, $margin); + ImageCopy($this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); + } + ImageDestroy($img_watermark_resized); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); + } + + } else { // overlay + + if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { + ImageAlphaBlending($img_watermark_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark_resized, true); + $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark_resized, 'C', $opacity, $margin); + ImageDestroy($img_watermark_resized); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); + } + + } + ImageDestroy($img_watermark); + + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('Cannot open overlay file "'.$filename.'"', __FILE__, __LINE__); + } + break; + + case 'wmi': + @list($filename, $alignment, $opacity, $margin) = explode('|', $parameter); + $alignment = ($alignment ? $alignment : 'BR'); + $opacity = (strlen($opacity) ? $opacity : 50); + $margin = (strlen($margin) ? $margin : 5); + + $filename = $this->ResolveFilenameToAbsolute($filename); + if (@is_readable($filename)) { + if ($img_watermark = $this->ImageCreateFromFilename($filename, $rawImageData)) { + // great + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark, $alignment, $opacity, $margin); + ImageDestroy($img_watermark); + } else { + $this->DebugMessage('ImageCreateFromFilename() failed for "'.$filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('!is_readable('.$filename.')', __FILE__, __LINE__); + } + break; + + case 'wmt': + @list($text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend) = explode('|', $parameter); + $text = ($text ? $text : ''); + $size = ($size ? $size : 3); + $alignment = ($alignment ? $alignment : 'BR'); + $hex_color = ($hex_color ? $hex_color : '000000'); + $ttffont = ($ttffont ? $ttffont : ''); + $opacity = (strlen($opacity) ? $opacity : 50); + $margin = (strlen($margin) ? $margin : 5); + $angle = (strlen($angle) ? $angle : 0); + $bg_color = ($bg_color ? $bg_color : false); + $bg_opacity = ($bg_opacity ? $bg_opacity : 0); + $fillextend = ($fillextend ? $fillextend : ''); + + if (basename($ttffont) == $ttffont) { + $ttffont = realpath($this->config_ttf_directory.DIRECTORY_SEPARATOR.$ttffont); + } else { + $ttffont = $this->ResolveFilenameToAbsolute($ttffont); + } + $phpthumbFilters->WatermarkText($this->gdimg_output, $text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend); + break; + + case 'blur': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Blur() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $phpthumbFilters->Blur($this->gdimg_output, $radius); + break; + + case 'gblr': + $phpthumbFilters->BlurGaussian($this->gdimg_output); + break; + + case 'sblr': + $phpthumbFilters->BlurSelective($this->gdimg_output); + break; + + case 'mean': + $phpthumbFilters->MeanRemoval($this->gdimg_output); + break; + + case 'smth': + $phpthumbFilters->Smooth($this->gdimg_output, $parameter); + break; + + case 'usm': + @list($amount, $radius, $threshold) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + $radius = ($radius ? $radius : 0.5); + $threshold = (strlen($threshold) ? $threshold : 3); + if (phpthumb_functions::gd_version() >= 2.0) { + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.unsharp.php')) { + $include_error = ob_get_contents(); + if ($include_error) { + $this->DebugMessage('include_once("'.dirname(__FILE__).'/phpthumb.unsharp.php") generated message: "'.$include_error.'"', __FILE__, __LINE__); + } + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.unsharp.php" which is required for unsharp masking', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ob_end_clean(); + phpUnsharpMask::applyUnsharpMask($this->gdimg_output, $amount, $radius, $threshold); + } else { + $this->DebugMessage('Skipping unsharp mask because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + break; + } + } + } + return true; + } + + + function MaxFileSize() { + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping MaxFileSize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + if ($this->maxb > 0) { + switch ($this->thumbnailFormat) { + case 'png': + case 'gif': + $imgRenderFunction = 'image'.$this->thumbnailFormat; + + ob_start(); + $imgRenderFunction($this->gdimg_output); + $imgdata = ob_get_contents(); + ob_end_clean(); + + if (strlen($imgdata) > $this->maxb) { + for ($i = 8; $i >= 1; $i--) { + $tempIMG = ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + ImageCopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + ImageTrueColorToPalette($tempIMG, true, pow(2, $i)); + ob_start(); + $imgRenderFunction($tempIMG); + $imgdata = ob_get_contents(); + ob_end_clean(); + + if (strlen($imgdata) <= $this->maxb) { + ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); + break; + } + } + } + if (strlen($imgdata) > $this->maxb) { + ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); + return false; + } + break; + + case 'jpeg': + ob_start(); + ImageJPEG($this->gdimg_output); + $imgdata = ob_get_contents(); + ob_end_clean(); + + $OriginalJPEGquality = $this->thumbnailQuality; + if (strlen($imgdata) > $this->maxb) { + for ($i = 3; $i < 20; $i++) { + $q = round(100 * (1 - log10($i / 2))); + ob_start(); + ImageJPEG($this->gdimg_output, '', $q); + $imgdata = ob_get_contents(); + ob_end_clean(); + + $this->thumbnailQuality = $q; + if (strlen($imgdata) <= $this->maxb) { + break; + } + } + } + if (strlen($imgdata) > $this->maxb) { + return false; + } + break; + + default: + return false; + break; + } + } + return true; + } + + + function CalculateThumbnailDimensions() { + $this->thumbnailCropX = ($this->sx ? (($this->sx >= 1) ? $this->sx : round($this->sx * $this->source_width)) : 0); + $this->thumbnailCropY = ($this->sy ? (($this->sy >= 1) ? $this->sy : round($this->sy * $this->source_height)) : 0); + $this->thumbnailCropW = ($this->sw ? (($this->sw >= 1) ? $this->sw : round($this->sw * $this->source_width)) : $this->source_width); + $this->thumbnailCropH = ($this->sh ? (($this->sh >= 1) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height); + + // limit source area to original image area + $this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width - $this->thumbnailCropX)); + $this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY)); + + $this->DebugMessage('CalculateThumbnailDimensions() [x,y,w,h] initially set to ['.$this->thumbnailCropX.','.$this->thumbnailCropY.','.$this->thumbnailCropW.','.$this->thumbnailCropH.']', __FILE__, __LINE__); + + + if ($this->zc && $this->w && $this->h) { + // Zoom Crop + // retain proportional resizing we did above, but crop off larger dimension so smaller + // dimension fully fits available space + + $scaling_X = $this->source_width / $this->w; + $scaling_Y = $this->source_height / $this->h; + if ($scaling_X > $scaling_Y) { + // some of the width will need to be cropped + $allowable_width = $this->source_width / $scaling_X * $scaling_Y; + $this->thumbnailCropW = round($allowable_width); + $this->thumbnailCropX = round(($this->source_width - $allowable_width) / 2); + + } elseif ($scaling_Y > $scaling_X) { + // some of the height will need to be cropped + $allowable_height = $this->source_height / $scaling_Y * $scaling_X; + $this->thumbnailCropH = round($allowable_height); + $this->thumbnailCropY = round(($this->source_height - $allowable_height) / 2); + + } else { + // image fits perfectly, no cropping needed + } + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = $this->thumbnail_height; + + } elseif ($this->iar && $this->w && $this->h) { + + // Ignore Aspect Ratio + // stretch image to fit exactly 'w' x 'h' + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = $this->thumbnail_height; + + } else { + + $original_aspect_ratio = $this->thumbnailCropW / $this->thumbnailCropH; + if ($this->aoe) { + $maxwidth = max($this->w, $this->thumbnailCropW); + $maxheight = max($this->h, $this->thumbnailCropH); + $maxwidth = max($maxwidth, $maxheight * $original_aspect_ratio); + $maxheight = max($maxheight, $maxwidth / $original_aspect_ratio); + } else { + $maxwidth = phpthumb_functions::nonempty_min($this->w, $this->thumbnailCropW, $this->config_output_maxwidth); + $maxheight = phpthumb_functions::nonempty_min($this->h, $this->thumbnailCropH, $this->config_output_maxheight); + $maxwidth = min($maxwidth, $maxheight * $original_aspect_ratio); + $maxheight = min($maxheight, $maxwidth / $original_aspect_ratio); + } + + $this->thumbnail_image_width = $maxwidth; + $this->thumbnail_image_height = $maxheight; + $this->thumbnail_width = $maxwidth; + $this->thumbnail_height = $maxheight; + + $this->FixedAspectRatio(); + } + + $this->thumbnail_width = max(1, floor($this->thumbnail_width)); + $this->thumbnail_height = max(1, floor($this->thumbnail_height)); + return true; + } + + + function CreateGDoutput() { + + $this->CalculateThumbnailDimensions(); + + // Create the GD image (either true-color or 256-color, depending on GD version) + $this->gdimg_output = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height); + + // Images that have transparency must have the background filled with the configured 'bg' color + // otherwise the transparent color will appear as black + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_output, true); + if ($this->is_alpha && phpthumb_functions::gd_version() >= 2) { + + ImageAlphaBlending($this->gdimg_output, false); + $output_full_alpha = phpthumb_functions::ImageColorAllocateAlphaSafe($this->gdimg_output, 255, 255, 255, 127); + ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha); + + } else { + + $current_transparent_color = ImageColorTransparent($this->gdimg_source); + if ($this->bg || (@$current_transparent_color >= 0)) { + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); + ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); + + } + + } + return true; + } + + function SetOrientationDependantWidthHeight() { + $this->DebugMessage('SetOrientationDependantWidthHeight() starting with "'.$this->source_width.'"x"'.$this->source_height.'"', __FILE__, __LINE__); + if ($this->source_height > $this->source_width) { + // portrait + $this->w = phpthumb_functions::OneOfThese($this->wp, $this->w, $this->ws, $this->wl); + $this->h = phpthumb_functions::OneOfThese($this->hp, $this->h, $this->hs, $this->hl); + } elseif ($this->source_height < $this->source_width) { + // landscape + $this->w = phpthumb_functions::OneOfThese($this->wl, $this->w, $this->ws, $this->wp); + $this->h = phpthumb_functions::OneOfThese($this->hl, $this->h, $this->hs, $this->hp); + } else { + // square + $this->w = phpthumb_functions::OneOfThese($this->ws, $this->w, $this->wl, $this->wp); + $this->h = phpthumb_functions::OneOfThese($this->hs, $this->h, $this->hl, $this->hp); + } + //$this->w = round($this->w ? $this->w : (($this->h && $this->source_height) ? $this->h * $this->source_width / $this->source_height : $this->w)); + //$this->h = round($this->h ? $this->h : (($this->w && $this->source_width) ? $this->w * $this->source_height / $this->source_width : $this->h)); + $this->DebugMessage('SetOrientationDependantWidthHeight() setting w="'.intval($this->w).'", h="'.intval($this->h).'"', __FILE__, __LINE__); + return true; + } + + function ExtractEXIFgetImageSize() { + $this->DebugMessage('starting ExtractEXIFgetImageSize()', __FILE__, __LINE__); + + if (is_resource($this->gdimg_source)) { + + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + $this->SetOrientationDependantWidthHeight(); + + } elseif ($this->rawImageData && !$this->sourceFilename) { + + $this->DebugMessage('bypassing EXIF and GetImageSize sections because $this->rawImageData is set and $this->sourceFilename is not set', __FILE__, __LINE__); + + } + + if (is_null($this->getimagesizeinfo)) { + $this->getimagesizeinfo = @GetImageSize($this->sourceFilename); + } + + if (!empty($this->getimagesizeinfo)) { + // great + $this->getimagesizeinfo['filesize'] = @filesize($this->sourceFilename); + } elseif (!$this->rawImageData) { + $this->DebugMessage('GetImageSize("'.$this->sourceFilename.'") failed', __FILE__, __LINE__); + } + + if ($this->config_prefer_imagemagick) { + if ($this->ImageMagickThumbnailToGD()) { + return true; + } + $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); + } + + $this->source_width = $this->getimagesizeinfo[0]; + $this->source_height = $this->getimagesizeinfo[1]; + + $this->SetOrientationDependantWidthHeight(); + + if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == 2)) { + // Extract EXIF info from JPEGs + + $this->exif_thumbnail_width = ''; + $this->exif_thumbnail_height = ''; + $this->exif_thumbnail_type = ''; + + // The parameters width, height and imagetype are available since PHP v4.3.0 + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + + $this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type); + + } else { + + // older versions of exif_thumbnail output an error message but NOT return false on failure + ob_start(); + $this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename); + $exit_thumbnail_error = ob_get_contents(); + ob_end_clean(); + if (!$exit_thumbnail_error && $this->exif_thumbnail_data) { + + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + $this->exif_thumbnail_width = ImageSX($gdimg_exif_temp); + $this->exif_thumbnail_height = ImageSY($gdimg_exif_temp); + $this->exif_thumbnail_type = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned + unset($gdimg_exif_temp); + } else { + return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in '.__FILE__.' on line '.__LINE__); + } + + } + + } + + } elseif (!function_exists('exif_thumbnail')) { + + $this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__); + return false; + + } + + $this->DebugMessage('EXIF thumbnail extraction: (size='.strlen($this->exif_thumbnail_data).'; type="'.$this->exif_thumbnail_type.'"; '.intval($this->exif_thumbnail_width).'x'.intval($this->exif_thumbnail_height).')', __FILE__, __LINE__); + + // see if EXIF thumbnail can be used directly with no processing + if ($this->config_use_exif_thumbnail_for_speed && $this->exif_thumbnail_data) { + while (true) { + if (!$this->xto) { + $source_ar = $this->source_width / $this->source_height; + $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; + if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { + $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); + break; + } + if ($this->w && ($this->w != $this->exif_thumbnail_width)) { + $this->DebugMessage('not using EXIF thumbnail because $this->w != $this->exif_thumbnail_width ('.$this->w.' != '.$this->exif_thumbnail_width.')', __FILE__, __LINE__); + break; + } + if ($this->h && ($this->h != $this->exif_thumbnail_height)) { + $this->DebugMessage('not using EXIF thumbnail because $this->h != $this->exif_thumbnail_height ('.$this->h.' != '.$this->exif_thumbnail_height.')', __FILE__, __LINE__); + break; + } + $CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'far', 'bg', 'bc', 'fltr', 'phpThumbDebug'); + foreach ($CannotBeSetParameters as $dummy => $parameter) { + if ($this->$parameter) { + break 2; + } + } + } + + $this->DebugMessage('setting $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data)', __FILE__, __LINE__); + $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + return true; + } + } + + if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) { + + // Source image is larger than would fit in available PHP memory. + // If ImageMagick is installed, use it to generate the thumbnail. + // Else, if an EXIF thumbnail is available, use that as the source image. + // Otherwise, no choice but to fail with an error message + $this->DebugMessage('image is '.$this->source_width.'x'.$this->source_height.' and therefore contains more pixels ('.($this->source_width * $this->source_height).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); + if (!$this->config_prefer_imagemagick && $this->ImageMagickThumbnailToGD()) { + // excellent, we have a thumbnailed source image + return true; + } + + } + return true; + } + + + function SetCacheFilename() { + if (!is_null($this->cache_filename)) { + $this->DebugMessage('$this->cache_filename already set, skipping SetCacheFilename()', __FILE__, __LINE__); + return true; + } + $this->setOutputFormat(); + $this->setCacheDirectory(); + if (!$this->config_cache_directory) { + $this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__); + return false; + } + + if (!$this->sourceFilename && !$this->rawImageData && $this->src) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); + } + + if ($this->config_cache_default_only_suffix && $this->sourceFilename) { + // simplified cache filenames: + // only use default parameters in phpThumb.config.php + // substitute source filename into * in $this->config_cache_default_only_suffix + // (eg: '*_thumb' becomes 'picture_thumb.jpg') + if (strpos($this->config_cache_default_only_suffix, '*') === false) { + $this->DebugMessage('aborting simplified caching filename because no * in "'.$this->config_cache_default_only_suffix.'"', __FILE__, __LINE__); + } else { + preg_match('/(.+)(\.[a-z0-9]+)?$/iU', basename($this->sourceFilename), $matches); + $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.str_replace('*', $matches[1], $this->config_cache_default_only_suffix).'.'.strtolower($this->thumbnailFormat); + return true; + } + } + + $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.$this->config_cache_prefix; + if ($this->new) { + $this->cache_filename .= '_new'.strtolower(md5($this->new)); + } elseif ($this->md5s) { + // source image MD5 hash provided + $this->DebugMessage('SetCacheFilename() _raw set from $this->md5s = "'.$this->md5s.'"', __FILE__, __LINE__); + $this->cache_filename .= '_raw'.$this->md5s; + } elseif (!$this->src && $this->rawImageData) { + $this->DebugMessage('SetCacheFilename() _raw set from md5($this->rawImageData) = "'.md5($this->rawImageData).'"', __FILE__, __LINE__); + $this->cache_filename .= '_raw'.strtolower(md5($this->rawImageData)); + } else { + $this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "'.$this->sourceFilename.'" = "'.md5($this->sourceFilename).'"', __FILE__, __LINE__); + $this->cache_filename .= '_src'.strtolower(md5($this->sourceFilename)); + } + if (@$_SERVER['HTTP_REFERER'] && $this->config_nooffsitelink_enabled) { + $parsed_url1 = @parse_url(@$_SERVER['HTTP_REFERER']); + $parsed_url2 = @parse_url('http://'.@$_SERVER['HTTP_HOST']); + if (@$parsed_url1['host'] && @$parsed_url2['host'] && ($parsed_url1['host'] != $parsed_url2['host'])) { + // include "_offsite" only if nooffsitelink_enabled and if referrer doesn't match the domain of the current server + $this->cache_filename .= '_offsite'; + } + } + + $ParametersString = ''; + if ($this->fltr && is_array($this->fltr)) { + $ParametersString .= '_fltr'.implode('_fltr', $this->fltr); + } + $FilenameParameters1 = array('ar', 'bg', 'bc', 'far'); + foreach ($FilenameParameters1 as $dummy => $key) { + if ($this->$key) { + $ParametersString .= '_'.$key.$this->$key; + } + } + $FilenameParameters2 = array('h', 'w', 'wl', 'wp', 'ws', 'hp', 'hs', 'sx', 'sy', 'sw', 'sh', 'xto', 'ra', 'iar', 'aoe', 'maxb'); + foreach ($FilenameParameters2 as $dummy => $key) { + if ($this->$key) { + $ParametersString .= '_'.$key.intval($this->$key); + } + } + if ($this->thumbnailFormat == 'jpeg') { + // only JPEG output has variable quality option + $ParametersString .= '_q'.intval($this->thumbnailQuality); + } + $this->DebugMessage('SetCacheFilename() _par set from md5('.$ParametersString.')', __FILE__, __LINE__); + $this->cache_filename .= '_par'.strtolower(md5($ParametersString)); + + if ($this->md5s) { + // source image MD5 hash provided + // do not source image modification date -- + // cached image will be used even if file was modified or removed + } elseif (!$this->config_cache_source_filemtime_ignore_remote && eregi('^(f|ht)tps?://', $this->src)) { + $this->cache_filename .= '_dat'.intval(phpthumb_functions::filedate_remote($this->src)); + } elseif (!$this->config_cache_source_filemtime_ignore_local && $this->src && !$this->rawImageData) { + $this->cache_filename .= '_dat'.intval(@filemtime($this->sourceFilename)); + } + + $this->cache_filename .= '.'.strtolower($this->thumbnailFormat); + + return true; + } + + + function ImageCreateFromFilename($filename, &$rawimagedata) { + // try to create GD image source directly via GD, if possible, + // rather than buffering to memory and creating with ImageCreateFromString + $ImageCreateWasAttempted = false; + $gd_image = false; + + $this->DebugMessage('starting ImageCreateFromFilename('.$filename.', ['.strlen($rawimagedata).' bytes])', __FILE__, __LINE__); + + if ($filename && ($getimagesizeinfo = @GetImageSize($filename))) { + if (($this->config_max_source_pixels > 0) && (($getimagesizeinfo[0] * $getimagesizeinfo[1]) > $this->config_max_source_pixels)) { + $ImageCreateFromFunction = array( + 1 => 'ImageCreateFromGIF', + 2 => 'ImageCreateFromJPEG', + 3 => 'ImageCreateFromPNG', + 15 => 'ImageCreateFromWBMP', + ); + $this->DebugMessage('ImageCreateFromFilename found ($getimagesizeinfo[2]=='.@$getimagesizeinfo[2].')', __FILE__, __LINE__); + switch (@$getimagesizeinfo[2]) { + case 1: // GIF + case 2: // JPEG + case 3: // PNG + case 15: // WBMP + $ImageCreateFromFunctionName = $ImageCreateFromFunction[$getimagesizeinfo[2]]; + if (function_exists($ImageCreateFromFunctionName)) { + $this->DebugMessage('Calling '.$ImageCreateFromFunctionName.'('.$filename.')', __FILE__, __LINE__); + $ImageCreateWasAttempted = true; + $gd_image = @$ImageCreateFromFunctionName($filename); + } else { + $this->DebugMessage('NOT calling '.$ImageCreateFromFunctionName.'('.$filename.') because !function_exists('.$ImageCreateFromFunctionName.')', __FILE__, __LINE__); + } + break; + + case 4: // SWF + case 5: // PSD + case 6: // BMP + case 7: // TIFF (LE) + case 8: // TIFF (BE) + case 9: // JPC + case 10: // JP2 + case 11: // JPX + case 12: // JB2 + case 13: // SWC + case 14: // IFF + case 16: // XBM + $this->DebugMessage('No built-in image creation function for image type "'.@$getimagesizeinfo[2].'" ($getimagesizeinfo[2])', __FILE__, __LINE__); + break; + + default: + $this->DebugMessage('Unknown value for $getimagesizeinfo[2]: "'.@$getimagesizeinfo[2].'"', __FILE__, __LINE__); + break; + } + } else { + $this->DebugMessage('image is '.$getimagesizeinfo[0].'x'.$getimagesizeinfo[1].' and therefore contains more pixels ('.($getimagesizeinfo[0] * $getimagesizeinfo[1]).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('empty $filename or GetImageSize('.$filename.') failed', __FILE__, __LINE__); + } + + if (!$gd_image) { + // cannot create from filename, attempt to create source image with ImageCreateFromString, if possible + if ($ImageCreateWasAttempted) { + $this->DebugMessage(@$ImageCreateFromFunctionName.'() was attempted but FAILED', __FILE__, __LINE__); + } + if (!$rawimagedata) { + $this->DebugMessage('Populating $rawimagedata', __FILE__, __LINE__); + if ($fp = @fopen($filename, 'rb')) { + + $rawimagedata = ''; + $filesize = filesize($filename); + $blocksize = 32768; + $blockreads = ceil($filesize / $blocksize); + for ($i = 0; $i < $blockreads; $i++) { + $rawimagedata .= fread($fp, $blocksize); + } + fclose($fp); + + } else { + $this->DebugMessage('cannot fopen('.$filename.')', __FILE__, __LINE__); + } + } + if ($rawimagedata) { + $this->DebugMessage('attempting ImageCreateFromStringReplacement($rawimagedata ('.strlen($rawimagedata).' bytes), true)', __FILE__, __LINE__); + $gd_image = $this->ImageCreateFromStringReplacement($rawimagedata, true); + } + } + return $gd_image; + } + + function SourceImageToGD() { + if (is_resource($this->gdimg_source)) { + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $this->DebugMessage('skipping SourceImageToGD() because $this->gdimg_source is already a resource ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); + return true; + } + $this->DebugMessage('starting SourceImageToGD()', __FILE__, __LINE__); + while (true) { + if (!$this->config_use_exif_thumbnail_for_speed) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__); + break; + } + if (!$this->exif_thumbnail_data) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty', __FILE__, __LINE__); + break; + } + if (($this->thumbnailCropX != 0) || ($this->thumbnailCropY != 0)) { + $this->DebugMessage('Not using EXIF thumbnail data because source cropping is enabled ('.$this->thumbnailCropX.','.$this->thumbnailCropY.')', __FILE__, __LINE__); + break; + } + if (($this->w > $this->exif_thumbnail_width) || ($this->h > $this->exif_thumbnail_height)) { + $this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small ('.$this->exif_thumbnail_width.'x'.$this->exif_thumbnail_height.' vs '.$this->w.'x'.$this->h.')', __FILE__, __LINE__); + break; + } + $source_ar = $this->source_width / $this->source_height; + $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; + if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { + $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); + } + + // EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image + $this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__); + + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + + $this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__); + $this->gdimg_source = $gdimg_exif_temp; + $this->source_width = $this->exif_thumbnail_width; + $this->source_height = $this->exif_thumbnail_height; + $this->thumbnailCropW = $this->source_width; + $this->thumbnailCropH = $this->source_height; + return true; + + } else { + $this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__); + } + + break; + } + if (!$this->gdimg_source) { + + if ($this->md5s && ($this->md5s != phpthumb_functions::md5_file_safe($this->sourceFilename))) { + return $this->ErrorImage('$this->md5s != md5($rawimagedata)'."\n".'"'.$this->md5s.'" != '."\n".'"'.phpthumb_functions::md5_file_safe($this->sourceFilename).'"'); + } + switch (@$this->getimagesizeinfo[2]) { + case 1: + case 3: + // GIF or PNG input file may have transparency + $this->is_alpha = true; + break; + } + + $this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename, $this->rawImageData); + + if ($this->md5s && ($this->md5s != md5($this->rawImageData))) { + return $this->ErrorImage('$this->md5s != md5($this->rawImageData)'."\n".'"'.$this->md5s.'" != '."\n".'"'.md5($this->rawImageData).'"'); + } + + if (!$this->gdimg_source) { + $this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__); + + if ($this->ImageMagickThumbnailToGD()) { + + // excellent, we have a thumbnailed source image + $this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__); + + } else { + + $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); + + $imageHeader = ''; + $gd_info = gd_info(); + $GDreadSupport = false; + switch (substr($this->rawImageData, 0, 3)) { + case 'GIF': + $imageHeader = 'Content-Type: image/gif'; + $GDreadSupport = (bool) @$gd_info['GIF Read Support']; + break; + case "\xFF\xD8\xFF": + $imageHeader = 'Content-Type: image/jpeg'; + $GDreadSupport = (bool) @$gd_info['JPG Support']; + break; + case "\x89".'PN': + $imageHeader = 'Content-Type: image/png'; + $GDreadSupport = (bool) @$gd_info['PNG Support']; + break; + } + if ($imageHeader) { + // cannot create image for whatever reason (maybe ImageCreateFromJPEG et al are not available?) + // and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit + if ($this->config_error_die_on_source_failure) { + $this->ErrorImage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), cannot generate thumbnail'); + } else { + //$this->DebugMessage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), outputing raw image', __FILE__, __LINE__); + //if (!$this->phpThumbDebug) { + // header($imageHeader); + // echo $this->rawImageData; + // exit; + //} + return false; + } + } + + switch (substr($this->rawImageData, 0, 2)) { + case 'BM': + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + ob_end_clean(); + return $this->ErrorImage('include_once('.dirname(__FILE__).'/phpthumb.bmp.php) failed'); + } + ob_end_clean(); + $phpthumb_bmp = new phpthumb_bmp(); + if ($this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, (phpthumb_functions::gd_version() >= 2.0))) { + $this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__); + break; + } + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on BMP source conversion' : 'phpthumb_bmp2gd() failed'); + break; + } + + + switch (substr($this->rawImageData, 0, 4)) { + case 'II'."\x2A\x00": + case 'MM'."\x00\x2A": + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on TIFF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support TIFF source images without it'); + break; + + case "\xD7\xCD\xC6\x9A": + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); + break; + } + + if (!$this->gdimg_source) { + return $this->ErrorImage('Unknown image type identified by "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()'); + } + + } + } + } + if (!$this->gdimg_source) { + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + $this->DebugMessage('All other attempts failed, but successfully using EXIF thumbnail as source image', __FILE__, __LINE__); + $this->gdimg_source = $gdimg_exif_temp; + // override allow-enlarging setting if EXIF thumbnail is the only source available + // otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size + $this->aoe = true; + return true; + } + return false; + } + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + return true; + } + + + function phpThumbDebugVarDump($var) { + if (is_null($var)) { + return 'NULL'; + } elseif (is_bool($var)) { + return ($var ? 'TRUE' : 'FALSE'); + } elseif (is_string($var)) { + return 'string('.strlen($var).')'.str_repeat(' ', max(0, 3 - strlen(strlen($var)))).' "'.$var.'"'; + } elseif (is_int($var)) { + return 'integer '.$var; + } elseif (is_float($var)) { + return 'float '.$var; + } elseif (is_array($var)) { + ob_start(); + var_dump($var); + $vardumpoutput = ob_get_contents(); + ob_end_clean(); + return strtr($vardumpoutput, "\n\r\t", ' '); + } + return gettype($var); + } + + function phpThumbDebug() { + if ($this->config_disable_debug) { + return $this->ErrorImage('phpThumbDebug disabled'); + } + + $FunctionsExistance = array('exif_thumbnail', 'gd_info', 'image_type_to_mime_type', 'ImageCopyResampled', 'ImageCopyResized', 'ImageCreate', 'ImageCreateFromString', 'ImageCreateTrueColor', 'ImageIsTrueColor', 'ImageRotate', 'ImageTypes', 'version_compare', 'ImageCreateFromGIF', 'ImageCreateFromJPEG', 'ImageCreateFromPNG', 'ImageCreateFromWBMP', 'ImageCreateFromXBM', 'ImageCreateFromXPM', 'ImageCreateFromString', 'ImageCreateFromGD', 'ImageCreateFromGD2', 'ImageCreateFromGD2Part', 'ImageJPEG', 'ImageGIF', 'ImagePNG', 'ImageWBMP'); + $ParameterNames = array('src', 'new', 'w', 'h', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'far', 'bg', 'bc', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'iar', 'maxb'); + $ConfigVariableNames = array('document_root', 'temp_directory', 'output_format', 'output_maxwidth', 'output_maxheight', 'error_message_image_default', 'error_bgcolor', 'error_textcolor', 'error_fontsize', 'error_die_on_error', 'error_silent_die_on_error', 'error_die_on_source_failure', 'nohotlink_enabled', 'nohotlink_valid_domains', 'nohotlink_erase_image', 'nohotlink_text_message', 'nooffsitelink_enabled', 'nooffsitelink_valid_domains', 'nooffsitelink_require_refer', 'nooffsitelink_erase_image', 'nooffsitelink_text_message', 'high_security_enabled', 'allow_src_above_docroot', 'allow_src_above_phpthumb', 'allow_parameter_file', 'allow_parameter_goto', 'max_source_pixels', 'use_exif_thumbnail_for_speed', 'border_hexcolor', 'background_hexcolor', 'ttf_directory', 'disable_pathinfo_parsing', 'disable_imagecopyresampled'); + $OtherVariableNames = array('phpThumbDebug', 'thumbnailQuality', 'thumbnailFormat', 'gdimg_output', 'gdimg_source', 'sourceFilename', 'source_width', 'source_height', 'thumbnailCropX', 'thumbnailCropY', 'thumbnailCropW', 'thumbnailCropH', 'exif_thumbnail_width', 'exif_thumbnail_height', 'exif_thumbnail_type', 'thumbnail_width', 'thumbnail_height', 'thumbnail_image_width', 'thumbnail_image_height'); + + $DebugOutput = array(); + $DebugOutput[] = 'phpThumb() version = '.$this->phpthumb_version; + $DebugOutput[] = 'phpversion() = '.@phpversion(); + $DebugOutput[] = 'PHP_OS = '.PHP_OS; + $DebugOutput[] = '__FILE__ = '.__FILE__; + $DebugOutput[] = 'realpath(.) = '.@realpath('.'); + $DebugOutput[] = '$_SERVER[PHP_SELF] = '.@$_SERVER['PHP_SELF']; + $DebugOutput[] = '$_SERVER[HTTP_REFERER] = '.@$_SERVER['HTTP_REFERER']; + $DebugOutput[] = '$_SERVER[QUERY_STRING] = '.@$_SERVER['QUERY_STRING']; + $DebugOutput[] = '$_SERVER[PATH_INFO] = '.@$_SERVER['PATH_INFO']; + $DebugOutput[] = '$_SERVER[DOCUMENT_ROOT] = '.@$_SERVER['DOCUMENT_ROOT']; + $DebugOutput[] = 'getenv(DOCUMENT_ROOT) = '.@getenv('DOCUMENT_ROOT'); + $DebugOutput[] = ''; + + $DebugOutput[] = 'get_magic_quotes_gpc() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_gpc()); + $DebugOutput[] = 'get_magic_quotes_runtime() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_runtime()); + $DebugOutput[] = 'error_reporting() = '.$this->phpThumbDebugVarDump(error_reporting()); + $DebugOutput[] = 'ini_get(error_reporting) = '.$this->phpThumbDebugVarDump(@ini_get('error_reporting')); + $DebugOutput[] = 'ini_get(display_errors) = '.$this->phpThumbDebugVarDump(@ini_get('display_errors')); + $DebugOutput[] = 'ini_get(allow_url_fopen) = '.$this->phpThumbDebugVarDump(@ini_get('allow_url_fopen')); + $DebugOutput[] = 'ini_get(disable_functions) = '.$this->phpThumbDebugVarDump(@ini_get('disable_functions')); + $DebugOutput[] = 'ini_get(safe_mode) = '.$this->phpThumbDebugVarDump(@ini_get('safe_mode')); + $DebugOutput[] = 'ini_get(open_basedir) = '.$this->phpThumbDebugVarDump(@ini_get('open_basedir')); + $DebugOutput[] = 'ini_get(memory_limit) = '.$this->phpThumbDebugVarDump(@ini_get('memory_limit')); + $DebugOutput[] = 'ini_get(max_execution_time) = '.$this->phpThumbDebugVarDump(@ini_get('max_execution_time')); + $DebugOutput[] = 'get_cfg_var(memory_limit) = '.$this->phpThumbDebugVarDump(@get_cfg_var('memory_limit')); + $DebugOutput[] = 'memory_get_usage() = '.(function_exists('memory_get_usage') ? $this->phpThumbDebugVarDump(@memory_get_usage()) : 'n/a'); + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->config_prefer_imagemagick = '.$this->phpThumbDebugVarDump($this->config_prefer_imagemagick); + $DebugOutput[] = '$this->config_imagemagick_path = '.$this->phpThumbDebugVarDump($this->config_imagemagick_path); + $DebugOutput[] = '$this->ImageMagickWhichConvert() = '.$this->ImageMagickWhichConvert(); + $IMpathUsed = ($this->config_imagemagick_path ? $this->config_imagemagick_path : $this->ImageMagickWhichConvert()); + $DebugOutput[] = '[actual ImageMagick path used] = '.$this->phpThumbDebugVarDump($IMpathUsed); + $DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(@file_exists($IMpathUsed)); + $DebugOutput[] = 'ImageMagickVersion() = '.$this->ImageMagickVersion(); + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->config_cache_directory = '.$this->phpThumbDebugVarDump($this->config_cache_directory); + $DebugOutput[] = '$this->config_cache_disable_warning = '.$this->phpThumbDebugVarDump($this->config_cache_disable_warning); + $DebugOutput[] = '$this->config_cache_maxage = '.$this->phpThumbDebugVarDump($this->config_cache_maxage); + $DebugOutput[] = '$this->config_cache_maxsize = '.$this->phpThumbDebugVarDump($this->config_cache_maxsize); + $DebugOutput[] = '$this->config_cache_maxfiles = '.$this->phpThumbDebugVarDump($this->config_cache_maxfiles); + $DebugOutput[] = '$this->config_cache_force_passthru = '.$this->phpThumbDebugVarDump($this->config_cache_force_passthru); + $DebugOutput[] = '$this->cache_filename = '.$this->phpThumbDebugVarDump($this->cache_filename); + $DebugOutput[] = 'is_readable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(is_readable($this->config_cache_directory)); + $DebugOutput[] = 'is_writable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(is_writable($this->config_cache_directory)); + $DebugOutput[] = 'is_readable($this->cache_filename) = '.$this->phpThumbDebugVarDump(is_readable($this->cache_filename)); + $DebugOutput[] = 'is_writable($this->cache_filename) = '.(file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(is_writable($this->cache_filename)) : 'n/a'); + $DebugOutput[] = ''; + + foreach ($ConfigVariableNames as $dummy => $varname) { + $varname = 'config_'.$varname; + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 37, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + foreach ($OtherVariableNames as $dummy => $varname) { + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 27, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = 'strlen($this->rawImageData) = '.strlen(@$this->rawImageData); + $DebugOutput[] = 'strlen($this->exif_thumbnail_data) = '.strlen(@$this->exif_thumbnail_data); + $DebugOutput[] = ''; + + foreach ($ParameterNames as $dummy => $varname) { + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 4, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + foreach ($FunctionsExistance as $dummy => $functionname) { + $DebugOutput[] = 'builtin_function_exists('.$functionname.')'.str_repeat(' ', 23 - strlen($functionname)).' = '.$this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname)); + } + $DebugOutput[] = ''; + + $gd_info = gd_info(); + foreach ($gd_info as $key => $value) { + $DebugOutput[] = 'gd_info.'.str_pad($key, 34, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + $exif_info = phpthumb_functions::exif_info(); + foreach ($exif_info as $key => $value) { + $DebugOutput[] = 'exif_info.'.str_pad($key, 26, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { + foreach ($ApacheLookupURIarray as $key => $value) { + $DebugOutput[] = 'ApacheLookupURIarray.'.str_pad($key, 15, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + } else { + $DebugOutput[] = 'ApacheLookupURIarray() -- FAILED'; + } + $DebugOutput[] = ''; + + if (isset($_GET) && is_array($_GET)) { + foreach ($_GET as $key => $value) { + $DebugOutput[] = '$_GET['.$key.']'.str_repeat(' ', 30 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); + } + } + if (isset($_POST) && is_array($_POST)) { + foreach ($_POST as $key => $value) { + $DebugOutput[] = '$_POST['.$key.']'.str_repeat(' ', 29 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); + } + } + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->debugmessages:'; + foreach ($this->debugmessages as $dummy => $errorstring) { + $DebugOutput[] = ' * '.$errorstring; + } + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->debugtiming:'; + foreach ($this->debugtiming as $timestamp => $timingstring) { + $DebugOutput[] = ' * '.$timestamp.' '.$timingstring; + } + $DebugOutput[] = ' * Total processing time: '.number_format(max(array_keys($this->debugtiming)) - min(array_keys($this->debugtiming)), 6); + + return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500, true); + } + + function ErrorImage($text, $width=0, $height=0, $forcedisplay=false) { + $width = ($width ? $width : $this->config_error_image_width); + $height = ($height ? $height : $this->config_error_image_height); + + $text = 'phpThumb() v'.$this->phpthumb_version."\n\n".$text; + if ($this->config_disable_debug) { + $text = 'Error messages disabled'; + } + + $this->DebugMessage($text, __FILE__, __LINE__); + if ($this->phpThumbDebug && !$forcedisplay) { + return false; + } + if (!$this->config_error_die_on_error && !$forcedisplay) { + $this->fatalerror = $text; + return false; + } + if ($this->config_error_silent_die_on_error) { + exit; + } + if ($this->err || $this->config_error_message_image_default) { + // Show generic custom error image instead of error message + // for use on production sites where you don't want debug messages + if ($this->err == 'showerror') { + // fall through and actually show error message even if default error image is set + } else { + header('Location: '.($this->err ? $this->err : $this->config_error_message_image_default)); + exit; + } + } + if (!$this->thumbnailFormat || (phpthumb_functions::gd_version() < 1)) { + $this->thumbnailFormat = 'text'; + } + if (@$this->thumbnailFormat == 'text') { + // bypass all GD functions and output text error message + die('
    '.$text.'
    '); + } + + $FontWidth = ImageFontWidth($this->config_error_fontsize); + $FontHeight = ImageFontHeight($this->config_error_fontsize); + + $LinesOfText = explode("\n", @wordwrap($text, floor($width / $FontWidth), "\n", true)); + $height = max($height, count($LinesOfText) * $FontHeight); + + $headers_file = ''; + $headers_line = ''; + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=') && headers_sent($headers_file, $headers_line)) { + + echo "\n".'**Headers already sent in file "'.$headers_file.'" on line "'.$headers_line.'", dumping error message as text:**
    '."\n\n".$text."\n".'
    '; + + } elseif (headers_sent()) { + + echo "\n".'**Headers already sent, dumping error message as text:**
    '."\n\n".$text."\n".'
    '; + + } elseif ($gdimg_error = ImageCreate($width, $height)) { + + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor, true); + $text_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true); + ImageFilledRectangle($gdimg_error, 0, 0, $width, $height, $background_color); + $lineYoffset = 0; + foreach ($LinesOfText as $dummy => $line) { + ImageString($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color); + $lineYoffset += $FontHeight; + } + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_PNG) { + header('Content-Type: image/png'); + ImagePNG($gdimg_error); + } elseif ($imagetypes & IMG_GIF) { + header('Content-Type: image/gif'); + ImageGIF($gdimg_error); + } elseif ($imagetypes & IMG_JPG) { + header('Content-Type: image/jpeg'); + ImageJPEG($gdimg_error); + } elseif ($imagetypes & IMG_WBMP) { + header('Content-Type: image/wbmp'); + ImageWBMP($gdimg_error); + } + } + ImageDestroy($gdimg_error); + + } + if (!headers_sent()) { + echo "\n".'**Failed to send graphical error image, dumping error message as text:**
    '."\n\n".$text; + } + exit; + return true; + } + + function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors=false) { + // there are serious bugs in the non-bundled versions of GD which may cause + // PHP to segfault when calling ImageCreateFromString() - avoid if at all possible + // when not using a bundled version of GD2 + if (phpthumb_functions::gd_is_bundled()) { + return @ImageCreateFromString($RawImageData); + } + if (ini_get('safe_mode')) { + $this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__); + return false; + } + + switch (substr($RawImageData, 0, 3)) { + case 'GIF': + $ICFSreplacementFunctionName = 'ImageCreateFromGIF'; + break; + case "\xFF\xD8\xFF": + $ICFSreplacementFunctionName = 'ImageCreateFromJPEG'; + break; + case "\x89".'PN': + $ICFSreplacementFunctionName = 'ImageCreateFromPNG'; + break; + default: + $this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "'.phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)).'"', __FILE__, __LINE__); + return false; + break; + } + if ($tempnam = $this->phpThumb_tempnam()) { + if ($fp_tempnam = @fopen($tempnam, 'wb')) { + fwrite($fp_tempnam, $RawImageData); + fclose($fp_tempnam); + if (($ICFSreplacementFunctionName == 'ImageCreateFromGIF') && !function_exists($ICFSreplacementFunctionName)) { + + // Need to create from GIF file, but ImageCreateFromGIF does not exist + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.gif.php')) { + $ErrorMessage = 'Failed to include required file "'.dirname(__FILE__).'/phpthumb.gif.php" in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + ob_end_clean(); + // gif_loadFileToGDimageResource() cannot read from raw data, write to file first + if ($tempfilename = $this->phpThumb_tempnam()) { + if ($fp_tempfile = @fopen($tempfilename, 'wb')) { + fwrite($fp_tempfile, $RawImageData); + fclose($fp_tempfile); + $gdimg_source = gif_loadFileToGDimageResource($tempfilename); + unlink($tempfilename); + return $gdimg_source; + break; + } else { + $ErrorMessage = 'Failed to open tempfile in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + } else { + $ErrorMessage = 'Failed to open generate tempfile name in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + + } elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam))) { + + // great + unlink($tempnam); + return $gdimg_source; + + } else { // GD functions not available + + if (!headers_sent()) { + // base64-encoded error image in GIF format + $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; + header('Content-Type: image/gif'); + echo base64_decode($ERROR_NOGD); + } else { + echo '*** ERROR: No PHP-GD support available ***'; + } + exit; + + } + } else { + $ErrorMessage = 'Failed to fopen('.$tempnam.', "wb") in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + @unlink($tempnam); + } else { + $ErrorMessage = 'Failed to generate phpThumb_tempnam() in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; + } + if ($DieOnErrors && $ErrorMessage) { + return $this->ErrorImage($ErrorMessage); + } + return false; + } + + function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) { + if (phpthumb_functions::gd_version() >= 2.0) { + if ($this->config_disable_imagecopyresampled) { + return phpthumb_functions::ImageCopyResampleBicubic($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + return ImageCopyResampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + return ImageCopyResized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + + function phpThumb_tempnam() { + if (!$this->config_temp_directory) { + $this->config_temp_directory = (getenv('TMPDIR') ? getenv('TMPDIR') : getenv('TMP')); + } + $tempnam = realpath(tempnam($this->config_temp_directory, 'pThumb')); + $this->DebugMessage('phpThumb_tempnam() returning "'.$tempnam.'"', __FILE__, __LINE__); + return $tempnam; + } + + function DebugMessage($message, $file='', $line='') { + $this->debugmessages[] = $message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); + return true; + } + + function DebugTimingMessage($message, $file='', $line='', $timestamp=0) { + if (!$timestamp) { + $timestamp = array_sum(explode(' ', microtime())); + } + $this->debugtiming[number_format($timestamp, 6, '.', '')] = ': '.$message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); + return true; + } + +} + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/phpthumb.filters.php b/site/retailers/phpthumb/phpthumb.filters.php new file mode 100644 index 0000000..ac058cb --- /dev/null +++ b/site/retailers/phpthumb/phpthumb.filters.php @@ -0,0 +1,1235 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.filters.php - image processing filter functions // +// /// +////////////////////////////////////////////////////////////// + +class phpthumb_filters { + + var $phpThumbObject = null; + + function phpthumb_filters() { + return true; + } + + function ApplyMask(&$gdimg_mask, &$gdimg_image) { + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping ApplyMask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=')) { + + $this->DebugMessage('Using alpha ApplyMask() technique', __FILE__, __LINE__); + if ($gdimg_mask_resized = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { + + ImageCopyResampled($gdimg_mask_resized, $gdimg_mask, 0, 0, 0, 0, ImageSX($gdimg_image), ImageSY($gdimg_image), ImageSX($gdimg_mask), ImageSY($gdimg_mask)); + if ($gdimg_mask_blendtemp = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { + + $color_background = ImageColorAllocate($gdimg_mask_blendtemp, 0, 0, 0); + ImageFilledRectangle($gdimg_mask_blendtemp, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp), $color_background); + ImageAlphaBlending($gdimg_mask_blendtemp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_mask_blendtemp, true); + for ($x = 0; $x < ImageSX($gdimg_image); $x++) { + for ($y = 0; $y < ImageSY($gdimg_image); $y++) { + //$RealPixel = phpthumb_functions::GetPixelColor($gdimg_mask_blendtemp, $x, $y); + $RealPixel = phpthumb_functions::GetPixelColor($gdimg_image, $x, $y); + $MaskPixel = phpthumb_functions::GrayscalePixel(phpthumb_functions::GetPixelColor($gdimg_mask_resized, $x, $y)); + $MaskAlpha = 127 - (floor($MaskPixel['red'] / 2) * (1 - ($RealPixel['alpha'] / 127))); + $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_mask_blendtemp, $RealPixel['red'], $RealPixel['green'], $RealPixel['blue'], $MaskAlpha); + ImageSetPixel($gdimg_mask_blendtemp, $x, $y, $newcolor); + } + } + ImageAlphaBlending($gdimg_image, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_image, true); + ImageCopy($gdimg_image, $gdimg_mask_blendtemp, 0, 0, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp)); + ImageDestroy($gdimg_mask_blendtemp); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + ImageDestroy($gdimg_mask_resized); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + + } else { + // alpha merging requires PHP v4.3.2+ + $this->DebugMessage('Skipping ApplyMask() technique because PHP is v"'.phpversion().'"', __FILE__, __LINE__); + } + return true; + } + + + function Bevel(&$gdimg, $width, $hexcolor1, $hexcolor2) { + $width = ($width ? $width : 5); + $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); + $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); + + ImageAlphaBlending($gdimg, true); + for ($i = 0; $i < $width; $i++) { + $alpha = round(($i / $width) * 127); + $color1[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1, false, $alpha); + $color2[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2, false, $alpha); + + ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1[$i]); // left + ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1[$i]); // top + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2[$i]); // right + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2[$i]); // bottom + } + return true; + } + + + function Blur(&$gdimg, $radius=0.5) { + // Taken from Torstein Hønsi's phpUnsharpMask (see phpthumb.unsharp.php) + + $radius = round(max(0, min($radius, 50)) * 2); + if (!$radius) { + return false; + } + + $w = ImageSX($gdimg); + $h = ImageSY($gdimg); + if ($imgBlur = ImageCreateTrueColor($w, $h)) { + // Gaussian blur matrix: + // 1 2 1 + // 2 4 2 + // 1 2 1 + + // Move copies of the image around one pixel at the time and merge them with weight + // according to the matrix. The same matrix is simply repeated for higher radii. + for ($i = 0; $i < $radius; $i++) { + ImageCopy ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1); // up left + ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w, $h, 50.00000); // down right + ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left + ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w, $h - 1, 25.00000); // up right + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left + ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w, $h, 25.00000); // right + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w, $h - 1, 20.00000); // up + ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w, $h, 16.666667); // down + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w, $h, 50.000000); // center + ImageCopy ($gdimg, $imgBlur, 0, 0, 0, 0, $w, $h); + } + return true; + } + return false; + } + + + function BlurGaussian(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)', __FILE__, __LINE__); + // fall through and try it the hard way + } + $this->DebugMessage('FAILED: phpthumb_filters::BlurGaussian($gdimg) [using phpthumb_filters::Blur() instead]', __FILE__, __LINE__); + return phpthumb_filters::Blur($gdimg, 0.5); + } + + + function BlurSelective(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::BlurSelective($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Brightness(&$gdimg, $amount=0) { + if ($amount == 0) { + return true; + } + $amount = max(-255, min(255, $amount)); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + + $scaling = (255 - abs($amount)) / 255; + $baseamount = (($amount > 0) ? $amount : 0); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + foreach ($OriginalPixel as $key => $value) { + $NewPixel[$key] = round($baseamount + ($OriginalPixel[$key] * $scaling)); + } + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Contrast(&$gdimg, $amount=0) { + if ($amount == 0) { + return true; + } + $amount = max(-255, min(255, $amount)); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_CONTRAST, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_CONTRAST, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + + if ($amount > 0) { + $scaling = 1 + ($amount / 255); + } else { + $scaling = (255 - abs($amount)) / 255; + } + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + foreach ($OriginalPixel as $key => $value) { + $NewPixel[$key] = min(255, max(0, round($OriginalPixel[$key] * $scaling))); + } + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + } + + + function Colorize(&$gdimg, $amount, $targetColor) { + $amount = (is_numeric($amount) ? $amount : 25); + $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'gray'); + + if ($amount == 0) { + return true; + } + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if ($targetColor == 'gray') { + $targetColor = '808080'; + } + $r = substr($targetColor, 0, 2); + $g = substr($targetColor, 2, 2); + $b = substr($targetColor, 4, 2); + if (ImageFilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + + // overridden below for grayscale + if ($targetColor != 'gray') { + $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); + $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); + $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); + } + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + if ($targetColor == 'gray') { + $TargetPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + } + foreach ($TargetPixel as $key => $value) { + $NewPixel[$key] = round(max(0, min(255, ($OriginalPixel[$key] * ((100 - $amount) / 100)) + ($TargetPixel[$key] * ($amount / 100))))); + } + //$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Desaturate(&$gdimg, $amount, $color='') { + if ($amount == 0) { + return true; + } + return phpthumb_filters::Colorize($gdimg, $amount, (phpthumb_functions::IsHexColor($color) ? $color : 'gray')); + } + + + function DropShadow(&$gdimg, $distance, $width, $hexcolor, $angle, $fade) { + if (phpthumb_functions::gd_version() < 2) { + return false; + } + $distance = ($distance ? $distance : 10); + $width = ($width ? $width : 10); + $hexcolor = ($hexcolor ? $hexcolor : '000000'); + $angle = ($angle ? $angle : 225); + $fade = ($fade ? $fade : 1); + + $width_shadow = cos(deg2rad($angle)) * ($distance + $width); + $height_shadow = sin(deg2rad($angle)) * ($distance + $width); + + $scaling = min(ImageSX($gdimg) / (ImageSX($gdimg) + abs($width_shadow)), ImageSY($gdimg) / (ImageSY($gdimg) + abs($height_shadow))); + + for ($i = 0; $i < $width; $i++) { + $WidthAlpha[$i] = (abs(($width / 2) - $i) / $width) * $fade; + $Offset['x'] = cos(deg2rad($angle)) * ($distance + $i); + $Offset['y'] = sin(deg2rad($angle)) * ($distance + $i); + } + + $tempImageWidth = ImageSX($gdimg) + abs($Offset['x']); + $tempImageHeight = ImageSY($gdimg) + abs($Offset['y']); + + if ($gdimg_dropshadow_temp = phpthumb_functions::ImageCreateFunction($tempImageWidth, $tempImageHeight)) { + + ImageAlphaBlending($gdimg_dropshadow_temp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_dropshadow_temp, true); + $transparent1 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, 0, 0, 0, 127); + ImageFill($gdimg_dropshadow_temp, 0, 0, $transparent1); + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $PixelMap[$x][$y] = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + } + } + for ($x = 0; $x < $tempImageWidth; $x++) { + for ($y = 0; $y < $tempImageHeight; $y++) { + //for ($i = 0; $i < $width; $i++) { + for ($i = 0; $i < 1; $i++) { + if (!isset($PixelMap[$x][$y]['alpha']) || ($PixelMap[$x][$y]['alpha'] > 0)) { + if (isset($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']) && ($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha'] < 127)) { + $thisColor = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor, false, $PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']); + ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); + } + } + } + } + } + + ImageAlphaBlending($gdimg_dropshadow_temp, true); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + if ($PixelMap[$x][$y]['alpha'] < 127) { + $thisColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, $PixelMap[$x][$y]['red'], $PixelMap[$x][$y]['green'], $PixelMap[$x][$y]['blue'], $PixelMap[$x][$y]['alpha']); + ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); + } + } + } + + phpthumb_functions::gd_ImageSaveAlpha($gdimg, true); + ImageAlphaBlending($gdimg, false); + //$this->is_alpha = true; + $transparent2 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0, 0, 0, 127); + ImageFilledRectangle($gdimg, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $transparent2); + ImageCopyResampled($gdimg, $gdimg_dropshadow_temp, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg_dropshadow_temp), ImageSY($gdimg_dropshadow_temp)); + + ImageDestroy($gdimg_dropshadow_temp); + } + return true; + } + + + function EdgeDetect(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::EdgeDetect($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Elipse($gdimg) { + if (phpthumb_functions::gd_version() < 2) { + return false; + } + // generate mask at twice desired resolution and downsample afterwards for easy antialiasing + if ($gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg) * 2, ImageSY($gdimg) * 2)) { + if ($gdimg_elipsemask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + + $color_transparent = ImageColorAllocate($gdimg_elipsemask_double, 255, 255, 255); + ImageFilledEllipse($gdimg_elipsemask_double, ImageSX($gdimg), ImageSY($gdimg), (ImageSX($gdimg) - 1) * 2, (ImageSY($gdimg) - 1) * 2, $color_transparent); + ImageCopyResampled($gdimg_elipsemask, $gdimg_elipsemask_double, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg) * 2, ImageSY($gdimg) * 2); + + phpthumb_filters::ApplyMask($gdimg_elipsemask, $gdimg); + ImageDestroy($gdimg_elipsemask); + return true; + + } else { + $this->DebugMessage('$gdimg_elipsemask = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); + } + ImageDestroy($gdimg_elipsemask_double); + } else { + $this->DebugMessage('$gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); + } + return false; + } + + + function Emboss(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_EMBOSS)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EMBOSS)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::Emboss($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Flip(&$gdimg, $x=false, $y=false) { + if (!$x && !$y) { + return false; + } + if ($tempImage = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + if ($x) { + ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + ImageCopy($gdimg, $tempImage, ImageSX($gdimg) - 1 - $x, 0, $x, 0, 1, ImageSY($gdimg)); + } + } + if ($y) { + ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); + for ($y = 0; $y < ImageSY($gdimg); $y++) { + ImageCopy($gdimg, $tempImage, 0, ImageSY($gdimg) - 1 - $y, 0, $y, ImageSX($gdimg), 1); + } + } + ImageDestroy($tempImage); + } + return true; + } + + + function Frame(&$gdimg, $frame_width, $edge_width, $hexcolor_frame, $hexcolor1, $hexcolor2) { + $frame_width = ($frame_width ? $frame_width : 5); + $edge_width = ($edge_width ? $edge_width : 1); + $hexcolor_frame = ($hexcolor_frame ? $hexcolor_frame : 'CCCCCC'); + $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); + $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); + + $color_frame = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor_frame); + $color1 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1); + $color2 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2); + for ($i = 0; $i < $edge_width; $i++) { + // outer bevel + ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1); // left + ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1); // top + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2); // right + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2); // bottom + } + for ($i = 0; $i < $frame_width; $i++) { + // actual frame + ImageRectangle($gdimg, $edge_width + $i, $edge_width + $i, ImageSX($gdimg) - $edge_width - $i, ImageSY($gdimg) - $edge_width - $i, $color_frame); + } + for ($i = 0; $i < $edge_width; $i++) { + // inner bevel + ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color2); // left + ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color2); // top + ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color1); // right + ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color1); // bottom + } + return true; + } + + + function Gamma(&$gdimg, $amount) { + if (number_format($amount, 4) == '1.0000') { + return true; + } + return ImageGammaCorrect($gdimg, 1.0, $amount); + } + + + function Grayscale(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + return phpthumb_filters::Colorize($gdimg, 100, 'gray'); + } + + + function HistogramAnalysis(&$gdimg, $calculateGray=false) { + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + @$Analysis['red'][$OriginalPixel['red']]++; + @$Analysis['green'][$OriginalPixel['green']]++; + @$Analysis['blue'][$OriginalPixel['blue']]++; + @$Analysis['alpha'][$OriginalPixel['alpha']]++; + if ($calculateGray) { + $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + @$Analysis['gray'][$GrayPixel['red']]++; + } + } + } + $keys = array('red', 'green', 'blue', 'alpha'); + if ($calculateGray) { + $keys[] = 'gray'; + } + foreach ($keys as $dummy => $key) { + ksort($Analysis[$key]); + } + return $Analysis; + } + + + function HistogramStretch(&$gdimg, $band='*', $min=-1, $max=-1) { + // equivalent of "Auto Contrast" in Adobe Photoshop + + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); + $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); + if (!isset($keys[$band])) { + return false; + } + $key = $keys[$band]; + + // If the absolute brightest and darkest pixels are used then one random + // pixel in the image could throw off the whole system. Instead, count up/down + // from the limit and allow 0.1% of brightest/darkest pixels to be clipped to min/max + $clip_threshold = ImageSX($gdimg) * ImageSX($gdimg) * 0.001; + if ($min >= 0) { + $range_min = min($min, 255); + } else { + $countsum = 0; + for ($i = 0; $i <= 255; $i++) { + $countsum += @$Analysis[$key][$i]; + if ($countsum >= $clip_threshold) { + $range_min = $i - 1; + break; + } + } + $range_min = max($range_min, 0); + } + if ($max >= 0) { + $range_max = max($max, 255); + } else { + $countsum = 0; + $threshold = ImageSX($gdimg) * ImageSX($gdimg) * 0.001; // 0.1% of brightest and darkest pixels can be clipped + for ($i = 255; $i >= 0; $i--) { + $countsum += @$Analysis[$key][$i]; + if ($countsum >= $clip_threshold) { + $range_max = $i + 1; + break; + } + } + $range_max = min($range_max, 255); + } + $range_scale = (($range_max == $range_min) ? 1 : (255 / ($range_max - $range_min))); + if (($range_min == 0) && ($range_max == 255)) { + // no adjustment neccesary - don't waste CPU time! + return true; + } + + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + if ($band == '*') { + $new['red'] = min(255, max(0, ($OriginalPixel['red'] - $range_min) * $range_scale)); + $new['green'] = min(255, max(0, ($OriginalPixel['green'] - $range_min) * $range_scale)); + $new['blue'] = min(255, max(0, ($OriginalPixel['blue'] - $range_min) * $range_scale)); + $new['alpha'] = min(255, max(0, ($OriginalPixel['alpha'] - $range_min) * $range_scale)); + } else { + $new = $OriginalPixel; + $new[$key] = min(255, max(0, ($OriginalPixel[$key] - $range_min) * $range_scale)); + } + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $new['red'], $new['green'], $new['blue'], $new['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + + return true; + } + + + function HistogramOverlay(&$gdimg, $bands='*', $colors='', $width=0.25, $height=0.25, $alignment='BR', $opacity=50, $margin=5) { + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); + + $histW = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); + $histH = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); + if ($gdHist = ImageCreateTrueColor($histW, $histH)) { + $color_back = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHist, 0, 0, 0, 127); + ImageFilledRectangle($gdHist, 0, 0, $histW, $histH, $color_back); + ImageAlphaBlending($gdHist, false); + phpthumb_functions::gd_ImageSaveAlpha($gdHist, true); + + if ($gdHistTemp = ImageCreateTrueColor(256, 100)) { + $color_back_temp = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHistTemp, 255, 0, 255, 127); + ImageAlphaBlending($gdHistTemp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdHistTemp, true); + ImageFilledRectangle($gdHistTemp, 0, 0, ImageSX($gdHistTemp), ImageSY($gdHistTemp), $color_back_temp); + + $DefaultColors = array('r'=>'FF0000', 'g'=>'00FF00', 'b'=>'0000FF', 'a'=>'999999', '*'=>'FFFFFF'); + $Colors = explode(';', $colors); + $BandsToGraph = array_unique(preg_split('//', $bands)); + $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); + foreach ($BandsToGraph as $key => $band) { + if (!isset($keys[$band])) { + continue; + } + $PeakValue = max($Analysis[$keys[$band]]); + $thisColor = phpthumb_functions::ImageHexColorAllocate($gdHistTemp, phpthumb_functions::IsHexColor(@$Colors[$key]) ? $Colors[$key] : $DefaultColors[$band]); + $tempHeight = ImageSY($gdHistTemp); + for ($x = 0; $x <= 255; $x++) { + ImageLine($gdHistTemp, $x, $tempHeight - 1, $x, $tempHeight - 1 - round(@$Analysis[$keys[$band]][$x] / $PeakValue * $tempHeight), $thisColor); + } + ImageLine($gdHistTemp, 0, $tempHeight - 1, 255, $tempHeight - 1, $thisColor); + ImageLine($gdHistTemp, 0, $tempHeight - 2, 255, $tempHeight - 2, $thisColor); + } + ImageCopyResampled($gdHist, $gdHistTemp, 0, 0, 0, 0, ImageSX($gdHist), ImageSY($gdHist), ImageSX($gdHistTemp), ImageSY($gdHistTemp)); + ImageDestroy($gdHistTemp); + } else { + return false; + } + + phpthumb_filters::WatermarkOverlay($gdimg, $gdHist, $alignment, $opacity, $margin); + ImageDestroy($gdHist); + return true; + } + return false; + } + + + function ImageBorder(&$gdimg, $border_width, $radius_x, $radius_y, $hexcolor_border) { + $border_width = ($border_width ? $border_width : 1); + $radius_x = ($radius_x ? $radius_x : 0); + $radius_y = ($radius_y ? $radius_y : 0); + + $output_width = ImageSX($gdimg); + $output_height = ImageSY($gdimg); + + list($new_width, $new_height) = phpthumb_functions::ProportionalResize($output_width, $output_height, $output_width - max($border_width * 2, $radius_x), $output_height - max($border_width * 2, $radius_y)); + $offset_x = ($radius_x ? $output_width - $new_width - $radius_x : 0); + $offset_y = ($radius_y ? $output_height - $new_height - $radius_y : 0); + + if ($gd_border_canvas = phpthumb_functions::ImageCreateFunction($output_width, $output_height)) { + + phpthumb_functions::gd_ImageSaveAlpha($gd_border_canvas, true); + ImageAlphaBlending($gd_border_canvas, false); + $color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gd_border_canvas, 255, 255, 255, 127); + ImageFilledRectangle($gd_border_canvas, 0, 0, $output_width, $output_height, $color_background); + + $color_border = phpthumb_functions::ImageHexColorAllocate($gd_border_canvas, (phpthumb_functions::IsHexColor($hexcolor_border) ? $hexcolor_border : '000000')); + + for ($i = 0; $i < $border_width; $i++) { + ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $i, $output_width - $radius_x - ceil($offset_x / 2), $i, $color_border); // top + ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $output_height - 1 - $i, $output_width - $radius_x - ceil($offset_x / 2), $output_height - 1 - $i, $color_border); // bottom + ImageLine($gd_border_canvas, floor($offset_x / 2) + $i, $radius_y, floor($offset_x / 2) + $i, $output_height - $radius_y, $color_border); // left + ImageLine($gd_border_canvas, $output_width - 1 - $i - ceil($offset_x / 2), $radius_y, $output_width - 1 - $i - ceil($offset_x / 2), $output_height - $radius_y, $color_border); // right + } + + if ($radius_x && $radius_y) { + + // PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results + // Solution: Draw multiple 1px arcs side-by-side. + + // Problem: parallel arcs give strange/ugly antialiasing problems + // Solution: draw non-parallel arcs, from one side of the line thickness at the start angle + // to the opposite edge of the line thickness at the terminating angle + for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { + ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left + ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right + ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right + ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left + } + if ($border_width > 1) { + for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { + ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left + ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right + ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right + ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left + } + } + + } + $this->phpThumbObject->ImageResizeFunction($gd_border_canvas, $gdimg, floor(($output_width - $new_width) / 2), round(($output_height - $new_height) / 2), 0, 0, $new_width, $new_height, $output_width, $output_height); + + ImageDestroy($gdimg); + $gdimg = phpthumb_functions::ImageCreateFunction($output_width, $output_height); + phpthumb_functions::gd_ImageSaveAlpha($gdimg, true); + ImageAlphaBlending($gdimg, false); + $gdimg_color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 255, 255, 255, 127); + ImageFilledRectangle($gdimg, 0, 0, $output_width, $output_height, $gdimg_color_background); + + ImageCopy($gdimg, $gd_border_canvas, 0, 0, 0, 0, $output_width, $output_height); + //$gdimg = $gd_border_canvas; + ImageDestroy($gd_border_canvas); + return true; + + + } else { + $this->DebugMessage('FAILED: $gd_border_canvas = phpthumb_functions::ImageCreateFunction('.$output_width.', '.$output_height.')', __FILE__, __LINE__); + } + return false; + } + + + function MeanRemoval(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::MeanRemoval($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Negative(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_NEGATE)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_NEGATE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, (~$currentPixel['red'] & 0xFF), (~$currentPixel['green'] & 0xFF), (~$currentPixel['blue'] & 0xFF), $currentPixel['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function RoundedImageCorners(&$gdimg, $radius_x, $radius_y) { + // generate mask at twice desired resolution and downsample afterwards for easy antialiasing + // mask is generated as a white double-size elipse on a triple-size black background and copy-paste-resampled + // onto a correct-size mask image as 4 corners due to errors when the entire mask is resampled at once (gray edges) + if ($gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction($radius_x * 6, $radius_y * 6)) { + if ($gdimg_cornermask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + + $color_transparent = ImageColorAllocate($gdimg_cornermask_triple, 255, 255, 255); + ImageFilledEllipse($gdimg_cornermask_triple, $radius_x * 3, $radius_y * 3, $radius_x * 4, $radius_y * 4, $color_transparent); + + ImageFilledRectangle($gdimg_cornermask, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $color_transparent); + + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, 0, $radius_x, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, ImageSY($gdimg) - $radius_y, $radius_x, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, ImageSY($gdimg) - $radius_y, $radius_x * 3, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, 0, $radius_x * 3, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + + phpthumb_filters::ApplyMask($gdimg_cornermask, $gdimg); + ImageDestroy($gdimg_cornermask); + $this->DebugMessage('RoundedImageCorners('.$radius_x.', '.$radius_y.') succeeded', __FILE__, __LINE__); + return true; + + } else { + $this->DebugMessage('FAILED: $gdimg_cornermask = phpthumb_functions::ImageCreateFunction('.ImageSX($gdimg).', '.ImageSY($gdimg).')', __FILE__, __LINE__); + } + ImageDestroy($gdimg_cornermask_triple); + + } else { + $this->DebugMessage('FAILED: $gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction('.($radius_x * 6).', '.($radius_y * 6).')', __FILE__, __LINE__); + } + return false; + } + + + function Saturation(&$gdimg, $amount, $color='') { + if ($amount == 0) { + return true; + } elseif ($amount > 0) { + $amount = 0 - $amount; + } else { + $amount = abs($amount); + } + return phpthumb_filters::Desaturate($gdimg, $amount, $color); + } + + + function Sepia(&$gdimg, $amount, $targetColor) { + $amount = (is_numeric($amount) ? max(0, min(100, $amount)) : 50); + $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'A28065'); + + if ($amount == 0) { + return true; + } + + $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); + $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); + $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); + + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + + // http://www.gimpguru.org/Tutorials/SepiaToning/ + // "In the traditional sepia toning process, the tinting occurs most in + // the mid-tones: the lighter and darker areas appear to be closer to B&W." + $SepiaAmount = ((128 - abs($GrayPixel['red'] - 128)) / 128) * ($amount / 100); + + foreach ($TargetPixel as $key => $value) { + $NewPixel[$key] = round(max(0, min(255, $GrayPixel[$key] * (1 - $SepiaAmount) + ($TargetPixel[$key] * $SepiaAmount)))); + } + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Smooth(&$gdimg, $amount=6) { + $amount = min(25, max(0, $amount)); + if ($amount == 0) { + return true; + } + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_SMOOTH, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SMOOTH, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, '.$amount.') [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Threshold(&$gdimg, $cutoff) { + $cutoff = min(255, max(0, ($cutoff ? $cutoff : 128))); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $grayPixel = phpthumb_functions::GrayscalePixel($currentPixel); + if ($grayPixel['red'] < $cutoff) { + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0x00, 0x00, 0x00, $currentPixel['alpha']); + } else { + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0xFF, 0xFF, 0xFF, $currentPixel['alpha']); + } + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function ImageTrueColorToPalette2(&$image, $dither, $ncolors) { + // http://www.php.net/manual/en/function.imagetruecolortopalette.php + // zmorris at zsculpt dot com (17-Aug-2004 06:58) + $width = ImageSX($image); + $height = ImageSY($image); + $image_copy = ImageCreateTrueColor($width, $height); + //ImageCopyMerge($image_copy, $image, 0, 0, 0, 0, $width, $height, 100); + ImageCopy($image_copy, $image, 0, 0, 0, 0, $width, $height); + ImageTrueColorToPalette($image, $dither, $ncolors); + ImageColorMatch($image_copy, $image); + ImageDestroy($image_copy); + return true; + } + + function ReduceColorDepth(&$gdimg, $colors=256, $dither=true) { + $colors = max(min($colors, 256), 2); + // ImageTrueColorToPalette usually makes ugly colors, the replacement is a bit better + //ImageTrueColorToPalette($gdimg, $dither, $colors); + phpthumb_filters::ImageTrueColorToPalette2($gdimg, $dither, $colors); + return true; + } + + + function WhiteBalance(&$gdimg, $targetColor='') { + if (phpthumb_functions::IsHexColor($targetColor)) { + $targetPixel = array( + 'red' => hexdec(substr($targetColor, 0, 2)), + 'green' => hexdec(substr($targetColor, 2, 2)), + 'blue' => hexdec(substr($targetColor, 4, 2)) + ); + } else { + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, false); + $targetPixel = array( + 'red' => max(array_keys($Analysis['red'])), + 'green' => max(array_keys($Analysis['green'])), + 'blue' => max(array_keys($Analysis['blue'])) + ); + } + $grayValue = phpthumb_functions::GrayscaleValue($targetPixel['red'], $targetPixel['green'], $targetPixel['blue']); + $scaleR = $grayValue / $targetPixel['red']; + $scaleG = $grayValue / $targetPixel['green']; + $scaleB = $grayValue / $targetPixel['blue']; + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe( + $gdimg, + max(0, min(255, round($currentPixel['red'] * $scaleR))), + max(0, min(255, round($currentPixel['green'] * $scaleG))), + max(0, min(255, round($currentPixel['blue'] * $scaleB))), + $currentPixel['alpha'] + ); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function WatermarkText(&$gdimg, $text, $size, $alignment, $hex_color='000000', $ttffont='', $opacity=100, $margin=5, $angle=0, $bg_color=false, $bg_opacity=0, $fillextend='') { + // text watermark requested + if (!$text) { + return false; + } + ImageAlphaBlending($gdimg, true); + + $metaTextArray = array( + '^Fb' => $this->phpThumbObject->getimagesizeinfo['filesize'], + '^Fk' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1024), + '^Fm' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1048576), + '^X' => $this->phpThumbObject->getimagesizeinfo[0], + '^Y' => $this->phpThumbObject->getimagesizeinfo[1], + '^x' => ImageSX($gdimg), + '^y' => ImageSY($gdimg), + '^^' => '^', + ); + $text = strtr($text, $metaTextArray); + + $text = str_replace("\r\n", "\n", $text); + $text = str_replace("\r", "\n", $text); + $textlines = explode("\n", $text); + + if (@is_readable($ttffont) && is_file($ttffont)) { + + $opacity = 100 - intval(max(min($opacity, 100), 0)); + + $this->DebugMessage('Using TTF font "'.$ttffont.'"', __FILE__, __LINE__); + + $TTFbox = ImageTTFbBox($size, $angle, $ttffont, $text); + + $min_x = min($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); + $max_x = max($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); + //$text_width = round($max_x - $min_x + ($size * 0.5)); + $text_width = round($max_x - $min_x); + + $min_y = min($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); + $max_y = max($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); + //$text_height = round($max_y - $min_y + ($size * 0.5)); + $text_height = round($max_y - $min_y); + + $TTFboxChar = ImageTTFbBox($size, $angle, $ttffont, 'jH'); + $char_min_y = min($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); + $char_max_y = max($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); + $char_height = round($char_max_y - $char_min_y); + + switch ($alignment) { + case 'T': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = $char_height + $margin; + break; + + case 'B': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + + case 'L': + $text_origin_x = $margin; + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'R': + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'C': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'TL': + $text_origin_x = $margin; + $text_origin_y = $char_height + $margin; + break; + + case 'TR': + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = $char_height + $margin; + break; + + case 'BL': + $text_origin_x = $margin; + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + + case 'BR': + default: + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + } + $letter_color_text = phpthumb_functions::ImageHexColorAllocate($gdimg, $hex_color, false, $opacity * 1.27); + + if ($alignment == '*') { + + $text_origin_y = $char_height + $margin; + while (($text_origin_y - $text_height) < ImageSY($gdimg)) { + $text_origin_x = $margin; + while ($text_origin_x < ImageSX($gdimg)) { + ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); + $text_origin_x += ($text_width + $margin); + } + $text_origin_y += ($text_height + $margin); + } + + } else { + + //ImageRectangle($gdimg, $text_origin_x + $min_x, $text_origin_y + $TTFbox[1], $text_origin_x + $min_x + $text_width, $text_origin_y + $TTFbox[1] - $text_height, $letter_color_text); + if (phpthumb_functions::IsHexColor($bg_color)) { + $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); + $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, $bg_color, false, $text_background_alpha); + } else { + $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, 'FFFFFF', false, 127); + } + $x1 = $text_origin_x + $min_x; + $y1 = $text_origin_y + $TTFbox[1]; + $x2 = $text_origin_x + $min_x + $text_width; + $y2 = $text_origin_y + $TTFbox[1] - $text_height; + $x_TL = eregi('x', $fillextend) ? 0 : min($x1, $x2); + $y_TL = eregi('y', $fillextend) ? 0 : min($y1, $y2); + $x_BR = eregi('x', $fillextend) ? ImageSX($gdimg) : max($x1, $x2); + $y_BR = eregi('y', $fillextend) ? ImageSY($gdimg) : max($y1, $y2); + //while ($y_BR > ImageSY($gdimg)) { + // $y_TL--; + // $y_BR--; + // $text_origin_y--; + //} + ImageFilledRectangle($gdimg, $x_TL, $y_TL, $x_BR, $y_BR, $text_color_background); + ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); + + } + return true; + + } else { + + $size = min(5, max(1, $size)); + $this->DebugMessage('Using built-in font (size='.$size.') for text watermark'.($ttffont ? ' because $ttffont !is_readable('.$ttffont.')' : ''), __FILE__, __LINE__); + + $text_width = 0; + $text_height = 0; + foreach ($textlines as $dummy => $line) { + $text_width = max($text_width, ImageFontWidth($size) * strlen($line)); + $text_height += ImageFontHeight($size); + } + if ($img_watermark = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { + ImageAlphaBlending($img_watermark, false); + if (phpthumb_functions::IsHexColor($bg_color)) { + $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); + $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, $bg_color, false, $text_background_alpha); + } else { + $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, 'FFFFFF', false, 127); + } + ImageFilledRectangle($img_watermark, 0, 0, ImageSX($img_watermark), ImageSY($img_watermark), $text_color_background); + + if ($angle && function_exists('ImageRotate')) { + // using $img_watermark_mask is pointless if ImageRotate function isn't available + if ($img_watermark_mask = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { + $mask_color_background = ImageColorAllocate($img_watermark_mask, 0, 0, 0); + ImageAlphaBlending($img_watermark_mask, false); + ImageFilledRectangle($img_watermark_mask, 0, 0, ImageSX($img_watermark_mask), ImageSY($img_watermark_mask), $mask_color_background); + $mask_color_watermark = ImageColorAllocate($img_watermark_mask, 255, 255, 255); + } + } + + $text_color_watermark = phpthumb_functions::ImageHexColorAllocate($img_watermark, $hex_color); + foreach ($textlines as $key => $line) { + switch ($alignment) { + case 'C': + case 'T': + case 'B': + $x_offset = round(($text_width - (ImageFontWidth($size) * strlen($line))) / 2); + break; + + case 'L': + case 'TL': + case 'BL': + $x_offset = 0; + break; + + case 'R': + case 'TR': + case 'BR': + default: + $x_offset = $text_width - (ImageFontWidth($size) * strlen($line)); + break; + } + ImageString($img_watermark, $size, $x_offset, $key * ImageFontHeight($size), $line, $text_color_watermark); + if ($angle && $img_watermark_mask) { + ImageString($img_watermark_mask, $size, $x_offset, $key * ImageFontHeight($size), $text, $mask_color_watermark); + } + } + if ($angle && $img_watermark_mask) { + $img_watermark = ImageRotate($img_watermark, $angle, $text_color_background); + $img_watermark_mask = ImageRotate($img_watermark_mask, $angle, $mask_color_background); + phpthumb_filters::ApplyMask($img_watermark_mask, $img_watermark); + } + phpthumb_filters::WatermarkOverlay($gdimg, $img_watermark, $alignment, $opacity, $margin); + ImageDestroy($img_watermark); + return true; + } + + } + return false; + } + + + function WatermarkOverlay(&$gdimg_dest, &$img_watermark, $alignment='*', $opacity=50, $margin=5) { + if (is_resource($gdimg_dest) && is_resource($img_watermark)) { + $watermark_source_x = 0; + $watermark_source_y = 0; + $img_source_width = ImageSX($gdimg_dest); + $img_source_height = ImageSY($gdimg_dest); + $watermark_source_width = ImageSX($img_watermark); + $watermark_source_height = ImageSY($img_watermark); + $watermark_opacity_percent = max(0, min(100, $opacity)); + if ($margin < 1) { + $watermark_margin_percent = 1 - $margin; + } else { + $watermark_margin_percent = (100 - max(0, min(100, $margin))) / 100; + } + $watermark_margin_x = round((1 - $watermark_margin_percent) * $img_source_width); + $watermark_margin_y = round((1 - $watermark_margin_percent) * $img_source_height); + switch ($alignment) { + case '*': + if ($gdimg_tiledwatermark = phpthumb_functions::ImageCreateFunction($img_source_width, $img_source_height)) { + + ImageAlphaBlending($gdimg_tiledwatermark, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_tiledwatermark, true); + $text_color_transparent = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_tiledwatermark, 255, 0, 255, 127); + ImageFill($gdimg_tiledwatermark, 0, 0, $text_color_transparent); + + // set the tiled image transparent color to whatever the untiled image transparency index is +// ImageColorTransparent($gdimg_tiledwatermark, ImageColorTransparent($img_watermark)); + + // a "cleaner" way of doing it, but can't handle the margin feature :( +// ImageSetTile($gdimg_tiledwatermark, $img_watermark); +// ImageFill($gdimg_tiledwatermark, 0, 0, IMG_COLOR_TILED); +// break; + +// ImageFill($gdimg_tiledwatermark, 0, 0, ImageColorTransparent($gdimg_tiledwatermark)); + // tile the image as many times as can fit + for ($x = $watermark_margin_x; $x < ($img_source_width + $watermark_source_width); $x += round($watermark_source_width + ((1 - $watermark_margin_percent) * $img_source_width))) { + for ($y = $watermark_margin_y; $y < ($img_source_height + $watermark_source_height); $y += round($watermark_source_height + ((1 - $watermark_margin_percent) * $img_source_height))) { + ImageCopy( + $gdimg_tiledwatermark, + $img_watermark, + $x, + $y, + 0, + 0, + min($watermark_source_width, $img_source_width - $x - ((1 - $watermark_margin_percent) * $img_source_width)), + min($watermark_source_height, $img_source_height - $y - ((1 - $watermark_margin_percent) * $img_source_height)) + ); + } + } + + $watermark_source_width = ImageSX($gdimg_tiledwatermark); + $watermark_source_height = ImageSY($gdimg_tiledwatermark); + $watermark_destination_x = 0; + $watermark_destination_y = 0; + + ImageDestroy($img_watermark); + $img_watermark = $gdimg_tiledwatermark; + } + break; + + case 'T': + $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); + $watermark_destination_y = $watermark_margin_y; + break; + + case 'B': + $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + + case 'L': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); + break; + + case 'R': + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); + break; + + case 'C': + $watermark_destination_x = round(($img_source_width / 2) - ($watermark_source_width / 2)); + $watermark_destination_y = round(($img_source_height / 2) - ($watermark_source_height / 2)); + break; + + case 'TL': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = $watermark_margin_y; + break; + + case 'TR': + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = $watermark_margin_y; + break; + + case 'BL': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + + case 'BR': + default: + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + } + ImageAlphaBlending($gdimg_dest, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_dest, true); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark, true); + phpthumb_functions::ImageCopyRespectAlpha($gdimg_dest, $img_watermark, $watermark_destination_x, $watermark_destination_y, 0, 0, $watermark_source_width, $watermark_source_height, $watermark_opacity_percent); + + return true; + } + return false; + } + + + function DebugMessage($message, $file='', $line='') { + if (is_object($this->phpThumbObject)) { + return $this->phpThumbObject->DebugMessage($message, $file, $line); + } + return false; + } +} + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/phpthumb.functions.php b/site/retailers/phpthumb/phpthumb.functions.php new file mode 100644 index 0000000..9e29609 --- /dev/null +++ b/site/retailers/phpthumb/phpthumb.functions.php @@ -0,0 +1,707 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.functions.php - general support functions // +// /// +////////////////////////////////////////////////////////////// + +class phpthumb_functions { + + function user_function_exists($functionname) { + if (function_exists('get_defined_functions')) { + static $get_defined_functions = array(); + if (empty($get_defined_functions)) { + $get_defined_functions = get_defined_functions(); + } + return in_array(strtolower($functionname), $get_defined_functions['user']); + } + return function_exists($functionname); + } + + + function builtin_function_exists($functionname) { + if (function_exists('get_defined_functions')) { + static $get_defined_functions = array(); + if (empty($get_defined_functions)) { + $get_defined_functions = get_defined_functions(); + } + return in_array(strtolower($functionname), $get_defined_functions['internal']); + } + return function_exists($functionname); + } + + + function version_compare_replacement_sub($version1, $version2, $operator='') { + // If you specify the third optional operator argument, you can test for a particular relationship. + // The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively. + // Using this argument, the function will return 1 if the relationship is the one specified by the operator, 0 otherwise. + + // If a part contains special version strings these are handled in the following order: dev < (alpha = a) < (beta = b) < RC < pl + static $versiontype_lookup = array(); + if (empty($versiontype_lookup)) { + $versiontype_lookup['dev'] = 10001; + $versiontype_lookup['a'] = 10002; + $versiontype_lookup['alpha'] = 10002; + $versiontype_lookup['b'] = 10003; + $versiontype_lookup['beta'] = 10003; + $versiontype_lookup['RC'] = 10004; + $versiontype_lookup['pl'] = 10005; + } + if (isset($versiontype_lookup[$version1])) { + $version1 = $versiontype_lookup[$version1]; + } + if (isset($versiontype_lookup[$version2])) { + $version2 = $versiontype_lookup[$version2]; + } + + switch ($operator) { + case '<': + case 'lt': + return intval($version1 < $version2); + break; + case '<=': + case 'le': + return intval($version1 <= $version2); + break; + case '>': + case 'gt': + return intval($version1 > $version2); + break; + case '>=': + case 'ge': + return intval($version1 >= $version2); + break; + case '==': + case '=': + case 'eq': + return intval($version1 == $version2); + break; + case '!=': + case '<>': + case 'ne': + return intval($version1 != $version2); + break; + } + if ($version1 == $version2) { + return 0; + } elseif ($version1 < $version2) { + return -1; + } + return 1; + } + + + function version_compare_replacement($version1, $version2, $operator='') { + if (function_exists('version_compare')) { + // built into PHP v4.1.0+ + return version_compare($version1, $version2, $operator); + } + + // The function first replaces _, - and + with a dot . in the version strings + $version1 = strtr($version1, '_-+', '...'); + $version2 = strtr($version2, '_-+', '...'); + + // and also inserts dots . before and after any non number so that for example '4.3.2RC1' becomes '4.3.2.RC.1'. + // Then it splits the results like if you were using explode('.',$ver). Then it compares the parts starting from left to right. + $version1 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version1); + $version2 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version2); + + $parts1 = explode('.', $version1); + $parts2 = explode('.', $version1); + $parts_count = max(count($parts1), count($parts2)); + for ($i = 0; $i < $parts_count; $i++) { + $comparison = phpthumb_functions::version_compare_replacement_sub($version1, $version2, $operator); + if ($comparison != 0) { + return $comparison; + } + } + return 0; + } + + + function phpinfo_array() { + static $phpinfo_array = array(); + if (empty($phpinfo_array)) { + ob_start(); + phpinfo(); + $phpinfo = ob_get_contents(); + ob_end_clean(); + $phpinfo_array = explode("\n", $phpinfo); + } + return $phpinfo_array; + } + + + function exif_info() { + static $exif_info = array(); + if (empty($exif_info)) { + // based on code by johnschaefer at gmx dot de + // from PHP help on gd_info() + $exif_info = array( + 'EXIF Support' => '', + 'EXIF Version' => '', + 'Supported EXIF Version' => '', + 'Supported filetypes' => '' + ); + $phpinfo_array = phpthumb_functions::phpinfo_array(); + foreach ($phpinfo_array as $dummy => $line) { + $line = trim(strip_tags($line)); + foreach ($exif_info as $key => $value) { + if (strpos($line, $key) === 0) { + $newvalue = trim(str_replace($key, '', $line)); + $exif_info[$key] = $newvalue; + } + } + } + } + return $exif_info; + } + + + function ImageTypeToMIMEtype($imagetype) { + if (function_exists('image_type_to_mime_type') && ($imagetype >= 1) && ($imagetype <= 16)) { + // PHP v4.3.0+ + return image_type_to_mime_type($imagetype); + } + static $image_type_to_mime_type = array( + 1 => 'image/gif', // IMAGETYPE_GIF + 2 => 'image/jpeg', // IMAGETYPE_JPEG + 3 => 'image/png', // IMAGETYPE_PNG + 4 => 'application/x-shockwave-flash', // IMAGETYPE_SWF + 5 => 'image/psd', // IMAGETYPE_PSD + 6 => 'image/bmp', // IMAGETYPE_BMP + 7 => 'image/tiff', // IMAGETYPE_TIFF_II (intel byte order) + 8 => 'image/tiff', // IMAGETYPE_TIFF_MM (motorola byte order) + 9 => 'application/octet-stream', // IMAGETYPE_JPC + 10 => 'image/jp2', // IMAGETYPE_JP2 + 11 => 'application/octet-stream', // IMAGETYPE_JPX + 12 => 'application/octet-stream', // IMAGETYPE_JB2 + 13 => 'application/x-shockwave-flash', // IMAGETYPE_SWC + 14 => 'image/iff', // IMAGETYPE_IFF + 15 => 'image/vnd.wap.wbmp', // IMAGETYPE_WBMP + 16 => 'image/xbm', // IMAGETYPE_XBM + + 'gif' => 'image/gif', // IMAGETYPE_GIF + 'jpg' => 'image/jpeg', // IMAGETYPE_JPEG + 'jpeg' => 'image/jpeg', // IMAGETYPE_JPEG + 'png' => 'image/png', // IMAGETYPE_PNG + 'bmp' => 'image/bmp', // IMAGETYPE_BMP + 'ico' => 'image/x-icon', + ); + + return (isset($image_type_to_mime_type[$imagetype]) ? $image_type_to_mime_type[$imagetype] : false); + } + + + function HexCharDisplay($string) { + $len = strlen($string); + $output = ''; + for ($i = 0; $i < $len; $i++) { + $output .= ' 0x'.str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT); + } + return $output; + } + + + function IsHexColor($HexColorString) { + return eregi('^[0-9A-F]{6}$', $HexColorString); + } + + + function ImageColorAllocateAlphaSafe(&$gdimg_hexcolorallocate, $R, $G, $B, $alpha=false) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && ($alpha !== false)) { + return ImageColorAllocateAlpha($gdimg_hexcolorallocate, $R, $G, $B, intval($alpha)); + } else { + return ImageColorAllocate($gdimg_hexcolorallocate, $R, $G, $B); + } + } + + function ImageHexColorAllocate(&$gdimg_hexcolorallocate, $HexColorString, $dieOnInvalid=false, $alpha=false) { + if (!is_resource($gdimg_hexcolorallocate)) { + die('$gdimg_hexcolorallocate is not a GD resource in ImageHexColorAllocate()'); + } + if (phpthumb_functions::IsHexColor($HexColorString)) { + $R = hexdec(substr($HexColorString, 0, 2)); + $G = hexdec(substr($HexColorString, 2, 2)); + $B = hexdec(substr($HexColorString, 4, 2)); + return phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_hexcolorallocate, $R, $G, $B, $alpha); + } + if ($dieOnInvalid) { + die('Invalid hex color string: "'.$HexColorString.'"'); + } + return ImageColorAllocate($gdimg_hexcolorallocate, 0x00, 0x00, 0x00); + } + + + function HexColorXOR($hexcolor) { + return strtoupper(str_pad(dechex(~hexdec($hexcolor) & 0xFFFFFF), 6, '0', STR_PAD_LEFT)); + } + + + function GetPixelColor(&$img, $x, $y) { + if (!is_resource($img)) { + return false; + } + return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y)); + } + + + function GrayscaleValue($r, $g, $b) { + return round(($r * 0.30) + ($g * 0.59) + ($b * 0.11)); + } + + + function GrayscalePixel($OriginalPixel) { + $gray = phpthumb_functions::GrayscaleValue($OriginalPixel['red'], $OriginalPixel['green'], $OriginalPixel['blue']); + return array('red'=>$gray, 'green'=>$gray, 'blue'=>$gray); + } + + + function GrayscalePixelRGB($rgb) { + $r = ($rgb >> 16) & 0xFF; + $g = ($rgb >> 8) & 0xFF; + $b = $rgb & 0xFF; + return ($r * 0.299) + ($g * 0.587) + ($b * 0.114); + } + + + function ImageCopyResampleBicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) { + // ron at korving dot demon dot nl + // http://www.php.net/imagecopyresampled + + $scaleX = ($src_w - 1) / $dst_w; + $scaleY = ($src_h - 1) / $dst_h; + + $scaleX2 = $scaleX / 2.0; + $scaleY2 = $scaleY / 2.0; + + $isTrueColor = ImageIsTrueColor($src_img); + + for ($y = $src_y; $y < $src_y + $dst_h; $y++) { + $sY = $y * $scaleY; + $siY = (int) $sY; + $siY2 = (int) $sY + $scaleY2; + + for ($x = $src_x; $x < $src_x + $dst_w; $x++) { + $sX = $x * $scaleX; + $siX = (int) $sX; + $siX2 = (int) $sX + $scaleX2; + + if ($isTrueColor) { + + $c1 = ImageColorAt($src_img, $siX, $siY2); + $c2 = ImageColorAt($src_img, $siX, $siY); + $c3 = ImageColorAt($src_img, $siX2, $siY2); + $c4 = ImageColorAt($src_img, $siX2, $siY); + + $r = (( $c1 + $c2 + $c3 + $c4 ) >> 2) & 0xFF0000; + $g = ((($c1 & 0x00FF00) + ($c2 & 0x00FF00) + ($c3 & 0x00FF00) + ($c4 & 0x00FF00)) >> 2) & 0x00FF00; + $b = ((($c1 & 0x0000FF) + ($c2 & 0x0000FF) + ($c3 & 0x0000FF) + ($c4 & 0x0000FF)) >> 2); + + } else { + + $c1 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY2)); + $c2 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY)); + $c3 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY2)); + $c4 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY)); + + $r = ($c1['red'] + $c2['red'] + $c3['red'] + $c4['red'] ) << 14; + $g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6; + $b = ($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue'] ) >> 2; + + } + ImageSetPixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r+$g+$b); + } + } + return true; + } + + + function ImageCreateFunction($x_size, $y_size) { + $ImageCreateFunction = 'ImageCreate'; + if (phpthumb_functions::gd_version() >= 2.0) { + $ImageCreateFunction = 'ImageCreateTrueColor'; + } + if (!function_exists($ImageCreateFunction)) { + return phpthumb::ErrorImage($ImageCreateFunction.'() does not exist - no GD support?'); + } + if (($x_size <= 0) || ($y_size <= 0)) { + return phpthumb::ErrorImage('Invalid image dimensions: '.$ImageCreateFunction.'('.$x_size.', '.$y_size.')'); + } + return $ImageCreateFunction($x_size, $y_size); + } + + + function ImageCopyRespectAlpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct=100) { + for ($x = $src_x; $x < $src_w; $x++) { + for ($y = $src_y; $y < $src_h; $y++) { + $RealPixel = phpthumb_functions::GetPixelColor($dst_im, $dst_x + $x, $dst_y + $y); + $OverlayPixel = phpthumb_functions::GetPixelColor($src_im, $x, $y); + $alphapct = $OverlayPixel['alpha'] / 127; + $opacipct = $pct / 100; + $overlaypct = (1 - $alphapct) * $opacipct; + + $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe( + $dst_im, + round($RealPixel['red'] * (1 - $overlaypct)) + ($OverlayPixel['red'] * $overlaypct), + round($RealPixel['green'] * (1 - $overlaypct)) + ($OverlayPixel['green'] * $overlaypct), + round($RealPixel['blue'] * (1 - $overlaypct)) + ($OverlayPixel['blue'] * $overlaypct), + //$RealPixel['alpha']); + 0); + + ImageSetPixel($dst_im, $dst_x + $x, $dst_y + $y, $newcolor); + } + } + return true; + } + + + function ProportionalResize($old_width, $old_height, $new_width=false, $new_height=false) { + $old_aspect_ratio = $old_width / $old_height; + if (($new_width === false) && ($new_height === false)) { + return false; + } elseif ($new_width === false) { + $new_width = $new_height * $old_aspect_ratio; + } elseif ($new_height === false) { + $new_height = $new_width / $old_aspect_ratio; + } + $new_aspect_ratio = $new_width / $new_height; + if ($new_aspect_ratio == $old_aspect_ratio) { + // great, done + } elseif ($new_aspect_ratio < $old_aspect_ratio) { + // limited by width + $new_height = $new_width / $old_aspect_ratio; + } elseif ($new_aspect_ratio > $old_aspect_ratio) { + // limited by height + $new_width = $new_height * $old_aspect_ratio; + } + return array(round($new_width), round($new_height)); + } + + + function SafeExec($command) { + static $AllowedExecFunctions = array(); + if (empty($AllowedExecFunctions)) { + $AllowedExecFunctions = array('shell_exec'=>true, 'passthru'=>true, 'system'=>true, 'exec'=>true); + if (@ini_get('safe_mode')) { + $AllowedExecFunctions['shell_exec'] = false; + } + $disable_functions = explode(',', @ini_get('disable_functions')); + foreach ($AllowedExecFunctions as $key => $value) { + if (in_array($key, $disable_functions)) { + $AllowedExecFunctions[$key] = false; + } + } + } + foreach ($AllowedExecFunctions as $execfunction => $is_allowed) { + if (!$is_allowed) { + continue; + } + if ($execfunction == 'passthru') { + ob_start(); + $execfunction($command); + $returnvalue = ob_get_contents(); + ob_end_clean(); + } else { + $returnvalue = @$execfunction($command); + } + return $returnvalue; + } + return false; + } + + + function ApacheLookupURIarray($filename) { + // apache_lookup_uri() only works when PHP is installed as an Apache module. + if (php_sapi_name() == 'apache') { + $keys = array('status', 'the_request', 'status_line', 'method', 'content_type', 'handler', 'uri', 'filename', 'path_info', 'args', 'boundary', 'no_cache', 'no_local_copy', 'allowed', 'send_bodyct', 'bytes_sent', 'byterange', 'clength', 'unparsed_uri', 'mtime', 'request_time'); + if ($apacheLookupURIobject = @apache_lookup_uri($filename)) { + $apacheLookupURIarray = array(); + foreach ($keys as $dummy => $key) { + $apacheLookupURIarray[$key] = @$apacheLookupURIobject->$key; + } + return $apacheLookupURIarray; + } + } + return false; + } + + + function gd_is_bundled() { + static $isbundled = null; + if (is_null($isbundled)) { + $gd_info = gd_info(); + $isbundled = (strpos($gd_info['GD Version'], 'bundled') !== false); + } + return $isbundled; + } + + + function gd_version($fullstring=false) { + static $cache_gd_version = array(); + if (empty($cache_gd_version)) { + $gd_info = gd_info(); + if (eregi('bundled \((.+)\)$', $gd_info['GD Version'], $matches)) { + $cache_gd_version[1] = $gd_info['GD Version']; // e.g. "bundled (2.0.15 compatible)" + $cache_gd_version[0] = (float) $matches[1]; // e.g. "2.0" (not "bundled (2.0.15 compatible)") + } else { + $cache_gd_version[1] = $gd_info['GD Version']; // e.g. "1.6.2 or higher" + $cache_gd_version[0] = (float) substr($gd_info['GD Version'], 0, 3); // e.g. "1.6" (not "1.6.2 or higher") + } + } + return $cache_gd_version[intval($fullstring)]; + } + + + function gd_ImageSaveAlpha(&$img, $flag) { + // requires PHP >= 4.3.2 + // requires GD >= 2.0.1 + if (function_exists('ImageSaveAlpha')) { + return ImageSaveAlpha($img, $flag); + } + return false; + } + + function filesize_remote($remotefile, $timeout=10) { + $size = false; + $url = parse_url($remotefile); + if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) { + fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n"); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + stream_set_timeout($fp, $timeout); + } + while (!feof($fp)) { + $headerline = fgets($fp, 4096); + if (eregi('^Content-Length: (.*)', $headerline, $matches)) { + $size = intval($matches[1]); + break; + } + } + fclose ($fp); + } + return $size; + } + + + function filedate_remote($remotefile, $timeout=10) { + $date = false; + $url = parse_url($remotefile); + if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) { + fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n"); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + stream_set_timeout($fp, $timeout); + } + while (!feof($fp)) { + $headerline = fgets($fp, 4096); + if (eregi('^Last-Modified: (.*)', $headerline, $matches)) { + $date = strtotime($matches[1]) - date('Z'); + break; + } + } + fclose ($fp); + } + return $date; + } + + + function md5_file_safe($filename) { + // md5_file() doesn't exist in PHP < 4.2.0 + if (function_exists('md5_file')) { + return md5_file($filename); + } + if ($fp = @fopen($filename, 'rb')) { + $filedata = fread($fp, filesize($filename)); + fclose($fp); + return md5($filedata); + } + return false; + } + + + function nonempty_min() { + $arg_list = func_get_args(); + $acceptable = array(); + foreach ($arg_list as $dummy => $arg) { + if ($arg) { + $acceptable[] = $arg; + } + } + return min($acceptable); + } + + + function LittleEndian2String($number, $minbytes=1) { + $intstring = ''; + while ($number > 0) { + $intstring = $intstring.chr($number & 255); + $number >>= 8; + } + return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT); + } + + function OneOfThese() { + // return the first useful (non-empty/non-zero/non-false) value from those passed + $arg_list = func_get_args(); + foreach ($arg_list as $key => $value) { + if ($value) { + return $value; + } + } + return false; + } + + function SafeURLread($url, &$error) { + if (function_exists('curl_version')) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); + $rawData = curl_exec($ch); + curl_close($ch); + if (strlen($rawData) > 0) { + return $rawData; + } + $error .= 'CURL available but returned no data; '; + } else { + $error .= 'CURL unavailable; '; + } + if (@ini_get('allow_url_fopen')) { + $rawData = ''; + ob_start(); + if ($fp = fopen($url, 'rb')) { + do { + $buffer = fread($fp, 8192); + $rawData .= $buffer; + } while (strlen($buffer) > 0); + fclose($fp); + } else { + $error = trim(strip_tags(ob_get_contents())); + } + ob_end_clean(); + if (!$error) { + return $rawData; + } + $error .= '; "allow_url_fopen" enabled but returned no data; '; + } else { + $error .= '"allow_url_fopen" disabled; '; + } + return false; + } + +} + + +if (!function_exists('gd_info')) { + // built into PHP v4.3.0+ (with bundled GD2 library) + function gd_info() { + static $gd_info = array(); + if (empty($gd_info)) { + // based on code by johnschaefer at gmx dot de + // from PHP help on gd_info() + $gd_info = array( + 'GD Version' => '', + 'FreeType Support' => false, + 'FreeType Linkage' => '', + 'T1Lib Support' => false, + 'GIF Read Support' => false, + 'GIF Create Support' => false, + 'JPG Support' => false, + 'PNG Support' => false, + 'WBMP Support' => false, + 'XBM Support' => false + ); + $phpinfo_array = phpthumb_functions::phpinfo_array(); + foreach ($phpinfo_array as $dummy => $line) { + $line = trim(strip_tags($line)); + foreach ($gd_info as $key => $value) { + //if (strpos($line, $key) !== false) { + if (strpos($line, $key) === 0) { + $newvalue = trim(str_replace($key, '', $line)); + $gd_info[$key] = $newvalue; + } + } + } + if (empty($gd_info['GD Version'])) { + // probable cause: "phpinfo() disabled for security reasons" + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_PNG) { + $gd_info['PNG Support'] = true; + } + if ($imagetypes & IMG_GIF) { + $gd_info['GIF Create Support'] = true; + } + if ($imagetypes & IMG_JPG) { + $gd_info['JPG Support'] = true; + } + if ($imagetypes & IMG_WBMP) { + $gd_info['WBMP Support'] = true; + } + } + // to determine capability of GIF creation, try to use ImageCreateFromGIF on a 1px GIF + if (function_exists('ImageCreateFromGIF')) { + if ($tempfilename = phpthumb::phpThumb_tempnam()) { + if ($fp_tempfile = @fopen($tempfilename, 'wb')) { + fwrite($fp_tempfile, base64_decode('R0lGODlhAQABAIAAAH//AP///ywAAAAAAQABAAACAUQAOw==')); // very simple 1px GIF file base64-encoded as string + fclose($fp_tempfile); + + // if we can convert the GIF file to a GD image then GIF create support must be enabled, otherwise it's not + $gd_info['GIF Read Support'] = (bool) @ImageCreateFromGIF($tempfilename); + } + unlink($tempfilename); + } + } + if (function_exists('ImageCreateTrueColor') && @ImageCreateTrueColor(1, 1)) { + $gd_info['GD Version'] = '2.0.1 or higher (assumed)'; + } elseif (function_exists('ImageCreate') && @ImageCreate(1, 1)) { + $gd_info['GD Version'] = '1.6.0 or higher (assumed)'; + } + } + } + return $gd_info; + } +} + + +if (!function_exists('is_executable')) { + // in PHP v3+, but v5.0+ for Windows + function is_executable($filename) { + // poor substitute, but better than nothing + return file_exists($filename); + } +} + + +if (!function_exists('file_get_contents')) { + // included in PHP v4.3.0+ + function file_get_contents($filename) { + if (eregi('^(f|ht)tp\://', $filename)) { + return SafeURLread($filename); + } + if ($fp = @fopen($filename, 'rb')) { + $buffer = fread($fp, filesize($filename)); + fclose($fp); + return $buffer; + } + return false; + } +} + + +if (!function_exists('file_put_contents')) { + // included in PHP v5.0.0+ + function file_put_contents($filename, $filedata) { + if ($fp = @fopen($filename, 'wb')) { + fwrite($fp, $filedata); + fclose($fp); + return true; + } + return false; + } +} + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/phpthumb.gif.php b/site/retailers/phpthumb/phpthumb.gif.php new file mode 100644 index 0000000..e928594 --- /dev/null +++ b/site/retailers/phpthumb/phpthumb.gif.php @@ -0,0 +1,1168 @@ + = gif_loadFile(filename, [index]) +// = gif_getSize( or filename, &width, &height) +// = gif_outputAsPng(, filename, [bgColor]) +// = gif_outputAsBmp(, filename, [bgcolor]) +// = gif_outputAsJpeg(, filename, [bgcolor]) - use cjpeg if available otherwise uses GD +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Original code by Fabien Ezber +// Modified by James Heinrich for use in phpThumb() - December 10, 2003 +// * Added function gif_loadFileToGDimageResource() - this returns a GD image resource +// * Modified gif_outputAsJpeg() to check if it's running under Windows, or if cjpeg is not +// available, in which case it will attempt to output JPEG using GD functions +// * added @ error-suppression to two lines where it checks: if ($this->m_img->m_bTrans) +// otherwise warnings are generated if error_reporting == E_ALL +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_loadFile($lpszFileName, $iIndex = 0) +{ + $gif = new CGIF(); + if ($gif->loadFile($lpszFileName, $iIndex)) { + return $gif; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// Added by James Heinrich - December 10, 2003 +function gif_loadFileToGDimageResource($gifFilename, $bgColor = -1) +{ + if ($gif = gif_loadFile($gifFilename)) { + + @set_time_limit(300); + // general strategy: convert raw data to PNG then convert PNG data to GD image resource + $PNGdata = $gif->getPng($bgColor); + if ($img = @ImageCreateFromString($PNGdata)) { + + // excellent - PNG image data successfully converted to GD image + return $img; + + } elseif ($img = $gif->getGD_PixelPlotterVersion()) { + + // problem: ImageCreateFromString() didn't like the PNG image data. + // This has been known to happen in PHP v4.0.6 + // solution: take the raw image data and create a new GD image and plot + // pixel-by-pixel on the GD image. This is extremely slow, but it does + // work and a slow solution is better than no solution, right? :) + return $img; + + } + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsBmp($gif, $lpszFileName, $bgColor = -1) +{ + if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) { + return false; + } + + $fd = $gif->getBmp($bgColor); + if (strlen($fd) <= 0) { + return false; + } + + if (!($fh = @fopen($lpszFileName, 'wb'))) { + return false; + } + @fwrite($fh, $fd, strlen($fd)); + @fflush($fh); + @fclose($fh); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsPng($gif, $lpszFileName, $bgColor = -1) +{ + if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) { + return false; + } + + $fd = $gif->getPng($bgColor); + if (strlen($fd) <= 0) { + return false; + } + + if (!($fh = @fopen($lpszFileName, 'wb'))) { + return false; + } + @fwrite($fh, $fd, strlen($fd)); + @fflush($fh); + @fclose($fh); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsJpeg($gif, $lpszFileName, $bgColor = -1) +{ + // JPEG output that does not require cjpeg added by James Heinrich - December 10, 2003 + if ((strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') && (file_exists('/usr/local/bin/cjpeg') || `which cjpeg`)) { + + if (gif_outputAsBmp($gif, $lpszFileName.'.bmp', $bgColor)) { + exec('cjpeg '.$lpszFileName.'.bmp >'.$lpszFileName.' 2>/dev/null'); + @unLink($lpszFileName.'.bmp'); + + if (@file_exists($lpszFileName)) { + if (@fileSize($lpszFileName) > 0) { + return true; + } + + @unLink($lpszFileName); + } + } + + } else { + + // either Windows, or cjpeg not found in path + if ($img = @ImageCreateFromString($gif->getPng($bgColor))) { + if (@ImageJPEG($img, $lpszFileName)) { + return true; + } + } + + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_getSize($gif, &$width, &$height) +{ + if (isSet($gif) && (@get_class($gif) == 'cgif') && $gif->loaded()) { + $width = $gif->width(); + $height = $gif->height(); + } elseif (@file_exists($gif)) { + $myGIF = new CGIF(); + if (!$myGIF->getSize($gif, $width, $height)) { + return false; + } + } else { + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFLZW +{ + var $MAX_LZW_BITS; + var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode; + var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFLZW() + { + $this->MAX_LZW_BITS = 12; + unSet($this->Next); + unSet($this->Vals); + unSet($this->Stack); + unSet($this->Buf); + + $this->Next = range(0, (1 << $this->MAX_LZW_BITS) - 1); + $this->Vals = range(0, (1 << $this->MAX_LZW_BITS) - 1); + $this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1); + $this->Buf = range(0, 279); + } + + /////////////////////////////////////////////////////////////////////////// + + function deCompress($data, &$datLen) + { + $stLen = strlen($data); + $datLen = 0; + $ret = ''; + + // INITIALIZATION + $this->LZWCommand($data, true); + + while (($iIndex = $this->LZWCommand($data, false)) >= 0) { + $ret .= chr($iIndex); + } + + $datLen = $stLen - strlen($data); + + if ($iIndex != -2) { + return false; + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function LZWCommand(&$data, $bInit) + { + if ($bInit) { + $this->SetCodeSize = ord($data{0}); + $data = substr($data, 1); + + $this->CodeSize = $this->SetCodeSize + 1; + $this->ClearCode = 1 << $this->SetCodeSize; + $this->EndCode = $this->ClearCode + 1; + $this->MaxCode = $this->ClearCode + 2; + $this->MaxCodeSize = $this->ClearCode << 1; + + $this->GetCode($data, $bInit); + + $this->Fresh = 1; + for ($i = 0; $i < $this->ClearCode; $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = $i; + } + + for (; $i < (1 << $this->MAX_LZW_BITS); $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = 0; + } + + $this->sp = 0; + return 1; + } + + if ($this->Fresh) { + $this->Fresh = 0; + do { + $this->FirstCode = $this->GetCode($data, $bInit); + $this->OldCode = $this->FirstCode; + } + while ($this->FirstCode == $this->ClearCode); + + return $this->FirstCode; + } + + if ($this->sp > 0) { + $this->sp--; + return $this->Stack[$this->sp]; + } + + while (($Code = $this->GetCode($data, $bInit)) >= 0) { + if ($Code == $this->ClearCode) { + for ($i = 0; $i < $this->ClearCode; $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = $i; + } + + for (; $i < (1 << $this->MAX_LZW_BITS); $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = 0; + } + + $this->CodeSize = $this->SetCodeSize + 1; + $this->MaxCodeSize = $this->ClearCode << 1; + $this->MaxCode = $this->ClearCode + 2; + $this->sp = 0; + $this->FirstCode = $this->GetCode($data, $bInit); + $this->OldCode = $this->FirstCode; + + return $this->FirstCode; + } + + if ($Code == $this->EndCode) { + return -2; + } + + $InCode = $Code; + if ($Code >= $this->MaxCode) { + $this->Stack[$this->sp] = $this->FirstCode; + $this->sp++; + $Code = $this->OldCode; + } + + while ($Code >= $this->ClearCode) { + $this->Stack[$this->sp] = $this->Vals[$Code]; + $this->sp++; + + if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error! + return -1; + + $Code = $this->Next[$Code]; + } + + $this->FirstCode = $this->Vals[$Code]; + $this->Stack[$this->sp] = $this->FirstCode; + $this->sp++; + + if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) { + $this->Next[$Code] = $this->OldCode; + $this->Vals[$Code] = $this->FirstCode; + $this->MaxCode++; + + if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) { + $this->MaxCodeSize *= 2; + $this->CodeSize++; + } + } + + $this->OldCode = $InCode; + if ($this->sp > 0) { + $this->sp--; + return $this->Stack[$this->sp]; + } + } + + return $Code; + } + + /////////////////////////////////////////////////////////////////////////// + + function GetCode(&$data, $bInit) + { + if ($bInit) { + $this->CurBit = 0; + $this->LastBit = 0; + $this->Done = 0; + $this->LastByte = 2; + return 1; + } + + if (($this->CurBit + $this->CodeSize) >= $this->LastBit) { + if ($this->Done) { + if ($this->CurBit >= $this->LastBit) { + // Ran off the end of my bits + return 0; + } + return -1; + } + + $this->Buf[0] = $this->Buf[$this->LastByte - 2]; + $this->Buf[1] = $this->Buf[$this->LastByte - 1]; + + $Count = ord($data{0}); + $data = substr($data, 1); + + if ($Count) { + for ($i = 0; $i < $Count; $i++) { + $this->Buf[2 + $i] = ord($data{$i}); + } + $data = substr($data, $Count); + } else { + $this->Done = 1; + } + + $this->LastByte = 2 + $Count; + $this->CurBit = ($this->CurBit - $this->LastBit) + 16; + $this->LastBit = (2 + $Count) << 3; + } + + $iRet = 0; + for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) { + $iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j; + } + + $this->CurBit += $this->CodeSize; + return $iRet; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFCOLORTABLE +{ + var $m_nColors; + var $m_arColors; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFCOLORTABLE() + { + unSet($this->m_nColors); + unSet($this->m_arColors); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, $num) + { + $this->m_nColors = 0; + $this->m_arColors = array(); + + for ($i = 0; $i < $num; $i++) { + $rgb = substr($lpData, $i * 3, 3); + if (strlen($rgb) < 3) { + return false; + } + + $this->m_arColors[] = (ord($rgb{2}) << 16) + (ord($rgb{1}) << 8) + ord($rgb{0}); + $this->m_nColors++; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function toString() + { + $ret = ''; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $ret .= + chr(($this->m_arColors[$i] & 0x000000FF)) . // R + chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G + chr(($this->m_arColors[$i] & 0x00FF0000) >> 16); // B + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function toRGBQuad() + { + $ret = ''; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $ret .= + chr(($this->m_arColors[$i] & 0x00FF0000) >> 16) . // B + chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G + chr(($this->m_arColors[$i] & 0x000000FF)) . // R + "\x00"; + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function colorIndex($rgb) + { + $rgb = intval($rgb) & 0xFFFFFF; + $r1 = ($rgb & 0x0000FF); + $g1 = ($rgb & 0x00FF00) >> 8; + $b1 = ($rgb & 0xFF0000) >> 16; + $idx = -1; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $r2 = ($this->m_arColors[$i] & 0x000000FF); + $g2 = ($this->m_arColors[$i] & 0x0000FF00) >> 8; + $b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16; + $d = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1); + + if (($idx == -1) || ($d < $dif)) { + $idx = $i; + $dif = $d; + } + } + + return $idx; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFFILEHEADER +{ + var $m_lpVer; + var $m_nWidth; + var $m_nHeight; + var $m_bGlobalClr; + var $m_nColorRes; + var $m_bSorted; + var $m_nTableSize; + var $m_nBgColor; + var $m_nPixelRatio; + var $m_colorTable; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFFILEHEADER() + { + unSet($this->m_lpVer); + unSet($this->m_nWidth); + unSet($this->m_nHeight); + unSet($this->m_bGlobalClr); + unSet($this->m_nColorRes); + unSet($this->m_bSorted); + unSet($this->m_nTableSize); + unSet($this->m_nBgColor); + unSet($this->m_nPixelRatio); + unSet($this->m_colorTable); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, &$hdrLen) + { + $hdrLen = 0; + + $this->m_lpVer = substr($lpData, 0, 6); + if (($this->m_lpVer <> 'GIF87a') && ($this->m_lpVer <> 'GIF89a')) { + return false; + } + + $this->m_nWidth = $this->w2i(substr($lpData, 6, 2)); + $this->m_nHeight = $this->w2i(substr($lpData, 8, 2)); + if (!$this->m_nWidth || !$this->m_nHeight) { + return false; + } + + $b = ord(substr($lpData, 10, 1)); + $this->m_bGlobalClr = ($b & 0x80) ? true : false; + $this->m_nColorRes = ($b & 0x70) >> 4; + $this->m_bSorted = ($b & 0x08) ? true : false; + $this->m_nTableSize = 2 << ($b & 0x07); + $this->m_nBgColor = ord(substr($lpData, 11, 1)); + $this->m_nPixelRatio = ord(substr($lpData, 12, 1)); + $hdrLen = 13; + + if ($this->m_bGlobalClr) { + $this->m_colorTable = new CGIFCOLORTABLE(); + if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) { + return false; + } + $hdrLen += 3 * $this->m_nTableSize; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFIMAGEHEADER +{ + var $m_nLeft; + var $m_nTop; + var $m_nWidth; + var $m_nHeight; + var $m_bLocalClr; + var $m_bInterlace; + var $m_bSorted; + var $m_nTableSize; + var $m_colorTable; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFIMAGEHEADER() + { + unSet($this->m_nLeft); + unSet($this->m_nTop); + unSet($this->m_nWidth); + unSet($this->m_nHeight); + unSet($this->m_bLocalClr); + unSet($this->m_bInterlace); + unSet($this->m_bSorted); + unSet($this->m_nTableSize); + unSet($this->m_colorTable); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, &$hdrLen) + { + $hdrLen = 0; + + $this->m_nLeft = $this->w2i(substr($lpData, 0, 2)); + $this->m_nTop = $this->w2i(substr($lpData, 2, 2)); + $this->m_nWidth = $this->w2i(substr($lpData, 4, 2)); + $this->m_nHeight = $this->w2i(substr($lpData, 6, 2)); + + if (!$this->m_nWidth || !$this->m_nHeight) { + return false; + } + + $b = ord($lpData{8}); + $this->m_bLocalClr = ($b & 0x80) ? true : false; + $this->m_bInterlace = ($b & 0x40) ? true : false; + $this->m_bSorted = ($b & 0x20) ? true : false; + $this->m_nTableSize = 2 << ($b & 0x07); + $hdrLen = 9; + + if ($this->m_bLocalClr) { + $this->m_colorTable = new CGIFCOLORTABLE(); + if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) { + return false; + } + $hdrLen += 3 * $this->m_nTableSize; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFIMAGE +{ + var $m_disp; + var $m_bUser; + var $m_bTrans; + var $m_nDelay; + var $m_nTrans; + var $m_lpComm; + var $m_gih; + var $m_data; + var $m_lzw; + + /////////////////////////////////////////////////////////////////////////// + + function CGIFIMAGE() + { + unSet($this->m_disp); + unSet($this->m_bUser); + unSet($this->m_bTrans); + unSet($this->m_nDelay); + unSet($this->m_nTrans); + unSet($this->m_lpComm); + unSet($this->m_data); + $this->m_gih = new CGIFIMAGEHEADER(); + $this->m_lzw = new CGIFLZW(); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($data, &$datLen) + { + $datLen = 0; + + while (true) { + $b = ord($data{0}); + $data = substr($data, 1); + $datLen++; + + switch($b) { + case 0x21: // Extension + if (!$this->skipExt($data, $len = 0)) { + return false; + } + $datLen += $len; + break; + + case 0x2C: // Image + // LOAD HEADER & COLOR TABLE + if (!$this->m_gih->load($data, $len = 0)) { + return false; + } + $data = substr($data, $len); + $datLen += $len; + + // ALLOC BUFFER + if (!($this->m_data = $this->m_lzw->deCompress($data, $len = 0))) { + return false; + } + $data = substr($data, $len); + $datLen += $len; + + if ($this->m_gih->m_bInterlace) { + $this->deInterlace(); + } + return true; + + case 0x3B: // EOF + default: + return false; + } + } + return false; + } + + /////////////////////////////////////////////////////////////////////////// + + function skipExt(&$data, &$extLen) + { + $extLen = 0; + + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + + switch($b) { + case 0xF9: // Graphic Control + $b = ord($data{1}); + $this->m_disp = ($b & 0x1C) >> 2; + $this->m_bUser = ($b & 0x02) ? true : false; + $this->m_bTrans = ($b & 0x01) ? true : false; + $this->m_nDelay = $this->w2i(substr($data, 2, 2)); + $this->m_nTrans = ord($data{4}); + break; + + case 0xFE: // Comment + $this->m_lpComm = substr($data, 1, ord($data{0})); + break; + + case 0x01: // Plain text + break; + + case 0xFF: // Application + break; + } + + // SKIP DEFAULT AS DEFS MAY CHANGE + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + while ($b > 0) { + $data = substr($data, $b); + $extLen += $b; + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + } + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } + + /////////////////////////////////////////////////////////////////////////// + + function deInterlace() + { + $data = $this->m_data; + + for ($i = 0; $i < 4; $i++) { + switch($i) { + case 0: + $s = 8; + $y = 0; + break; + + case 1: + $s = 8; + $y = 4; + break; + + case 2: + $s = 4; + $y = 2; + break; + + case 3: + $s = 2; + $y = 1; + break; + } + + for (; $y < $this->m_gih->m_nHeight; $y += $s) { + $lne = substr($this->m_data, 0, $this->m_gih->m_nWidth); + $this->m_data = substr($this->m_data, $this->m_gih->m_nWidth); + + $data = + substr($data, 0, $y * $this->m_gih->m_nWidth) . + $lne . + substr($data, ($y + 1) * $this->m_gih->m_nWidth); + } + } + + $this->m_data = $data; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIF +{ + var $m_gfh; + var $m_lpData; + var $m_img; + var $m_bLoaded; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIF() + { + $this->m_gfh = new CGIFFILEHEADER(); + $this->m_img = new CGIFIMAGE(); + $this->m_lpData = ''; + $this->m_bLoaded = false; + } + + /////////////////////////////////////////////////////////////////////////// + + function loadFile($lpszFileName, $iIndex) + { + if ($iIndex < 0) { + return false; + } + + // READ FILE + if (!($fh = @fopen($lpszFileName, 'rb'))) { + return false; + } + $this->m_lpData = @fRead($fh, @fileSize($lpszFileName)); + fclose($fh); + + // GET FILE HEADER + if (!$this->m_gfh->load($this->m_lpData, $len = 0)) { + return false; + } + $this->m_lpData = substr($this->m_lpData, $len); + + do { + if (!$this->m_img->load($this->m_lpData, $imgLen = 0)) { + return false; + } + $this->m_lpData = substr($this->m_lpData, $imgLen); + } + while ($iIndex-- > 0); + + $this->m_bLoaded = true; + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function getSize($lpszFileName, &$width, &$height) + { + if (!($fh = @fopen($lpszFileName, 'rb'))) { + return false; + } + $data = @fRead($fh, @fileSize($lpszFileName)); + @fclose($fh); + + $gfh = new CGIFFILEHEADER(); + if (!$gfh->load($data, $len = 0)) { + return false; + } + + $width = $gfh->m_nWidth; + $height = $gfh->m_nHeight; + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function getBmp($bgColor) + { + $out = ''; + + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $nColors = $this->m_img->m_gih->m_nTableSize; + $rgbq = $this->m_img->m_gih->m_colorTable->toRGBQuad(); + if ($bgColor != -1) { + $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor); + } + } elseif ($this->m_gfh->m_bGlobalClr) { + $nColors = $this->m_gfh->m_nTableSize; + $rgbq = $this->m_gfh->m_colorTable->toRGBQuad(); + if ($bgColor != -1) { + $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor); + } + } else { + $nColors = 0; + $bgColor = -1; + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth; + $bmp = ''; + $nPad = ($this->m_gfh->m_nWidth % 4) ? 4 - ($this->m_gfh->m_nWidth % 4) : 0; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) { + // TRANSPARENT -> BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } else { + $bmp .= $data{$nPxl}; + } + } else { + // BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } + } + $nPxl -= $this->m_gfh->m_nWidth << 1; + + // ADD PADDING + for ($x = 0; $x < $nPad; $x++) { + $bmp .= "\x00"; + } + } + + // BITMAPFILEHEADER + $out .= 'BM'; + $out .= $this->dword(14 + 40 + ($nColors << 2) + strlen($bmp)); + $out .= "\x00\x00"; + $out .= "\x00\x00"; + $out .= $this->dword(14 + 40 + ($nColors << 2)); + + // BITMAPINFOHEADER + $out .= $this->dword(40); + $out .= $this->dword($this->m_gfh->m_nWidth); + $out .= $this->dword($this->m_gfh->m_nHeight); + $out .= "\x01\x00"; + $out .= "\x08\x00"; + $out .= "\x00\x00\x00\x00"; + $out .= "\x00\x00\x00\x00"; + $out .= "\x12\x0B\x00\x00"; + $out .= "\x12\x0B\x00\x00"; + $out .= $this->dword($nColors % 256); + $out .= "\x00\x00\x00\x00"; + + // COLOR TABLE + if ($nColors > 0) { + $out .= $rgbq; + } + + // DATA + $out .= $bmp; + + return $out; + } + + /////////////////////////////////////////////////////////////////////////// + + function getPng($bgColor) + { + $out = ''; + + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $nColors = $this->m_img->m_gih->m_nTableSize; + $pal = $this->m_img->m_gih->m_colorTable->toString(); + if ($bgColor != -1) { + $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor); + } + } elseif ($this->m_gfh->m_bGlobalClr) { + $nColors = $this->m_gfh->m_nTableSize; + $pal = $this->m_gfh->m_colorTable->toString(); + if ($bgColor != -1) { + $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor); + } + } else { + $nColors = 0; + $bgColor = -1; + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = 0; + $bmp = ''; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + $bmp .= "\x00"; + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + $bmp .= $data{$nPxl}; + } else { + // BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } + } + } + $bmp = gzcompress($bmp, 9); + + /////////////////////////////////////////////////////////////////////// + // SIGNATURE + $out .= "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; + /////////////////////////////////////////////////////////////////////// + // HEADER + $out .= "\x00\x00\x00\x0D"; + $tmp = 'IHDR'; + $tmp .= $this->ndword($this->m_gfh->m_nWidth); + $tmp .= $this->ndword($this->m_gfh->m_nHeight); + $tmp .= "\x08\x03\x00\x00\x00"; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + /////////////////////////////////////////////////////////////////////// + // PALETTE + if ($nColors > 0) { + $out .= $this->ndword($nColors * 3); + $tmp = 'PLTE'; + $tmp .= $pal; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + } + /////////////////////////////////////////////////////////////////////// + // TRANSPARENCY + if (@$this->m_img->m_bTrans && ($nColors > 0)) { + $out .= $this->ndword($nColors); + $tmp = 'tRNS'; + for ($i = 0; $i < $nColors; $i++) { + $tmp .= ($i == $this->m_img->m_nTrans) ? "\x00" : "\xFF"; + } + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + } + /////////////////////////////////////////////////////////////////////// + // DATA BITS + $out .= $this->ndword(strlen($bmp)); + $tmp = 'IDAT'; + $tmp .= $bmp; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + /////////////////////////////////////////////////////////////////////// + // END OF FILE + $out .= "\x00\x00\x00\x00IEND\xAE\x42\x60\x82"; + + return $out; + } + + /////////////////////////////////////////////////////////////////////////// + + // Added by James Heinrich - January 5, 2003 + + // Takes raw image data and plots it pixel-by-pixel on a new GD image and returns that + // It's extremely slow, but the only solution when ImageCreateFromString() fails + function getGD_PixelPlotterVersion() + { + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $pal = $this->m_img->m_gih->m_colorTable->toString(); + } elseif ($this->m_gfh->m_bGlobalClr) { + $pal = $this->m_gfh->m_colorTable->toString(); + } else { + die('No color table available in getGD_PixelPlotterVersion()'); + } + + $PlottingIMG = ImageCreate($this->m_gfh->m_nWidth, $this->m_gfh->m_nHeight); + $NumColorsInPal = floor(strlen($pal) / 3); + for ($i = 0; $i < $NumColorsInPal; $i++) { + $ThisImageColor[$i] = ImageColorAllocate( + $PlottingIMG, + ord($pal{(($i * 3) + 0)}), + ord($pal{(($i * 3) + 1)}), + ord($pal{(($i * 3) + 2)})); + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + set_time_limit(30); + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) { + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]); + } else { + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[ord($data{$nPxl})]); + } + } else { + // BACKGROUND + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]); + } + } + $nPxl -= $this->m_gfh->m_nWidth << 1; + + } + + return $PlottingIMG; + } + + /////////////////////////////////////////////////////////////////////////// + + function dword($val) + { + $val = intval($val); + return chr($val & 0xFF).chr(($val & 0xFF00) >> 8).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF000000) >> 24); + } + + /////////////////////////////////////////////////////////////////////////// + + function ndword($val) + { + $val = intval($val); + return chr(($val & 0xFF000000) >> 24).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF00) >> 8).chr($val & 0xFF); + } + + /////////////////////////////////////////////////////////////////////////// + + function width() + { + return $this->m_gfh->m_nWidth; + } + + /////////////////////////////////////////////////////////////////////////// + + function height() + { + return $this->m_gfh->m_nHeight; + } + + /////////////////////////////////////////////////////////////////////////// + + function comment() + { + return $this->m_img->m_lpComm; + } + + /////////////////////////////////////////////////////////////////////////// + + function loaded() + { + return $this->m_bLoaded; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/phpthumb.ico.php b/site/retailers/phpthumb/phpthumb.ico.php new file mode 100644 index 0000000..aed7214 --- /dev/null +++ b/site/retailers/phpthumb/phpthumb.ico.php @@ -0,0 +1,119 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.ico.php - .ICO output format functions // +// /// +////////////////////////////////////////////////////////////// + + +class phpthumb_ico { + + function phpthumb_ico() { + return true; + } + + + function GD2ICOstring(&$gd_image_array) { + foreach ($gd_image_array as $key => $gd_image) { + + $ImageWidths[$key] = ImageSX($gd_image); + $ImageHeights[$key] = ImageSY($gd_image); + $bpp[$key] = ImageIsTrueColor($gd_image) ? 32 : 24; + $totalcolors[$key] = ImageColorsTotal($gd_image); + + $icXOR[$key] = ''; + for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) { + for ($x = 0; $x < $ImageWidths[$key]; $x++) { + $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); + $a = round(255 * ((127 - $argb['alpha']) / 127)); + $r = $argb['red']; + $g = $argb['green']; + $b = $argb['blue']; + + if ($bpp[$key] == 32) { + $icXOR[$key] .= chr($b).chr($g).chr($r).chr($a); + } elseif ($bpp[$key] == 24) { + $icXOR[$key] .= chr($b).chr($g).chr($r); + } + + if ($a < 128) { + @$icANDmask[$key][$y] .= '1'; + } else { + @$icANDmask[$key][$y] .= '0'; + } + } + // mask bits are 32-bit aligned per scanline + while (strlen($icANDmask[$key][$y]) % 32) { + $icANDmask[$key][$y] .= '0'; + } + } + $icAND[$key] = ''; + foreach ($icANDmask[$key] as $y => $scanlinemaskbits) { + for ($i = 0; $i < strlen($scanlinemaskbits); $i += 8) { + $icAND[$key] .= chr(bindec(str_pad(substr($scanlinemaskbits, $i, 8), 8, '0', STR_PAD_LEFT))); + } + } + + } + + foreach ($gd_image_array as $key => $gd_image) { + $biSizeImage = $ImageWidths[$key] * $ImageHeights[$key] * ($bpp[$key] / 8); + + // BITMAPINFOHEADER - 40 bytes + $BitmapInfoHeader[$key] = ''; + $BitmapInfoHeader[$key] .= "\x28\x00\x00\x00"; // DWORD biSize; + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageWidths[$key], 4); // LONG biWidth; + // The biHeight member specifies the combined + // height of the XOR and AND masks. + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageHeights[$key] * 2, 4); // LONG biHeight; + $BitmapInfoHeader[$key] .= "\x01\x00"; // WORD biPlanes; + $BitmapInfoHeader[$key] .= chr($bpp[$key])."\x00"; // wBitCount; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biCompression; + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($biSizeImage, 4); // DWORD biSizeImage; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biXPelsPerMeter; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biYPelsPerMeter; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrUsed; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrImportant; + } + + + $icondata = "\x00\x00"; // idReserved; // Reserved (must be 0) + $icondata .= "\x01\x00"; // idType; // Resource Type (1 for icons) + $icondata .= phpthumb_functions::LittleEndian2String(count($gd_image_array), 2); // idCount; // How many images? + + $dwImageOffset = 6 + (count($gd_image_array) * 16); + foreach ($gd_image_array as $key => $gd_image) { + // ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) + + $icondata .= chr($ImageWidths[$key]); // bWidth; // Width, in pixels, of the image + $icondata .= chr($ImageHeights[$key]); // bHeight; // Height, in pixels, of the image + $icondata .= chr($totalcolors[$key]); // bColorCount; // Number of colors in image (0 if >=8bpp) + $icondata .= "\x00"; // bReserved; // Reserved ( must be 0) + + $icondata .= "\x01\x00"; // wPlanes; // Color Planes + $icondata .= chr($bpp[$key])."\x00"; // wBitCount; // Bits per pixel + + $dwBytesInRes = 40 + strlen($icXOR[$key]) + strlen($icAND[$key]); + $icondata .= phpthumb_functions::LittleEndian2String($dwBytesInRes, 4); // dwBytesInRes; // How many bytes in this resource? + + $icondata .= phpthumb_functions::LittleEndian2String($dwImageOffset, 4); // dwImageOffset; // Where in the file is this image? + $dwImageOffset += strlen($BitmapInfoHeader[$key]); + $dwImageOffset += strlen($icXOR[$key]); + $dwImageOffset += strlen($icAND[$key]); + } + + foreach ($gd_image_array as $key => $gd_image) { + $icondata .= $BitmapInfoHeader[$key]; + $icondata .= $icXOR[$key]; + $icondata .= $icAND[$key]; + } + + return $icondata; + } + +} + +?> \ No newline at end of file diff --git a/site/retailers/phpthumb/phpthumb.unsharp.php b/site/retailers/phpthumb/phpthumb.unsharp.php new file mode 100644 index 0000000..799b5cd --- /dev/null +++ b/site/retailers/phpthumb/phpthumb.unsharp.php @@ -0,0 +1,162 @@ + // +// for use in phpThumb() on 3 February 2003. // +// // +// phpThumb() is found at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// + +/* +WARNING! Due to a known bug in PHP 4.3.2 this script is not working well in this version. +The sharpened images get too dark. The bug is fixed in version 4.3.3. + +Unsharp masking is a traditional darkroom technique that has proven very suitable for +digital imaging. The principle of unsharp masking is to create a blurred copy of the image +and compare it to the underlying original. The difference in colour values +between the two images is greatest for the pixels near sharp edges. When this +difference is subtracted from the original image, the edges will be +accentuated. + +The Amount parameter simply says how much of the effect you want. 100 is 'normal'. +Radius is the radius of the blurring circle of the mask. 'Threshold' is the least +difference in colour values that is allowed between the original and the mask. In practice +this means that low-contrast areas of the picture are left unrendered whereas edges +are treated normally. This is good for pictures of e.g. skin or blue skies. + +Any suggenstions for improvement of the algorithm, expecially regarding the speed +and the roundoff errors in the Gaussian blur process, are welcome. +*/ + +class phpUnsharpMask { + + function applyUnsharpMask(&$img, $amount, $radius, $threshold) { + + // $img is an image that is already created within php using + // imgcreatetruecolor. No url! $img must be a truecolor image. + + // Attempt to calibrate the parameters to Photoshop: + $amount = min($amount, 500); + $amount = $amount * 0.016; + if ($amount == 0) { + return true; + } + + $radius = min($radius, 50); + $radius = $radius * 2; + + $threshold = min($threshold, 255); + + $radius = abs(round($radius)); // Only integers make sense. + if ($radius == 0) { + return true; + } + + $w = ImageSX($img); + $h = ImageSY($img); + $imgCanvas = ImageCreateTrueColor($w, $h); + $imgCanvas2 = ImageCreateTrueColor($w, $h); + ImageCopy($imgCanvas, $img, 0, 0, 0, 0, $w, $h); + ImageCopy($imgCanvas2, $img, 0, 0, 0, 0, $w, $h); + + + $builtinFilterSucceeded = false; + if ($radius == 1) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($imgCanvas, IMG_FILTER_GAUSSIAN_BLUR) && ImageFilter($imgCanvas2, IMG_FILTER_GAUSSIAN_BLUR)) { + $builtinFilterSucceeded = true; + } + } + } + + if (!$builtinFilterSucceeded) { + $imgBlur = ImageCreateTrueColor($w, $h); + $imgBlur2 = ImageCreateTrueColor($w, $h); + + /////////////////////////// + // + // Gaussian blur matrix: + // 1 2 1 + // 2 4 2 + // 1 2 1 + // + /////////////////////////// + + // Move copies of the image around one pixel at the time and merge them with weight + // according to the matrix. The same matrix is simply repeated for higher radii. + for ($i = 0; $i < $radius; $i++) { + ImageCopy ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20 ); // up + ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center + ImageCopy ($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h); + + // During the loop above the blurred copy darkens, possibly due to a roundoff + // error. Therefore the sharp picture has to go through the same loop to + // produce a similar image for comparison. This is not a good thing, as processing + // time increases heavily. + ImageCopy ($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 20 ); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 16.666667); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); + ImageCopy ($imgCanvas2, $imgBlur2, 0, 0, 0, 0, $w, $h); + } + ImageDestroy($imgBlur); + ImageDestroy($imgBlur2); + } + + // Calculate the difference between the blurred pixels and the original + // and set the pixels + for ($x = 0; $x < $w; $x++) { // each row + for ($y = 0; $y < $h; $y++) { // each pixel + + $rgbOrig = ImageColorAt($imgCanvas2, $x, $y); + $rOrig = (($rgbOrig >> 16) & 0xFF); + $gOrig = (($rgbOrig >> 8) & 0xFF); + $bOrig = ($rgbOrig & 0xFF); + + $rgbBlur = ImageColorAt($imgCanvas, $x, $y); + $rBlur = (($rgbBlur >> 16) & 0xFF); + $gBlur = (($rgbBlur >> 8) & 0xFF); + $bBlur = ($rgbBlur & 0xFF); + + // When the masked pixels differ less from the original + // than the threshold specifies, they are set to their original value. + $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig; + $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig; + $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig; + + if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) { + $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew); + ImageSetPixel($img, $x, $y, $pixCol); + } + } + } + ImageDestroy($imgCanvas); + ImageDestroy($imgCanvas2); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/site/retailers/rating-example.php b/site/retailers/rating-example.php new file mode 100644 index 0000000..6225023 --- /dev/null +++ b/site/retailers/rating-example.php @@ -0,0 +1,60 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

    Race Rating System:

    + + + + + \ No newline at end of file diff --git a/site/retailers/rating/ajax.rate.item.php b/site/retailers/rating/ajax.rate.item.php new file mode 100644 index 0000000..38c90de --- /dev/null +++ b/site/retailers/rating/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/retailers/rating/classes/database.class.php b/site/retailers/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/retailers/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/retailers/rating/classes/error.class.php b/site/retailers/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/retailers/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Error Template Output + $output = "
    \r\n" . + "
    {$error}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Warning Template Output + $output = "
    \r\n" . + "
    {$warning}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/retailers/rating/classes/include.all.php b/site/retailers/rating/classes/include.all.php new file mode 100644 index 0000000..2c1fa21 --- /dev/null +++ b/site/retailers/rating/classes/include.all.php @@ -0,0 +1,7 @@ + diff --git a/site/retailers/rating/classes/rating.class.php b/site/retailers/rating/classes/rating.class.php new file mode 100644 index 0000000..35d5293 --- /dev/null +++ b/site/retailers/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +
    {$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
    {$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
    Overall Rating
    "; + $output .= "
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    \r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_RetailersRating` (`rating_retailer_id`, `rating_category_id`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_RetailersRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_RetailersRating` WHERE `rating_category_id`='{$varItem}' AND `rating_retailer_id`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_RetailersRating` WHERE `rating_retailer_id`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_RetailersRating` WHERE `rating_category_id`='{$varItem}' AND `rating_retailer_id`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> diff --git a/site/retailers/rating/int.to.words.php b/site/retailers/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/retailers/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/retailers/rating/rating-example.php b/site/retailers/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/retailers/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

    Race Rating System:

    + + + + + + + \ No newline at end of file diff --git a/site/retailers/regionlist.php b/site/retailers/regionlist.php new file mode 100644 index 0000000..0c88282 --- /dev/null +++ b/site/retailers/regionlist.php @@ -0,0 +1,88 @@ + '2008-01-01' ORDER BY gt.date ASC");*/ + +$results = mysql_query("SELECT gr.retailer_id, gr.retailer_name, gr.retailer_address, gr.retailer_address_two, gr.retailer_city, gr.retailer_state, gr.retailer_zip, gr.retailer_phone, gr.retailer_fax, gr.retailer_email, gr.retailer_website, gr.retailer_cart +FROM gforum_Retailers AS gr +RIGHT JOIN gforum_TriathlonsStates AS gts +ON gts.regionid = '".mysql_real_escape_string($_GET[region])."' AND gr.retailer_state_tag = gts.statetag +WHERE gr.retailer_valid = 1 ORDER BY gr.retailer_name ASC"); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} + +/*$results = mysql_query("SELECT onetype, twotype, threetype, oneunit, twounit, threeunit, name, nametag, statetag, swim, bike, run, city, state, uid, UNIX_TIMESTAMP(date) as foo FROM gforum_Triathlons RIGHT JOIN WHERE regionid='$_GET[region]' AND valid=1 AND date > '2008-01-01' ORDER BY date ASC");**/ + +// set the page title +$pagetitle = $regionname; + +// set meta tags +$meta_keywords = "triathlon retailers in ".$regionname; +$meta_description = "Trying to find triathlon retailers in ".$regionname."? Here is a listing of all ".$regionname." triathlon retailers."; +?> + + + + + + + + +
    + +
    +
    + + + +
    + + +
    +
    + +
    +

    Retailers

    + Back + + " class="btn btn-white float-right">Add Retailer + +
    + + +

    Region

    +
    + No triathlon retailers have been entered yet for $regionname.

    "; + } + ?> + + + + +
    +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/retailers/search.php b/site/retailers/search.php new file mode 100644 index 0000000..d9f00c4 --- /dev/null +++ b/site/retailers/search.php @@ -0,0 +1,368 @@ + + + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Search For A Retailer

    +

    If you would like to search for a retailer, please use the form below. None of the fields are mandatory. Checking no box in a field indicates you don't care if a shop has or does not have fitters on staff, a fit bike, or motion capture system, or any of the listed brands. Checking regions selects all states in that region. Checking any state's box selects or deselects that state. All searches are "OR" based, so checking two boxes will find shops that, for example, use either an EXIT fit bike OR a Serotta size-cycle. The one exception is for certifications, where checking both boxes will find shops who have both Serotta & FIST certifications; you can use the "ANY" box to search for shops who have fitters with one or the other or both certifications.

    + +
    +

    +
    +
    +
    Name Search
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Bike Fit

    +
    +
    +
    +
    Fitters On Staff
    +
    +
    + + + + + + + + +
    F.I.S.T. Tri F.I.S.T. Road F.I.S.T. AdvancedBikeFit, BodyGeometry, Retul, Serotta, or Trek ANY
    +
    +
    +
    +
    Default Tri-Fit Methodology
    +
    +
    +"); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +echo("\n"); +$i++; +while($i<4) { + echo(""); + $i++; +} +if(!($i%4)) echo ""; + +echo(""); + +?> +
    $row[retailer_method_name]ANY 
    +
    +
    +
    +
    Fit-Bike Model(s) Used
    +
    +
    +"); +//echo(""); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +if(!($i%4)) echo ""; +echo("\n"); +echo(""); + +?> +
    $row[retailers_fitbike_name]
    ANY
    +
    +
    +
    +
    Motion-Capture Systems
    +
    +
    +"); +//echo(""); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +if(!($i%4)) echo ""; +echo("\n"); +echo(""); + +?> +
    $row[retailers_motioncapture_name]
    ANY
    +
    +
    +
    +
    +
    +
    +

    Brands

    +
    +
    +
    +
    eCommerce Online Shopping Cart
    +
    +
    + Yes +
    +
    +
    +
    Mail order via
    +
    +
    + + + + + +
    eCommerce phone    
    +
    +
    +
    +
    Local delivery
    +
    +
    + + + + + +
    eCommerce phone    
    +
    +
    +
    +
    Advanced order for in-store pickup
    +
    +
    + + + + + +
    eCommerce phone    
    +
    +
    +
    +
    Spoke Alliance Member
    +
    +
    + Yes +
    +
    +
    +
    Wetsuits
    +
    +
    +"); +//echo(""); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +//if(!($i%4)) echo ""; +//echo("\n"); +echo(""); + +?> +
    $row[retailers_wetsuit_name]
    Any
    +
    +
    +
    +
    Bikes
    +
    +
    +"); +//echo(""); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +//if(!($i%4)) echo ""; +//echo("\n"); +echo(""); + +?> +
    $row[retailers_bike_name]
    Any
    +
    +
    +
    +
    Custom Frames
    +
    +
    +"); +//echo(""); +while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; +} +//if(!($i%4)) echo ""; +//echo("\n"); +echo(""); + +?> +
    $row[retailers_custom_name]
    Any
    +
    +
    +
    +
    +
    +
    +

    Location

    +
    +
    +
    +
    Region
    +
    +
    + +"; +foreach($regions AS $region => $statetag) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + +} + +?> + +
    $region
    + +

    Selecting a region will select all states in that region. You can then deselect or select any additional states. Only the selected states will be included in your search. Leaving all boxes blank will select races in all states.

    +
    +
    +
    +
    State
    +
    +
    + +"; +while($row = mysql_fetch_array($state_list)){ + if(!($i%4)) echo ""; + echo "\n"; + $i++; +} +?> + +
    $row[statelong]
    +

    Leave blank to select all.

    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/retailers/search_X.php b/site/retailers/search_X.php new file mode 100644 index 0000000..1ca3e3b --- /dev/null +++ b/site/retailers/search_X.php @@ -0,0 +1,335 @@ + '0'"; + } else { + $sql = $sql." AND ("; + $flag = 0; + foreach ($_POST[methods] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." retailer_method = '$value'"; + $flag = 1; + } + $sql = $sql.")"; + } +} + +if (isset($_POST[fitbikes])) { + if (in_array("999", $_POST[fitbikes])) { + $sql = $sql." AND retailer_fitbikes <> ',0,'"; + } else { + $sql = $sql." AND ("; + $flag = 0; + foreach ($_POST[fitbikes] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." retailer_fitbikes LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[fitbikes] AS $value) { + $sql = $sql." AND retailer_fitbikes LIKE '%,$value,%'"; + }**/ + } +} + +if (isset($_POST[motioncapture])) { + if (in_array("999", $_POST[motioncapture])) { + $sql = $sql." AND retailer_motioncapture <> ',0,'"; + } else { + $sql = $sql." AND ("; + $flag = 0; + foreach ($_POST[motioncapture] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." retailer_motioncapture LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[motioncapture] AS $value) { + $sql = $sql." AND retailer_motioncapture LIKE '%,$value,%'"; + }**/ + } +} + +if (isset($_POST[ecommerce])) { + $sql = $sql." AND retailer_cart = 1"; +} + +if (isset($_POST[spoke])) { + $sql = $sql." AND retailer_spoke = 1"; +} + +if (isset($_POST[mailorder_ecommerce])) { + $sql = $sql." AND retailer_mailorder_ecommerce = 1"; +} +if (isset($_POST[mailorder_phone])) { + $sql = $sql." AND retailer_mailorder_phone = 1"; +} +if (isset($_POST[local_ecommerce])) { + $sql = $sql." AND retailer_local_ecommerce = 1"; +} +if (isset($_POST[local_phone])) { + $sql = $sql." AND retailer_local_phone = 1"; +} +if (isset($_POST[pickup_ecommerce])) { + $sql = $sql." AND retailer_pickup_ecommerce = 1"; +} +if (isset($_POST[pickup_phone])) { + $sql = $sql." AND retailer_pickup_phone = 1"; +} +if (isset($_POST[ecommerce])) { + $sql = $sql." AND retailer_cart = 1"; +} + +if (isset($_POST[wetsuits])) { + $sql = $sql." AND ("; + $flag = 0; + foreach ($_POST[wetsuits] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." retailer_wetsuits LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[wetsuits] AS $value) { + $sql = $sql." AND retailer_wetsuits LIKE '%,$value,%'"; + }**/ +} + +if (isset($_POST[bikes])) { + $sql = $sql." AND ("; + $flag = 0; + foreach ($_POST[bikes] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." retailer_bikes LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bikes] AS $value) { + $sql = $sql." AND retailer_bikes LIKE '%,$value,%'"; + }**/ +} + +if (isset($_POST[customs])) { + $sql = $sql." AND ("; + $flag = 0; + foreach ($_POST[customs] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." retailer_customs LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[customs] AS $value) { + $sql = $sql." AND retailer_customs LIKE '%,$value,%'"; + }**/ +} + +// add tri or du or other +/*if (isset($_POST[type])) { + // convert the array to a SQL friendly format + $typelist = "(".implode(",", $_POST[type]).")"; + $sql = $sql." AND type IN $typelist"; +}*/ + +// regions are checkboxes that then check off all states within that region +// add states +if (isset($_POST[states])) { + $glue = "','"; + $statelist = "('".implode($glue, $_POST[states])."')"; + $sql = $sql." AND retailer_state_tag IN $statelist"; +} + + +$sql = $sql." ORDER BY retailer_name ASC"; + +//echo $sql; + +$results = mysql_query(mysql_real_escape_string($sql)); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} +$match_count = mysql_num_rows($results); + +//keyword search +// trim redundant keywords: triathlon, duathlon +$trim_words = array(" the ", " a ", " an ", "and ", " half ", "triathlon", "duathlon"); +foreach ($trim_words AS $word) { + $_POST['keyword'] = str_ireplace($word, " ", $_POST['keyword']); +} +$bool_Keywords = false; +if (isset($_POST['keyword']) && $_POST['keyword'] != "") { + $bool_Keywords = true; + while($row_retaileres = mysql_fetch_array($results)) { + // build an array that we can loop through. + $arr_retaileres[$i] = $row_retaileres; + $i++; + } + + $arr_Matches = array(); + foreach ($arr_retaileres AS $retailer) { + if (stripos($retailer['retailer_name'], $_POST['keyword']) !== false) { + // push this onto the array of matches + $retailer['percent'] = 100; + array_push($arr_Matches, $retailer); + } else { + $name_nospace = str_replace(" ", "", $retailer['retailer_name']); + $keyword_nospace = str_replace(" ", "", $_POST['keyword']); + if (stripos($name_nospace, $keyword_nospace) !== false) { + // push this onto the array of matches + $retailer['percent'] = 90; + array_push($arr_Matches, $retailer); + } else { + // trim redundant keywords + $retailer_name = $retailer['retailer_name']; + foreach ($trim_words AS $word) { + $retailer_name = str_ireplace($word, " ", $retailer_name); + } + //$retailer_name = str_ireplace(" ", "", $retailer_name); + $retailer_name = strtolower($retailer_name); + $arr_retailer_name = explode(" ", $retailer_name); + $_POST['keyword'] = strtolower($_POST['keyword']); + $_POST['keyword'] = str_replace(" ", "", $_POST['keyword']); + foreach ($arr_retailer_name AS $test_word) { + similar_text($test_word, $_POST['keyword'], $percent); + if ($percent >= $comp_pct) { + // push this onto the array of matches + $retailer['percent'] = round($percent, 0); + //$retailer['trimmed'] = $retailer_name; + array_push($arr_Matches, $retailer); + break; + } + } + } + } + } + + if (count($arr_Matches) == 0) { + $none = TRUE; + } + $match_count = count($arr_Matches); + + //sort the array by keyword match success instead of by date + function cmp($a, $b) + { + if ($a['percent'] == $b['percent']) { + return 0; + } + return ($a['percent'] > $b['percent']) ? -1 : 1; + } + + usort($arr_Matches, "cmp"); +} +//end keyword search + +// set the page title +$pagetitle = "Search Results"; + +// set meta tags +$meta_keywords = "search, retailers, triathlon, results"; +$meta_description = "Triathlon retailers in matching a user's search query. A list of matching retailers."; +?> + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Search Results

    +

    Retailers Match Your Search

    + + + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/retailers/statelist.php b/site/retailers/statelist.php new file mode 100644 index 0000000..d87d738 --- /dev/null +++ b/site/retailers/statelist.php @@ -0,0 +1,123 @@ + + + + + + + +
    + +
    +
    + + + +
    + +
    +
    + +
    +

    Retailers

    + Back + + Add Retailer + +
    + + +

    State

    +
    + No bike shops have been entered yet for ".$statename. ".

    "; + } ?> + + + + +
    +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/retailers/top_retailers.php b/site/retailers/top_retailers.php new file mode 100644 index 0000000..6bda738 --- /dev/null +++ b/site/retailers/top_retailers.php @@ -0,0 +1,105 @@ + ".$x_years_ago." GROUP BY grr.rating_retailer_id HAVING COUNT(grr.rating_vote) > ".$min_number_of_votes." ORDER BY score DESC, votes DESC"); + +$top_retailers = array(); +while($row = mysql_fetch_array($results)) { + + $row['weighted_score'] = $row['score']+$w_respondents*($row['respondents']); + $row['weighted_score'] = $row['weighted_score']+$w_retailer_cart*($row['retailer_cart']); + $row['weighted_score'] = $row['weighted_score']+$w_retailer_shopper_tags*substr_count($row['retailer_shopper_tags'], ','); + $row['weighted_score'] = $row['weighted_score']+$w_retailer_fitbikes*substr_count($row['retailer_fitbikes'], ','); + $row['weighted_score'] = $row['weighted_score']* $w_retailer_motioncapture+substr_count($row['retailer_motioncapture'], ','); + $row['weighted_score'] = $row['weighted_score']+$w_retailer_wetsuits*substr_count($row['retailer_wetsuits'], ','); + $row['weighted_score'] = $row['weighted_score']+$w_retailer_bikes*substr_count($row['retailer_bikes'], ','); + $row['weighted_score'] = $row['weighted_score']+$w_retailer_fist_names*substr_count($row['retailer_fist_names'], ','); + array_push($top_retailers, $row); +} + +//sort the array by keyword match success instead of by date +function cmp($a, $b) +{ + if ($a['weighted_score'] == $b['weighted_score']) { + return 0; + } + return ($a['weighted_score'] > $b['weighted_score']) ? -1 : 1; +} + +usort($top_retailers, "cmp"); + +// set the page title +$pagetitle = "Top Retailers"; + +// set meta tags +$meta_keywords = "top ranked retailers"; +$meta_description = "Top ranked triathlon retailers based on rankings submitted by the user."; +?> + + + + + +
    + +
    +
    + + +
    + +
    +
    + +
    +

    Top Ranked Triathlon Retailers

    +
    + +

    These rankings are compiled based off Slowtwitch.com's own scoring algorithm. The individual ranking - by stars - of each shop is still shown. But the list's ranking and the score shown on this page is the Slowtwitch.com score for each retailer.

    + + + + +
    + + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/retailers/top_retailers_dan_only.php b/site/retailers/top_retailers_dan_only.php new file mode 100644 index 0000000..5e6105e --- /dev/null +++ b/site/retailers/top_retailers_dan_only.php @@ -0,0 +1,121 @@ + ".$x_years_ago." GROUP BY grr.rating_retailer_id HAVING COUNT(grr.rating_vote) > ".$min_number_of_votes." ORDER BY score DESC, votes DESC"); + +$top_retailers = array(); +while($row = mysql_fetch_array($results)) { + + $row['weighted_score'] = $row['score']+$w_respondents*($row['respondents']); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_cart*($row['retailer_cart']); + + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_shopper_tags*substr_count($row['retailer_shopper_tags'], ','); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_fitbikes*substr_count($row['retailer_fitbikes'], ','); + + $row['weighted_score'] = $row['weighted_score']* $w_retailer_motioncapture+substr_count($row['retailer_motioncapture'], ','); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_wetsuits*substr_count($row['retailer_wetsuits'], ','); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_bikes*substr_count($row['retailer_bikes'], ','); + + $row['weighted_score'] = $row['weighted_score']+$w_retailer_fist_names*substr_count($row['retailer_fist_names'], ','); + + array_push($top_retailers, $row); +} + + //sort the array by keyword match success instead of by date + function cmp($a, $b) + { + if ($a['weighted_score'] == $b['weighted_score']) { + return 0; + } + return ($a['weighted_score'] > $b['weighted_score']) ? -1 : 1; + } + + usort($top_retailers, "cmp"); + +// set the page title +$pagetitle = "Top Retailers"; + +// set meta tags +$meta_keywords = "top ranked retailers"; +$meta_description = "Top ranked triathlon retailers based on rankings submitted by the user."; +?> + + + + + +
    + + +
    + + + + + +

    Top Ranked Triathlon Retailers

    +
    +These rankings are compiled based off Slowtwitch.com's own scoring algorithm. The individual ranking - by stars - of each shop is still shown. But the list's ranking and the score shown on this page is the Slowtwitch.com score for each retailer.

    + + + +"> + + +
    +"> + + - ".$row[retailer_city].", ".$row[retailer_state]." -"; ?> +
    +
    + + + +
    + +
    + + + + diff --git a/site/retailers/validate.php b/site/retailers/validate.php new file mode 100644 index 0000000..139c776 --- /dev/null +++ b/site/retailers/validate.php @@ -0,0 +1,108 @@ + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + +

    Unvalidated Retailers

    +
    + +
    + +
    +
    Shop Name: + "> +
    +
    +
    +
    Address: + $row[retailer_address_two]"); } echo("
    $row[retailer_city], $row[retailer_state] $row[retailer_zip]"); ?> +
    +
    +
    +
    Phone: + +
    +
    +
    +
    Fax: + +
    +
    +
    +
    E-mail: + $row[retailer_email]"; ?> +
    +
    +
    +
    Website: + $row[retailer_website]"; ?> +
    +
    +
    +
    + ">More information +
    Validate this retailer. Delete this retailer. +
    +
    + +
    + +
    + + +
    +
    +
    + + + +
    +
    + + +
    + + + diff --git a/site/retailers/validate_X.php b/site/retailers/validate_X.php new file mode 100644 index 0000000..c27828e --- /dev/null +++ b/site/retailers/validate_X.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/site/retailers/wiki_buttons.php b/site/retailers/wiki_buttons.php new file mode 100644 index 0000000..d103e13 --- /dev/null +++ b/site/retailers/wiki_buttons.php @@ -0,0 +1,21 @@ + + +
    + +
    + + +
    + +
    + + +
    + +
    diff --git a/site/retailers/wiki_edit.php b/site/retailers/wiki_edit.php new file mode 100644 index 0000000..08c8610 --- /dev/null +++ b/site/retailers/wiki_edit.php @@ -0,0 +1,555 @@ + + +"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); +?> + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + +

    Thank You

    +

    Thank you. Your shop should be added within 24 hours. You will now be redirected back to the homepage page.

    + + +

    Edit a Shop: Step 2 of 2

    + +

    Edit a Shop: Step 1 of 2

    + +

    Thank you

    + +
    + + +

    To edit a retailer, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes as a NEW retailer (for instance, if you have multiple locations), hit the "SAVE AS A NEW RETAILER" button. To save changes to the existing retailer entry, hit the "SAVE CHANGES TO YOUR SHOP" button. You will have a chance to review the data before confirming.

    + + + +
    +

    +
    +
    +
    Shop Name
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Address 2
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    Online Shopping Cart
    +
    +
    + (Must be a fully functional ecommerce system) +
    +
    +
    Spoke Alliance Member
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    We ship mail-order via
    +
    +
    + >e-commerce site
    + >phone +
    +
    +
    +
    We offer local home/work delivery, transacting via
    +
    +
    + >e-commerce site
    + >phone +
    +
    +
    +
    You may order in advance, and pick up, transacting via
    +
    +
    + >e-commerce site
    + >phone +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    F.I.S.T. Tri Fitter(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    F.I.S.T. Road Fitter(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    F.I.S.T. Advanced Fitter(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    BFACT Score
    +
    +
    + +
    +
    +
    +
    BikeFit, BodyGeometry, Retul, Serotta, or Trek Fitter(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    Default Tri-Fit Methodology
    +
    +
    +"); +while ($list = mysql_fetch_array($fetch)) { + echo("$list[retailer_method_name]\n"); + $i++; +} +?> +
    +
    +
    +
    Fit Bikes
    +
    +
    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[retailers_fitbike_name]\n"); +} +?> +
    +
    +
    +
    Motion-Capture Systems
    +
    +
    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[retailers_motioncapture_name]\n"); +} +?> +
    +
    +
    +
    +
    +
    + +

    IMPORTANT: Tri and road bike brands of which you'll have six or more sitting on the floor during the season.

    +
    +
    +
    +
    Wetsuits
    +
    +
    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[retailers_wetsuit_name]\n"); +} +?> +
    +
    +
    +
    Bikes
    +
    +
    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[retailers_bike_name]\n"); +} +?> +
    +
    +
    +
    Custom Frames
    +
    +
    +

    IMPORTANT: Custom brands of which you'll sell six or more in a 12 month period.

    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[retailers_custom_name]\n"); +} +?> +
    +
    +
    +
    Shop Hours
    +
    +
    + +
    +
    +
    +
    Barnett-Trained Mechanic(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    United Bicycle Institute-Trained Mechanic(s)
    +
    +
    + >None
    + >Yes, Their Names: + +
    +
    +
    +
    Shop Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + +
    + +
    +
    + + + +
    +
    + + +
    + + + diff --git a/site/retailers/wiki_edit_X.php b/site/retailers/wiki_edit_X.php new file mode 100644 index 0000000..1195e32 --- /dev/null +++ b/site/retailers/wiki_edit_X.php @@ -0,0 +1,165 @@ + 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = mysql_real_escape_string(trim($_POST[retailer_address])); + $address_two = mysql_real_escape_string(trim($_POST[retailer_address_two])); + $city = mysql_real_escape_string(trim($_POST[retailer_city])); + $state = mysql_real_escape_string($_POST[retailer_state]); + $state_tag = mysql_real_escape_string(strtolower(str_replace(" ","", $state))); + $zip = mysql_real_escape_string(trim($_POST[retailer_zip])); + $phone = mysql_real_escape_string(trim($_POST[retailer_phone])); + $fax = mysql_real_escape_string(trim($_POST[retailer_fax])); + $email = mysql_real_escape_string(trim($_POST[retailer_email])); + $website = mysql_real_escape_string(trim($_POST[retailer_website])); + $substring = "http://"; + if (!is_int(strpos($website, $substring))) { + $website = "http://".$website; + } + $cart = mysql_real_escape_string(trim($_POST[retailer_cart])); + $mailorder_ecommerce = mysql_real_escape_string(trim($_POST[retailer_mailorder_ecommerce])); + $mailorder_phone = mysql_real_escape_string(trim($_POST[retailer_mailorder_phone])); + $local_ecommerce = mysql_real_escape_string(trim($_POST[retailer_local_ecommerce])); + $local_phone = mysql_real_escape_string(trim($_POST[retailer_local_phone])); + $pickup_ecommerce = mysql_real_escape_string(trim($_POST[retailer_pickup_ecommerce])); + $pickup_phone = mysql_real_escape_string(trim($_POST[retailer_pickup_phone])); + $contact = mysql_real_escape_string($_POST[retailer_contact]); + if ( $contact == 0 ){ $contact_names = NULL; }else{ $contact_names = mysql_real_escape_string(trim($_POST[retailer_contact_names])); } + $fist = mysql_real_escape_string($_POST[retailer_fist]); + if ( $fist == 0 ){ $fist_names = NULL; }else{ $fist_names = mysql_real_escape_string(trim($_POST[retailer_fist_names])); } + $fist_road = mysql_real_escape_string($_POST[retailer_fist_road]); + if ( $fist_road == 0 ){ $fist_road_names = NULL; }else{ $fist_road_names = mysql_real_escape_string(trim($_POST[retailer_fist_road_names])); } + $fist_advanced = mysql_real_escape_string($_POST[retailer_fist_advanced]); + if ( $fist_advanced == 0 ){ $fist_advanced_names = NULL; }else{ $fist_advanced_names = mysql_real_escape_string(trim($_POST[retailer_fist_advanced_names])); } + $bfact = mysql_real_escape_string(trim($_POST[retailer_bfact])); + $serotta = mysql_real_escape_string($_POST[retailer_serotta]); + if ( $serotta == 0 ){ $serotta_names = NULL; }else{ $serotta_names = mysql_real_escape_string(trim($_POST[retailer_serotta_names])); } + /* Need to ltrim and rtrim commas before insertion --> or ltrim/rtrim before implosion*/ + $method = mysql_real_escape_string($_POST[retailer_method]); + $fitbikes = mysql_real_escape_string($_POST[retailer_fitbikes]); + $motioncapture = mysql_real_escape_string($_POST[retailer_motioncapture]); + $wetsuits = mysql_real_escape_string($_POST[retailer_wetsuits]); + $bikes = mysql_real_escape_string($_POST[retailer_bikes]); + $customs = mysql_real_escape_string($_POST[retailer_customs]); + $hours = mysql_real_escape_string(trim($_POST[retailer_hours])); + $barnett = mysql_real_escape_string($_POST[retailer_barnett]); + if ( $barnett == 0 ){ $barnett_names = NULL; }else{ $barnett_names = mysql_real_escape_string(trim($_POST[retailer_barnett_names])); } + $ubi = mysql_real_escape_string($_POST[retailer_ubi]); + if ( $ubi == 0 ){ $ubi_names = NULL; }else{ $ubi_names = mysql_real_escape_string(trim($_POST[retailer_ubi_names])); } + $info = mysql_real_escape_string(substr(trim($_POST[retailer_info]), 0, 4096)); + $directions = mysql_real_escape_string(substr(trim($_POST[retailer_directions]), 0, 4096)); + $submitted_by = mysql_real_escape_string($_POST[retailer_submitted_by]); + $id = mysql_real_escape_string($_POST[retailer_id]); + $edited_by = mysql_real_escape_string($_POST[edited_by]); + $edit_timestamp = time(); + $spoke = mysql_real_escape_string(trim($_POST[retailer_spoke])); + + // BEGIN CONFIRM ENTRY CHECK + if($_POST[confirm_entry] == 1){ + if(isset($_POST[new_shop])){ + $sql = "INSERT INTO gforum_Retailers (retailer_name, retailer_name_tag, retailer_address, retailer_address_two, retailer_city, retailer_state, retailer_state_tag, retailer_zip, retailer_phone, retailer_fax, retailer_email, retailer_website, retailer_cart, retailer_mailorder_ecommerce, retailer_mailorder_phone, retailer_local_ecommerce, retailer_local_phone, retailer_pickup_ecommerce, retailer_pickup_phone, retailer_contact, retailer_contact_names, retailer_fist, retailer_fist_names, retailer_fist_road, retailer_fist_road_names, retailer_fist_advanced, retailer_fist_advanced_names, retailer_bfact, retailer_serotta, retailer_serotta_names, retailer_method, retailer_fitbikes, retailer_motioncapture, retailer_wetsuits, retailer_bikes, retailer_customs, retailer_hours, retailer_barnett, retailer_barnett_names, retailer_ubi, retailer_ubi_names, retailer_info, retailer_directions, retailer_submitted_by, retailer_valid, retailer_spoke) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', '$cart', '$mailorder_ecommerce', '$mailorder_phone', '$local_ecommerce', '$local_phone', '$pickup_ecommerce', '$pickup_phone', $contact, '$contact_names', $fist, '$fist_names', $fist_road, '$fist_road_names', $fist_advanced, '$fist_advanced_names', '$bfact', $serotta, '$serotta_names', '$method', ',$fitbikes,', ',$motioncapture,', ',$wetsuits,', ',$bikes,', ',$customs,', '$hours', $barnett, '$barnett_names', $ubi, '$ubi_names', '$info', '$directions', $submitted_by, 0, '$spoke')"; + //echo("shop entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/add.php?confirmed=yes'); + } elseif(isset($_POST[save_changes])) { + $sql = "INSERT INTO gforum_RetailersEdits (retailer_id_fk, editor_user_id_fk, edit_timestamp, retailer_name, retailer_name_tag, retailer_address, retailer_address_two, retailer_city, retailer_state, retailer_state_tag, retailer_zip, retailer_phone, retailer_fax, retailer_email, retailer_website, retailer_cart, retailer_mailorder_ecommerce, retailer_mailorder_phone, retailer_local_ecommerce, retailer_local_phone, retailer_pickup_ecommerce, retailer_pickup_phone, retailer_contact, retailer_contact_names, retailer_fist, retailer_fist_names, retailer_fist_road, retailer_fist_road_names, retailer_fist_advanced, retailer_fist_advanced_names, retailer_bfact, retailer_serotta, retailer_serotta_names, retailer_method, retailer_fitbikes, retailer_motioncapture, retailer_wetsuits, retailer_bikes, retailer_customs, retailer_hours, retailer_barnett, retailer_barnett_names, retailer_ubi, retailer_ubi_names, retailer_info, retailer_directions, retailer_submitted_by, retailer_valid, retailer_spoke) VALUES ('$id', '$edited_by', '$edit_timestamp', '$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', '$cart', '$mailorder_ecommerce', '$mailorder_phone', '$local_ecommerce', '$local_phone', '$pickup_ecommerce', '$pickup_phone', $contact, '$contact_names', $fist, '$fist_names', $fist_road, '$fist_road_names', $fist_advanced, '$fist_advanced_names', '$bfact', $serotta, '$serotta_names', '$method', ',$fitbikes,', ',$motioncapture,', ',$wetsuits,', ',$bikes,', ',$customs,', '$hours', $barnett, '$barnett_names', $ubi, '$ubi_names', '$info', '$directions', $submitted_by, 0, '$spoke')"; + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/individual.php?retailer_id='.$id.'&wiki_change=success'); + } else { + header('Location: '.$site_url.'/individual.php?retailer_id='.$id.'&changes=failure'); + } + } else { + //echo("shop NOT entered."); + $confirm = 1; + } + // END CONFIRM ENTRY CHECK + } + // END ERROR MESSAGE CHECK +?> diff --git a/site/retailers/wiki_validate.php b/site/retailers/wiki_validate.php new file mode 100644 index 0000000..34202a8 --- /dev/null +++ b/site/retailers/wiki_validate.php @@ -0,0 +1,98 @@ + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Unvalidated Public Edits

    +
    + +
    + + +
    Edited on: by ".$editor_user_username.""; if ($boolEditorIsOwner) { echo " (original retailer submitter)"; } else { echo ""; } ?>
    +
    Info: + 400){ + $phrase = "…"; }else{ + $phrase = ""; } + + echo substr(htmlspecialchars(stripslashes($row[retailer_info])), 0, 160); + echo $phrase; + ?> +
    + +
    +
    + Location:
    + ">More information +
    Validate this edit. Delete this edit.
    +
    +
    + +
    +

    + +

    +
    + +
    +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/retailers/wiki_validate_X.php b/site/retailers/wiki_validate_X.php new file mode 100644 index 0000000..5e50b9e --- /dev/null +++ b/site/retailers/wiki_validate_X.php @@ -0,0 +1,99 @@ + \ No newline at end of file diff --git a/site/retailers/wiki_view.php b/site/retailers/wiki_view.php new file mode 100644 index 0000000..bd6c71f --- /dev/null +++ b/site/retailers/wiki_view.php @@ -0,0 +1,414 @@ + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    + + +
    + +Editor: ".$strEditor.""; ?> +
    + +Edit Date: +
    + +Street Address: +
    +Street Address Two: +
    +City: +
    +State: +
    +Zip/Postal Code: +
    +Phone: +
    +Fax / Alternate Phone: +
    +E-mail: +
    +Website: +
    +Spoke Alliance Member: + + +
    + +
    +
    +
    + +We ship mail-order via: + + +
    +We offer local home/work delivery, transacting via: + + +
    +You may order in advance, and pick up, transacting via: + + + +
    +
    + +
    + +
    + +
    +Key Tri-Specific Contact(s): +
    +F.I.S.T. Tri Fitter(s): +
    +F.I.S.T. Road Fitter(s): +
    +F.I.S.T. Advanced Fitter(s): +
    +BFACT Score: +
    +BikeFit, BodyGeometry, Retul, Serotta, or Trek Fitter(s): +
    +Default Tri-Fit Methodology: 0) { + while ($method_list = mysql_fetch_array($fetch)) { + echo ("$method_list[retailer_method_name]"); + } +} else { + echo ("Unanswered"); +} + +?> +
    +Fit Bikes: + +
    +Motion-Capture Systems: + +

    +
    + +
    + +
    +Wetsuits: + +
    +Bikes: + +
    +Custom Frames: + +

    +
    + +
    +
    +Shop Hours: +
    +Barnett-Trained Mechanic(s): +
    +United Bicycle Institute-Trained Mechanic(s): +

    +Shop Info: +

    +Directions: + +
    +
    + +
    + + +"; + include ('comments_add.php'); +}**/ + +?> + + + +
    + + + +"; +?> + + + + + +
    +
    +
    + 0){ +$tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value'") or die (mysql_error()); +$temprow = mysql_fetch_array($tempresults); +if($i > 1){ echo ", "; } +// TODO: SLOWTWITCH EDIT +//echo "$temprow[user_username]"; +// replace the link above with the link below for integration into gforum +echo "$temprow[user_username]"; +// TODO: SLOWTWITCH EDIT END +} +$i++; +} +if(count($tags) <= 1){ echo "No users"; } +?> +
    + +
    + + + +
    + + + +"; +?> + + + + +
    +
    +
    += 0){ +$tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); +$temprow = mysql_fetch_array($tempresults); +if($i >= 1){ echo "
    "; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + // TODO: SLOWTWITCH EDIT END +} +$i++; +} +if($numcount <= 0){ echo "No users"; } +?> +
    + +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/roadshow/add.php b/site/roadshow/add.php new file mode 100644 index 0000000..63ae49e --- /dev/null +++ b/site/roadshow/add.php @@ -0,0 +1,1754 @@ + + + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + +

    Thank you

    +

    Thank you. Your slowtwitch road show information should be added within 24 hours. You will now be redirected back to the add page.

    + + + +

    Add a Slowtwitch Road Show Event: Step 2 of 2

    + +

    Add a Slowtwitch Road Show Event: Step 1 of 2

    +
    + + +

    If you would like to add a slowtwitch road show to our website, simply fill out the form below. Be sure to fill out every field. After filling out each field, click submit. You will then be prompted to confirm your information before the information is sent to us.

    + +

    + + + +
    +
    +
    +
    Name
    +
    +
    + +
    +
    +
    +
    Event Date
    +
    +
    + + + +
    +
    +
    +
    Start Time
    +
    +
    + + : + + +
    +
    +
    +
    Street Address
    +
    +
    + +
    +
    +
    +
    Street Address Two (optional)
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    Override Address With Lat/Lng
    +
    +
    + class="txt medtext" >
    Check this if you know your physical address doesn't geocode properly using Google's API. Then enter the desired lat/lng in the boxes below. +
    +
    +
    +
    Latitude
    +
    +
    + +
    +
    +
    +
    Longitude
    +
    +
    + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax/Alternate Phone
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website (include http://)
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Local Assets

    +
    +
    +
    +
    Slowtwitch Ambassador(s)
    +
    +
    + >None + >Yes, Their Names: + +
    +
    +
    +
    Tri Club(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Coach(es)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Race Director(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Brewery(ies)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Other
    +
    +
    + +
    +
    +
    +
    Fit Bikes
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[fitbike_name]"); + } + ?> +
    +
    +
    +
    Saddle Quick Change
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[saddlechange_name]"); + } + ?> +
    +
    +
    +
    Motion Capture Systems
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[motioncapture_name]"); + } + ?> +
    +
    +
    +
    Custom Footbeds
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[footbed_name]\n"); + } + + ?> +
    +
    +
    +
    +
    +
    +

    Brands

    +
    +
    +
    +
    Tri Apparel
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[apparel_tri_name]\n"); + } + ?> +
    +
    +
    +
    Bike
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bike_name]\n"); + } + ?> +
    +
    +
    +
    Bike Saddles/Footwear/Aerobars/Bike Hydration
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikeaccessory_name]\n"); + } + ?> +
    +
    +
    +
    Bike Helmets/Eyewear
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikehelmet_name]\n"); + } + ?> +
    +
    +
    +
    Bike Nutritionals/Lubricants/Botanicals
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikebody_name]\n"); + } + ?> +
    +
    +
    +
    Bike Stationary Trainers
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[biketrainer_name]\n"); + } + ?> +
    +
    +
    +
    Bike Electronics/Cameras/Metrics
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikeelectronic_name]\n"); + } + ?> +
    +
    +
    +
    Bike Wheels/Tires
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikewheel_name]\n"); + } + ?> +
    +
    +
    +
    Bike Components
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikecomponent_name]\n"); + } + ?> +
    +
    +
    +
    Socks
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[sock_name]\n"); + } + ?> +
    +
    +
    +
    Running Shoes
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[shoe_name]\n"); + } + ?> +
    +
    +
    +
    Run Apparel
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[apparel_run_name]\n"); + $i++; + } + ?> +
    +
    +
    +
    Run Hydration
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[runhydrate_name]\n"); + } + ?> +
    +
    +
    +
    Wetsuits
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[wetsuit_name]\n"); + $i++; + } + ?> +
    +
    +
    +
    Swim Apparel/Gear
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[swimgear_name]\n"); + $i++; + } + ?> +
    +
    +
    +
    Body Care Tools
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bodycare_name]\n"); + } + ?> +
    +
    +
    +
    +
    +
    +

    Technology, Community & Education

    +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    F.I.S.T. Tri Fitters(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Diagnostic Equipment
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[diagnostic_name]\n"); + } + ?> +
    +
    +
    +
    +
    +
    +

    Social

    +
    +
    +
    +
    Shop hours
    +
    +
    + +
    +
    +
    +
    Runs & Classes
    +
    +
    + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + +

    Please confirm your information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your information before submitting.

    +
    +
    +
    Name
    +
    +
    + + = 50) { + if ($i == false) { + echo ("Duplicate Alert:"); + } + if ($i == true) {echo ("
    ");} + echo ("".$match_row['roadshow_name']." (".$match_row['roadshow_city'].", ".$match_row['roadshow_state'].") (Similarity: ".(round($percent, 0))."%)"); + $i = true; + } + } + ?> +
    +
    +
    +
    Date
    +
    +
    + +
    +
    +
    +
    Start
    +
    +
    + +
    +
    +
    +
    Street Address
    +
    +
    + +
    +
    +
    +
    Street Address Two
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    Lat/Lng
    +
    +
    + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax/Alternate Phone
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Local Assets

    +
    +
    +
    +
    Slowtwitch Ambassador(s)
    +
    +
    + +
    +
    +
    +
    Tri Club(s)
    +
    +
    + +
    +
    +
    +
    Coach(es)
    +
    +
    + +
    +
    +
    +
    Race Director(s)
    +
    +
    + +
    +
    +
    +
    Brewery(ies)
    +
    +
    + +
    +
    +
    +
    Other
    +
    +
    + +
    +
    +
    +
    Fitbike(s)
    +
    +
    + +
    +
    +
    +
    Saddle Quick Change
    +
    +
    + +
    +
    +
    +
    Motion Capture System(s)
    +
    +
    + +
    +
    +
    +
    Custom Footbed(s)
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Brands

    +
    +
    +
    +
    Triathlon Apparel
    +
    +
    + +
    +
    +
    +
    Bike(s)
    +
    +
    + +
    +
    +
    +
    Bike Saddles/Footwear/Aerobars/Bike Hydration
    +
    +
    + +
    +
    +
    +
    Bike Helmets/Eyewear
    +
    +
    + +
    +
    +
    +
    Bike Nutritionals/Lubricants/Botanicals
    +
    +
    + +
    +
    +
    +
    Bike Stationary Trainer(s)
    +
    +
    + +
    +
    +
    +
    Bike Electronics/Cameras/Metrics
    +
    +
    + +
    +
    +
    +
    Bike Wheels/Tires
    +
    +
    + +
    +
    +
    +
    Bike Component(s)
    +
    +
    + +
    +
    +
    +
    Sock(s)
    +
    +
    + +
    +
    +
    +
    Running Shoe(s)
    +
    +
    + +
    +
    +
    +
    Running Apparel
    +
    +
    + +
    +
    +
    +
    Run Hydration
    +
    +
    + +
    +
    +
    +
    Wetsuit(s)
    +
    +
    + +
    +
    +
    +
    Swim Apparel/Gear
    +
    +
    + +
    +
    +
    +
    Bodycare Tools
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Technology, Community & Education

    +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Tri Fitters(s)
    +
    +
    + +
    +
    +
    +
    Diagnostic Tools
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Social

    +
    +
    +
    +
    Shop Hours
    +
    +
    + +
    +
    +
    +
    General Info & Notes
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/roadshow/add_X.php b/site/roadshow/add_X.php new file mode 100644 index 0000000..f0e8632 --- /dev/null +++ b/site/roadshow/add_X.php @@ -0,0 +1,225 @@ +"; + $errmsg = rtrim($errmsg, ", "); +} + +$start_url = "(http(s)?\:\/\/)?"; // start url +$dots = "([\w_-]{2,}\.)+"; // one or more parts containing a '.' at the end +$last_part = "([\w_-]{2,})"; // last part doesn't contain a dot +$user = "((\/)(\~)[\w_=-]+)?((\/)[\w_=-]+)*"; // maybe subdirectories - possibly with user ~ +$end = "((\/)|(\/)[\w_-]+\.[\w]{2,})?"; // maybe a slash at the end or slash+file+extension +$qstring1 = "((\?[\w_-]+\=([^\#]+)){0,1}"; // querystring - first argument (?a=b) +$qstring2 = "(\&[\w_-]+\=([^\#]+))*)?"; // querystring - following arguments (&c=d) +$bkmrk = "(#[\w_-]+)?"; // bookmark + +$exp = "/^".$start_url.$dots.$last_part.$user.$end.$qstring1.$qstring2.$bkmrk."$/i"; +if( !preg_match($exp, $_POST[website]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
    "; +} +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[name]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Please use only letters and numbers in the name
    "; +} + +// begin error message check +if(!$errmsg){ + + $name = trim($_POST[name]); + $name_tag = strtolower(str_replace(" ","", $name)); + //if(strlen($name_tag) > 12){ //Shorten it + $name_tag = substr($name_tag, 0, 12); + //} // need to update a typo here in other dbs + $address = mysql_escape_string(trim($_POST[address])); + $full_address = $address; + if (isset($_POST['address_two'])) { $address_two = mysql_escape_string(trim($_POST[address_two])); } else { $address_two = NULL; $full_address = $full_address.", ".$address_two; } + $city = mysql_escape_string(trim($_POST[city])); + $full_address = $full_address.", ".$city; + $state = $_POST[state]; + $full_address = $full_address.", ".$state; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = mysql_escape_string(trim($_POST[zip])); + $full_address = $full_address." ".$zip; + $latlng_override = $_POST[latlng_override]; + if ($latlng_override == true) { + $lat = $_POST[lat]; + $lng = $_POST[lng]; + } else { + //geocode + //echo ($full_address); + $geocode_status = geocode($full_address); + //echo (is_array($geocode_status)); + if (is_array($geocode_status)) { + $geocode_error = false; + $lat = $geocode_status[0]; + $_POST[lat] = $lat; + $lng = $geocode_status[1]; + $_POST[lng] = $lng; + //echo ($lat.", ".$lng); + } else { + $geocode_error = true; + $lat = 0; + $_POST[lat] = $lat; + $lng = 0; + $_POST[lng] = $lng; + $geocode_message = $geocode_status; + } + } + $phone = mysql_escape_string(trim($_POST[phone])); + $fax = mysql_escape_string(trim($_POST[fax])); + $email = mysql_escape_string(trim($_POST[email])); + $website = mysql_escape_string(trim($_POST[website])); + + $stambassador = mysql_escape_string(trim($_POST[stambassador])); + $stambassador_names = mysql_escape_string(trim($_POST[stambassador_names])); + $triclub = mysql_escape_string(trim($_POST[triclub])); + $triclub_names = mysql_escape_string(trim($_POST[triclub_names])); + $coach = mysql_escape_string(trim($_POST[coach])); + $coach_names = mysql_escape_string(trim($_POST[coach_names])); + $racedirector = mysql_escape_string(trim($_POST[racedirector])); + $racedirector_names = mysql_escape_string(trim($_POST[racedirector_names])); + $brewery = mysql_escape_string(trim($_POST[brewery])); + $brewery_names = mysql_escape_string(trim($_POST[brewery_names])); + $local = mysql_escape_string(trim($_POST[local])); + $fitbike = $_POST[fitbike]; + $saddlechange = $_POST[saddlechange]; + $motioncapture = $_POST[motioncapture]; + $footbed = $_POST[footbed]; + $wetsuit = $_POST[wetsuit]; + $bike = $_POST[bike]; + $trispecific = mysql_escape_string(trim($_POST[trispecific])); + $trispecific_names = mysql_escape_string(trim($_POST[trispecific_names])); + $fist = mysql_escape_string(trim($_POST[fist])); + $fist_names = mysql_escape_string(trim($_POST[fist_names])); + $diagnostic = $_POST[diagnostic]; + $shoe = $_POST[shoe]; + $sock = $_POST[sock]; + $apparel_run = $_POST[apparel_run]; + $apparel_tri = $_POST[apparel_tri]; + $swimgear = $_POST[swimgear]; + $bikeaccessory = $_POST[bikeaccessory]; + $bikebody = $_POST[bikebody]; + $bikecomponent = $_POST[bikecomponent]; + $bikeelectronic = $_POST[bikeelectronic]; + $bikehelmet = $_POST[bikehelmet]; + $biketrainer = $_POST[biketrainer]; + $bikewheel = $_POST[bikewheel]; + $runhydrate = $_POST[runhydrate]; + $bodycare = $_POST[bodycare]; + $hours = mysql_escape_string(trim($_POST[hours])); + + $activity = mysql_escape_string(nl2br(substr(trim($_POST[activity]), 0, 4096))); + + $hour = $_POST[hour]; + if($_POST[daypart] == 1){ $hour = $hour + 12; } + $minute = $_POST[minute]; + $year = $_POST[year]; + $month = $_POST[month]; + $day = $_POST[day]; + $date = "$year-$month-$day $hour:$minute:00"; + + $submitted_by = $_POST[submitted_by]; + + // begin boolean check to see if we should insert the open water event into the dbase + if($_POST[insert_roadshow] == true){ + $sql = "INSERT INTO ".$prefix."Roadshow (roadshow_date, roadshow_name, roadshow_name_tag, roadshow_address, roadshow_address_two, roadshow_city, roadshow_state, roadshow_state_tag, roadshow_zip, roadshow_lat, roadshow_lng, roadshow_phone, roadshow_fax, roadshow_email, roadshow_website, roadshow_stambassador, roadshow_stambassador_names, roadshow_triclub, roadshow_triclub_names, roadshow_coach, roadshow_coach_names, roadshow_racedirector, roadshow_racedirector_names, roadshow_brewery, roadshow_brewery_names, roadshow_local, roadshow_fitbike, roadshow_saddlechange, roadshow_motioncapture, roadshow_footbed, roadshow_wetsuit, roadshow_bike, roadshow_trispecific, roadshow_trispecific_names, roadshow_fist, roadshow_fist_names, roadshow_diagnostic, roadshow_shoe, roadshow_sock, roadshow_apparel_run, roadshow_apparel_tri, roadshow_swimgear, roadshow_bikeaccessory, roadshow_bikebody, roadshow_bikecomponent, roadshow_bikeelectronic, roadshow_bikehelmet, roadshow_biketrainer, roadshow_bikewheel, roadshow_runhydrate, roadshow_bodycare, roadshow_hours, roadshow_activity, roadshow_submitted_by, roadshow_valid) VALUES ('$date', '$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$lat', '$lng', '$phone', '$fax', '$email', '$website', '$stambassador', '$stambassador_names', '$triclub', '$triclub_names', '$coach', '$coach_names', '$racedirector', '$racedirector_names', '$brewery', '$brewery_names', '$local', '$fitbike', '$saddlechange', '$motioncapture', '$footbed', '$wetsuit', '$bike', '$trispecific', '$trispecific_names', '$fist', '$fist_names', '$diagnostic', '$shoe', '$sock', '$apparel_run', '$apparel_tri', '$swimgear', '$bikeaccessory', '$bikebody', '$bikecomponent', '$bikeelectronic', '$bikehelmet', '$biketrainer', '$bikewheel', '$runhydrate', '$bodycare', '$hours', '$activity', $submitted_by, 0)"; + //echo("roadshow entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + //exit(); + $insert_success = true; + }else{ + //echo("event NOT entered."); + $confirm_roadshow = true; + } + // end insert check +} +// end error message check +?> diff --git a/site/roadshow/ajax.rate.item.php b/site/roadshow/ajax.rate.item.php new file mode 100644 index 0000000..2b62953 --- /dev/null +++ b/site/roadshow/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/roadshow/class/mysql.class.php b/site/roadshow/class/mysql.class.php new file mode 100644 index 0000000..6d82189 --- /dev/null +++ b/site/roadshow/class/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/roadshow/class/rating/classes/database.class.php b/site/roadshow/class/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/roadshow/class/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/roadshow/class/rating/classes/error.class.php b/site/roadshow/class/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/roadshow/class/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Error Template Output + $output = "
    \r\n" . + "
    {$error}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Warning Template Output + $output = "
    \r\n" . + "
    {$warning}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/roadshow/class/rating/classes/include.all.php b/site/roadshow/class/rating/classes/include.all.php new file mode 100644 index 0000000..95a5d46 --- /dev/null +++ b/site/roadshow/class/rating/classes/include.all.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/site/roadshow/class/rating/classes/rating.class.php b/site/roadshow/class/rating/classes/rating.class.php new file mode 100644 index 0000000..0921ec8 --- /dev/null +++ b/site/roadshow/class/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +{$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
    {$cat_info['rating_cat_name']}
    "; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
    Overall Rating
    "; + $output .= "
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    \r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_FittersRating` (`fitter_id_fk`, `category_id_fk`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_FittersRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_FittersRating` WHERE `category_id_fk`='{$varItem}' AND `fitter_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_FittersRating` WHERE `fitter_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_FittersRating` WHERE `category_id_fk`='{$varItem}' AND `fitter_id_fk`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> \ No newline at end of file diff --git a/site/roadshow/class/rating/int.to.words.php b/site/roadshow/class/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/roadshow/class/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/roadshow/class/rating/rating-example.php b/site/roadshow/class/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/roadshow/class/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

    Race Rating System:

    + + + + + + + \ No newline at end of file diff --git a/site/roadshow/comments_show.php b/site/roadshow/comments_show.php new file mode 100644 index 0000000..2260dd2 --- /dev/null +++ b/site/roadshow/comments_show.php @@ -0,0 +1,14 @@ + + + +" data-num-posts="5" data-width="500">
    */ ?> +" num_posts="5" width="500">**/ ?> + diff --git a/site/roadshow/config.php b/site/roadshow/config.php new file mode 100644 index 0000000..0118722 --- /dev/null +++ b/site/roadshow/config.php @@ -0,0 +1,312 @@ += '4.0.4pl1' && strstr($_SERVER["HTTP_USER_AGENT"],'compatible')) { + if (extension_loaded('zlib')) { + ob_end_clean(); + ob_start('ob_gzhandler'); + } +} else if ($phpver > '4.0') { + if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) { + if (extension_loaded('zlib')) { + $do_gzip_compress = TRUE; + ob_start(array('ob_gzhandler',5)); + ob_implicit_flush(0); + header('Content-Encoding: gzip'); + } + } +} +$phpver = explode(".", $phpver); +$phpver = "$phpver[0]$phpver[1]"; +if ($phpver >= 41) { + $PHP_SELF = $_SERVER['PHP_SELF']; +} + +if (!ini_get("register_globals")) { + import_request_variables('GPC'); +} + + +include("class/mysql.class.php"); +$db = new sql_db($dbhost, $dbuname, $dbpass, $dbname, false); +if(!$db->db_connect_id) { + + echo "


    Error:


    + Connection to database failed
    +








    "; + + exit(); +} + +$statecount = mysql_num_rows(mysql_query("SELECT * FROM gforum_Roadshow WHERE roadshow_valid = 1")); + +$sql = "SELECT * FROM ".$prefix."ResourceStates ORDER BY stateid"; +$result = mysql_query($sql) OR die(mysql_error()); +$state_list = array(); +$state_tag_list = array(); +while ($row = mysql_fetch_array($result)) { + $state_list[$row['stateid']] = $row['statelong']; + $state_tag_list[] = $row['statetag']; +} + +function curPageURL() { + $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); + $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); + $port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : ''; + $url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.$_SERVER["REQUEST_URI"]; + return $url; +} + +function geocode($address) { + // Initialize delay in geocode speed + $delay = 0; + $base_url = "http://" . MAPS_HOST . "/maps/api/geocode/xml?"; // . "&key=" . KEY; + //echo ("Base URL: ".$base_url); + + $status = ""; + $geocode_pending = true; + + while ($geocode_pending) { + $address = str_replace(" ", "+", $address); + $address = str_replace("#", "", $address); + $address = str_replace("\'", "", $address); + $address = str_replace("/", "", $address); + $request_url = $base_url . "address=" . $address . "&sensor=false"; //urlencode($address); + $request_url = mb_convert_encoding($request_url, "UTF-8", "auto"); + //echo ($request_url."
    "); + // Create cUrl object to grab XML content using $request_url + $c = curl_init(); + curl_setopt($c, CURLOPT_URL, $request_url); + curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); + $xmlContent = trim(curl_exec($c)); + curl_close($c); + + // Create SimpleXML object from XML Content + $xml = simplexml_load_string($xmlContent); + + // Print out all of the XML Object + //print header("Content-type: text/plain"); + //print_r($xml); + + $resolution = $xml->result->geometry->location_type; + + $status = $xml->status; + if (strcmp($status, "OK") == 0) { + // Successful geocode + $geocode_pending = false; + $lat = $xml->result->geometry->location->lat; + $lng = $xml->result->geometry->location->lng; + $latlng_array = array($lat, $lng); + return ($latlng_array); + } elseif (strcmp($status, "OVER_QUERY_LIMIT") == 0) { + // failure to geocode + $geocode_pending = false; + $status = "Road Show Event " . $row['roadshow_name'] . " failed to geocode. "; + $status = $status . "Received status " . $status . "

    \n"; + return ($status); + } else { + // failure to geocode + $geocode_pending = false; + $status = "Address " . $address . " failed to geocode. "; + $status = $status . "Received status " . $status . "

    \n"; + return ($status); + } + } + +} + +//Array of states for use in the form +/** $state_list = array('AL'=>"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming", + // New Foreign "States", + 'UK'=>"United Kingdom", + 'FR'=>"France", + 'DE'=>"Germany", + 'IT'=>"Italy", + 'CH'=>"Switzerland", + 'JP'=>"Japan", + 'AU'=>"Australia", + 'NZ'=>"New Zealand", + 'PI'=>"Pacific Islands", + 'HK'=>"Hong Kong"); +*/ +?> diff --git a/site/roadshow/delete_X.php b/site/roadshow/delete_X.php new file mode 100644 index 0000000..e54d6ee --- /dev/null +++ b/site/roadshow/delete_X.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/site/roadshow/include_appointment.php b/site/roadshow/include_appointment.php new file mode 100644 index 0000000..de52789 --- /dev/null +++ b/site/roadshow/include_appointment.php @@ -0,0 +1,4 @@ + +
    + +
    diff --git a/site/roadshow/include_breadcrumb.php b/site/roadshow/include_breadcrumb.php new file mode 100644 index 0000000..ddaf53f --- /dev/null +++ b/site/roadshow/include_breadcrumb.php @@ -0,0 +1,10 @@ + diff --git a/site/roadshow/include_buttons.php b/site/roadshow/include_buttons.php new file mode 100644 index 0000000..bbff566 --- /dev/null +++ b/site/roadshow/include_buttons.php @@ -0,0 +1,105 @@ + + +
    +
    + + +
    +
    " style="display: inline;"> + +
    +" style="display: inline;"> + + **/?> + +
    " style="display: inline;"> + +
    + +
    " style="display: inline;"> + +
    + + + +
    + + +
    + +
    Entered By: $username"); + } +} +?> +
    diff --git a/site/roadshow/include_common_content.php b/site/roadshow/include_common_content.php new file mode 100644 index 0000000..7aef4db --- /dev/null +++ b/site/roadshow/include_common_content.php @@ -0,0 +1,59 @@ + + +> + + +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    +
    +
    diff --git a/site/roadshow/include_common_footer.php b/site/roadshow/include_common_footer.php new file mode 100644 index 0000000..f11e4aa --- /dev/null +++ b/site/roadshow/include_common_footer.php @@ -0,0 +1 @@ + diff --git a/site/roadshow/include_common_head.php b/site/roadshow/include_common_head.php new file mode 100644 index 0000000..0e44674 --- /dev/null +++ b/site/roadshow/include_common_head.php @@ -0,0 +1,84 @@ + + + + + + + +Slowtwitch.com Roadshow Event Database: <? echo $pagetitle; ?> + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/site/roadshow/include_navigation.php b/site/roadshow/include_navigation.php new file mode 100644 index 0000000..4852c9d --- /dev/null +++ b/site/roadshow/include_navigation.php @@ -0,0 +1,34 @@ + + +
    +

    Road Show Stops

    +
    + $prior_city) { + echo ("
    ".$navdatetime->format('M j')." ".$navrow[''.$field_lead.'city'].", ".$navrow[''.$field_lead.'state'] . "
    "); + } else { + echo ("
    "); + } + echo (""); + echo ($navrow[''.$field_lead.'name']); + echo (""); + $prior_city = $current_city; +} + +?> + +
    +
    + Search   +
    +
    +
    diff --git a/site/roadshow/include_share.php b/site/roadshow/include_share.php new file mode 100644 index 0000000..ec982a2 --- /dev/null +++ b/site/roadshow/include_share.php @@ -0,0 +1,27 @@ + +
    + + + +   + + + + + + +  
    +
    +

    + +**/ + +?> \ No newline at end of file diff --git a/site/roadshow/include_sidebar.php b/site/roadshow/include_sidebar.php new file mode 100644 index 0000000..c389c20 --- /dev/null +++ b/site/roadshow/include_sidebar.php @@ -0,0 +1,13 @@ + +
    + + + +
    + + diff --git a/site/roadshow/include_status.php b/site/roadshow/include_status.php new file mode 100644 index 0000000..539bf5f --- /dev/null +++ b/site/roadshow/include_status.php @@ -0,0 +1,10 @@ +Admin:"); + echo("
    Add ".$local_singular.""); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table." WHERE ".$field_lead."valid = 0")); + echo("
    Validate Entries (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Edits")); + echo("
    Validate Edits (".$unvalid_count.")"); +} +?> diff --git a/site/roadshow/index.php b/site/roadshow/index.php new file mode 100644 index 0000000..1c9f6c5 --- /dev/null +++ b/site/roadshow/index.php @@ -0,0 +1,72 @@ + + + + + + + +
    + +
    +
    + + +
    + +
    +
    +
    +

    Road Show

    +
    + +

    Global road show event map

    +

    The map below shows the location of all registered Slowtwitch road show events around the globe. You can drag the map, zoom-in, zoom-out, and use any other of the standard Google Maps features. Anywhere you see a red icon, you can click to see the name of that road show event and a street address.

    +
    +
    +
    + +

    What if we threw a party and an expo broke out?

    +

    That's what the Slowtwitch Road Shows are all about. In 34 locations, 1 Road Show per selected U.S. city, triathletes and tri-curious can see, touch, learn about, and buy compelling stuff made for multisporters. Okay, we confess: lt's totally about wearing out the cash registers. But we'll make it a painless buy. Features of this special day, which is entirely free to attendees:

    +

    Beer, Free stuff, Demo shoes from popular running shoe brands, On-site race entries (discounts, maybe?), Beer, Slowtwitch staff and notorious Slowtwitch Reader Forum personalities., Cheap stuff, Virtual training and racing demos (Zwift and VirtualTrainer), Food, Beer, Demo bikes from the sport's most important tri bike makers, Lots of inventory in the latest stuff.

    + +

    Here's who'll you'll meet at Slowtwitch Road Shows:

    +

    Slowtwitch staff and regulars including Dan Empfield; Karen Sing; Ian Murray; Steve Fleck; Lars Finanger; Herbert Krabel. And also meet all your local race directors

    +

    But wait, there's more. Slowtwitch is more than an online magazine and the sport's largest Reader Forum. Its team members provided the templates for the wetsuits you wear and the bikes you ride; and the way you fit aboard those bikes. At most Road Shows you'll see or both of two workstations:

    +
      +
    • Saddle Optimizer: Rides several saddles back-to-back on stationary equipment built for the purpose
    • +
    • Complete Bike Solver: Discover, in granular details, what tri bikes fit you perfectly.
    • +
    +

    Some of these activations are available by appointment only. Choose your Road Show, and then choose your appointment (not all special activations and appointments are published; return as your Road Show approaches to make your appointment if it's not listed yet).

    +

    Visit our Slowtwitch Road Show Facebook page for updates, including itineraries for the Road Show in your townn.

    + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/roadshow/individual.php b/site/roadshow/individual.php new file mode 100644 index 0000000..8985c2c --- /dev/null +++ b/site/roadshow/individual.php @@ -0,0 +1,622 @@ + + + + + + + +
    + +
    +
    + + +
    + +
    +
    +
    +

    Road Show

    +
    +
    +

    + +

    Editor: your changes have been submitted and will be validated within 24 hours.

    + + + +

    Group Edits: there are group edits waiting to be validated.

    + + + +
    + + Date: format('Y-m-d'); ?>
    + Time: format('g:i A'); ?>
    + Street Address:
    + "") { + echo("Street Address Two:"); + echo stripslashes(htmlspecialchars($row[$field_lead.'address_two'])); + echo("
    "); + } ?> + City:
    + State:
    + Zip/Postal Code: +
    +
    + Phone:
    + E-mail:
    + + Shop Website: $website"; ?> +
    +
    + + + Raffle Link: $raffle"; ?>
    + RSVP on Facebook: $facebook"; ?> + + +
    +
    + + +
    +
    +

    Appointment Only Services

    +
    +

    Saddle Optimizer: Rides several saddles back-to-back on stationary equipment built for the purpose

    +

    Complete Bike Solver: Discover, in granular details, what tri bikes fit you perfectly.

    +
    +

    Brands

    +
    + "") { + echo "
    Triathlon Apparel: "; + echo $temp_list; + } + + $temp_list = ""; + + ?> + + "") { + echo "
    Bike(s): "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Bike Saddles/Footwear/Aerobars/Bike Hydration: + "; + echo $temp_list; + } + + $temp_list = ""; + + ?> + + "") { + echo "
    Bike Helmets/Eyewear: "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Bike Nutritionals/Lubricants/Botanicals: "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Bike Stationary Trainer(s): "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Bike Electronics/Cameras/Metrics: "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Bike Wheels/Tires: "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Bike Component(s): "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Sock(s): "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Running Shoe(s): "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Run Apparel: "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Run Hydration: "; + echo $temp_list; + } + + + echo $temp_list; + + $temp_list = ""; + + ?> + + "") { + echo "
    Wetsuit(s): "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Swim Apparel/Gear: "; + echo $temp_list; + } + + + $temp_list = ""; + + ?> + + "") { + echo "
    Bodycare Tools: "; + echo $temp_list; + } + + $temp_list = ""; + + ?> +
    +

    Road Show Itinerary

    +
    +

    Itinerary:

    +
    + +
    + +
    +
    +
    + Map location is based off of a geocode of the addressed entered using Google's Google Maps API. If your address does not geocode properly, you can either update the address (we will attempt to re-geocode after any updates to your entry) or you can use Google's geocoding tool found here: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html to obtain a lat/long for your location and enter that. To use the utility, type in an address that is close to your location and then drag-and-drop the marker to obtain the desired lat/long. If you choose to enter a lat/long, you must check the box on the edit page that says, "override geocode with entered lat/long." +
    +
    +
    + + + "; + ?> +

    +
    + 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i > 1){ echo ", "; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username]"; + // TODO: SLOWTWITCH EDIT END + } + $i++; + } + if(count($tags) <= 1){ echo "No users"; } + ?> +
    +
    +
    + + + "; + ?> +

    +
    + = 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i >= 1){ echo "
    "; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + // TODO: SLOWTWITCH EDIT END + } + $i++; + } + if($numcount <= 0){ echo "No users"; } + ?> +
    +
    +
    +
    + + + + + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/roadshow/logout.php b/site/roadshow/logout.php new file mode 100644 index 0000000..4b855d2 --- /dev/null +++ b/site/roadshow/logout.php @@ -0,0 +1,7 @@ + diff --git a/site/roadshow/masterbrands.php b/site/roadshow/masterbrands.php new file mode 100644 index 0000000..3c53fd1 --- /dev/null +++ b/site/roadshow/masterbrands.php @@ -0,0 +1,520 @@ + + + + + + +
    + + +
    + + + + + +BRANDS LISTED BY POPULARITY OF SELECTION
    + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_fitbike) AS brand_count FROM gforum_Roadshow WHERE roadshow_fitbike LIKE '%,".$arr_row[fitbike_id]."' OR roadshow_fitbike LIKE '%,".$arr_row[fitbike_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[fitbike_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[fitbike_name]"] == "" OR $holder_array["$arr_row[fitbike_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[fitbike_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "FITBIKE - $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_saddlechange) AS brand_count FROM gforum_Roadshow WHERE roadshow_saddlechange LIKE '%,".$arr_row[saddlechange_id]."' OR roadshow_saddlechange LIKE '%,".$arr_row[saddlechange_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[saddlechange_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[saddlechange_name]"] == "" OR $holder_array["$arr_row[saddlechange_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[saddlechange_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "SADDLE CHANGE - $key: $val
    "; +}**/ + + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_motioncapture) AS brand_count FROM gforum_Roadshow WHERE roadshow_motioncapture LIKE '%,".$arr_row[motioncapture_id]."' OR roadshow_motioncapture LIKE '%,".$arr_row[motioncapture_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[motioncapture_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[motioncapture_name]"] == "" OR $holder_array["$arr_row[motioncapture_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[motioncapture_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "MOTION CAPTURE - $key: $val
    "; +}**/ + + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_footbed) AS brand_count FROM gforum_Roadshow WHERE roadshow_footbed LIKE '%,".$arr_row[footbed_id]."' OR roadshow_footbed LIKE '%,".$arr_row[footbed_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[footbed_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[footbed_name]"] == "" OR $holder_array["$arr_row[footbed_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[footbed_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "CUSTOM FOOTBED - $key: $val
    "; +}**/ + +?> + + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_apparel_tri) AS brand_count FROM gforum_Roadshow WHERE roadshow_apparel_tri LIKE '%,".$arr_row[apparel_tri_id]."' OR roadshow_apparel_tri LIKE '%,".$arr_row[apparel_tri_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[apparel_tri_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[apparel_tri_name]"] == "" OR $holder_array["$arr_row[apparel_tri_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[apparel_tri_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "APPAREL TRI - $key: $val
    "; +}**/ + +?> + + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_bike) AS brand_count FROM gforum_Roadshow WHERE roadshow_bike LIKE '%,".$arr_row[bike_id]."' OR roadshow_bike LIKE '%,".$arr_row[bike_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[bike_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[bike_name]"] == "" OR $holder_array["$arr_row[bike_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[bike_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "BIKES - $key: $val
    "; +}**/ + + +?> + + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_bikeaccessory) AS brand_count FROM gforum_Roadshow WHERE roadshow_bikeaccessory LIKE '%,".$arr_row[bikeaccessory_id]."' OR roadshow_bikeaccessory LIKE '%,".$arr_row[bikeaccessory_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[bikeaccessory_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[bikeaccessory_name]"] == "" OR $holder_array["$arr_row[bikeaccessory_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[bikeaccessory_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "ACCESSORY $key: $val
    "; +}**/ + +?> + + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_bikehelmet) AS brand_count FROM gforum_Roadshow WHERE roadshow_bikehelmet LIKE '%,".$arr_row[bikehelmet_id]."' OR roadshow_bikehelmet LIKE '%,".$arr_row[bikehelmet_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[bikehelmet_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[bikehelmet_name]"] == "" OR $holder_array["$arr_row[bikehelmet_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[bikehelmet_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "HELMET $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_bikebodycare) AS brand_count FROM gforum_Roadshow WHERE roadshow_bikebodycare LIKE '%,".$arr_row[bikebodycare_id]."' OR roadshow_bikebodycare LIKE '%,".$arr_row[bikebodycare_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[bikebodycare_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[bikebodycare_name]"] == "" OR $holder_array["$arr_row[bikebodycare_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[bikebodycare_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "BODYCARE $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_biketrainer) AS brand_count FROM gforum_Roadshow WHERE roadshow_biketrainer LIKE '%,".$arr_row[biketrainer_id]."' OR roadshow_biketrainer LIKE '%,".$arr_row[biketrainer_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[biketrainer_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[biketrainer_name]"] == "" OR $holder_array["$arr_row[biketrainer_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[biketrainer_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "TRAINER $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_bikeelectronic) AS brand_count FROM gforum_Roadshow WHERE roadshow_bikeelectronic LIKE '%,".$arr_row[bikeelectronic_id]."' OR roadshow_bikeelectronic LIKE '%,".$arr_row[bikeelectronic_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[bikeelectronic_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[bikeelectronic_name]"] == "" OR $holder_array["$arr_row[bikeelectronic_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[bikeelectronic_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "ELECTRONIC $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_bikewheel) AS brand_count FROM gforum_Roadshow WHERE roadshow_bikewheel LIKE '%,".$arr_row[bikewheel_id]."' OR roadshow_bikewheel LIKE '%,".$arr_row[bikewheel_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[bikewheel_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[bikewheel_name]"] == "" OR $holder_array["$arr_row[bikewheel_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[bikewheel_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "WHEEL $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_bikecomponent) AS brand_count FROM gforum_Roadshow WHERE roadshow_bikecomponent LIKE '%,".$arr_row[bikecomponent_id]."' OR roadshow_bikecomponent LIKE '%,".$arr_row[bikecomponent_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[bikecomponent_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[bikecomponent_name]"] == "" OR $holder_array["$arr_row[bikecomponent_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[bikecomponent_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "COMPONENT $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_sock) AS brand_count FROM gforum_Roadshow WHERE roadshow_sock LIKE '%,".$arr_row[sock_id]."' OR roadshow_sock LIKE '%,".$arr_row[sock_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[sock_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[sock_name]"] == "" OR $holder_array["$arr_row[sock_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[sock_name]"] = $list_row[brand_count]; + } + } +} + +/**foreach ($holder_array as $key => $val) { + echo "SOCK $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_shoe) AS brand_count FROM gforum_Roadshow WHERE roadshow_shoe LIKE '%,".$arr_row[shoe_id]."' OR roadshow_shoe LIKE '%,".$arr_row[shoe_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[shoe_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[shoe_name]"] == "" OR $holder_array["$arr_row[shoe_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[shoe_name]"] = $list_row[brand_count]; + } + } +} + + +/**foreach ($holder_array as $key => $val) { + echo "SHOE $key: $val
    "; +}**/ + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_apparel_run) AS brand_count FROM gforum_Roadshow WHERE roadshow_apparel_run LIKE '%,".$arr_row[apparel_run_id]."' OR roadshow_apparel_run LIKE '%,".$arr_row[apparel_run_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[apparel_run_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[apparel_run_name]"] == "" OR $holder_array["$arr_row[apparel_run_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[apparel_run_name]"] = $list_row[brand_count]; + } + } +} + + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_runhydrate) AS brand_count FROM gforum_Roadshow WHERE roadshow_runhydrate LIKE '%,".$arr_row[runhydrate_id]."' OR roadshow_runhydrate LIKE '%,".$arr_row[runhydrate_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[runhydrate_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[runhydrate_name]"] == "" OR $holder_array["$arr_row[runhydrate_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[runhydrate_name]"] = $list_row[brand_count]; + } + } +} + + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_wetsuit) AS brand_count FROM gforum_Roadshow WHERE roadshow_wetsuit LIKE '%,".$arr_row[wetsuit_id]."' OR roadshow_wetsuit LIKE '%,".$arr_row[wetsuit_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[wetsuit_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[wetsuit_name]"] == "" OR $holder_array["$arr_row[wetsuit_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[wetsuit_name]"] = $list_row[brand_count]; + } + } +} + + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_swimgear) AS brand_count FROM gforum_Roadshow WHERE roadshow_swimgear LIKE '%,".$arr_row[swimgear_id]."' OR roadshow_swimgear LIKE '%,".$arr_row[swimgear_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[swimgear_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[swimgear_name]"] == "" OR $holder_array["$arr_row[swimgear_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[swimgear_name]"] = $list_row[brand_count]; + } + } +} + + +?> + + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_bodycare) AS brand_count FROM gforum_Roadshow WHERE roadshow_bodycare LIKE '%,".$arr_row[bodycare_id]."' OR roadshow_bodycare LIKE '%,".$arr_row[bodycare_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[bodycare_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[bodycare_name]"] == "" OR $holder_array["$arr_row[bodycare_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[bodycare_name]"] = $list_row[brand_count]; + } + } +} + + +?> + +"; +$arr_results = mysql_query($sql_one); +while ($arr_row = mysql_fetch_array($arr_results)) { + $sql_two = "SELECT COUNT(roadshow_diagnostic) AS brand_count FROM gforum_Roadshow WHERE roadshow_diagnostic LIKE '%,".$arr_row[diagnostic_id]."' OR roadshow_diagnostic LIKE '%,".$arr_row[diagnostic_id].",%'"; + // echo $sql_two."
    "; + $list_results = mysql_query($sql_two); + while ($list_row = mysql_fetch_array($list_results)) { + //echo $arr_row[diagnostic_name].": ".$list_row[brand_count]."
    "; + if ($holder_array["$arr_row[diagnostic_name]"] == "" OR $holder_array["$arr_row[diagnostic_name]"] < $list_row[brand_count]) { + $holder_array["$arr_row[diagnostic_name]"] = $list_row[brand_count]; + } + } +} + +arsort($holder_array); +foreach ($holder_array as $key => $val) { + echo "$key: $val
    "; +} +unset ($holder_array); + +?> + +
    + + + +
    + + + +
    + +
    + + + + diff --git a/site/roadshow/phpsqlgeocode_csv.php b/site/roadshow/phpsqlgeocode_csv.php new file mode 100644 index 0000000..56df024 --- /dev/null +++ b/site/roadshow/phpsqlgeocode_csv.php @@ -0,0 +1,85 @@ += 5) { + // successful geocode + $geocode_pending = false; + $lat = $csvSplit[2]; + $lng = $csvSplit[3]; + + $query = sprintf("UPDATE gforum_OpenWater " . + " SET openwater_lat = '%s', openwater_lng = '%s' " . + " WHERE openwater_id = %s LIMIT 1;", + mysql_real_escape_string($lat), + mysql_real_escape_string($lng), + mysql_real_escape_string($id)); + $update_result = mysql_query($query); + if (!$update_result) { + die("Invalid query: " . mysql_error()); + } + } else if (strcmp($status, "620") == 0) { + // sent geocodes too fast + $delay += 100000; + } else if ($accuracy < 5) { + // failure to geocode + $geocode_pending = false; + echo "Address " . $address . " did not geocode to great enough accuracy to be useful. "; + echo "Accuracy match: " . $accuracy . " +\n"; + } else { + // failure to geocode + $geocode_pending = false; + echo "Address " . $address . " failed to geocode. "; + echo "Received status " . $status . " +\n"; + } + usleep($delay); + } +} +?> diff --git a/site/roadshow/rating/ajax.rate.item.php b/site/roadshow/rating/ajax.rate.item.php new file mode 100644 index 0000000..38c90de --- /dev/null +++ b/site/roadshow/rating/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/roadshow/rating/classes/database.class.php b/site/roadshow/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/roadshow/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/roadshow/rating/classes/error.class.php b/site/roadshow/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/roadshow/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Error Template Output + $output = "
    \r\n" . + "
    {$error}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Warning Template Output + $output = "
    \r\n" . + "
    {$warning}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/roadshow/rating/classes/include.all.php b/site/roadshow/rating/classes/include.all.php new file mode 100644 index 0000000..95a5d46 --- /dev/null +++ b/site/roadshow/rating/classes/include.all.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/site/roadshow/rating/classes/rating.class.php b/site/roadshow/rating/classes/rating.class.php new file mode 100644 index 0000000..ed458d6 --- /dev/null +++ b/site/roadshow/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +{$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
    {$cat_info['rating_cat_name']}
    "; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
    Overall Rating
    "; + $output .= "
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    \r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_FittersRating` (`rating_fitter_id`, `rating_category_id`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_FittersRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_FittersRating` WHERE `rating_category_id`='{$varItem}' AND `rating_fitter_id`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_FittersRating` WHERE `rating_fitter_id`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_FittersRating` WHERE `rating_category_id`='{$varItem}' AND `rating_fitter_id`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> \ No newline at end of file diff --git a/site/roadshow/rating/int.to.words.php b/site/roadshow/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/roadshow/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/roadshow/rating/rating-example.php b/site/roadshow/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/roadshow/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

    Race Rating System:

    + + + + + + + \ No newline at end of file diff --git a/site/roadshow/regionlist.php b/site/roadshow/regionlist.php new file mode 100644 index 0000000..b1bdd25 --- /dev/null +++ b/site/roadshow/regionlist.php @@ -0,0 +1,99 @@ + + + + + + +
    + + +
    + + + + + +

    +
    + + + +"> + +"> + + +"> + + + +"> + + + + +

    ">
    Address: ".$row[''.$field_lead.'address_two'].""); + } + echo("
    ".$row[''.$field_lead.'city'].", ".$row[''.$field_lead.'state']." ".$row[''.$field_lead.'zip'].""); + ?> +
    ".$row[''.$field_lead.'phone']."
    Fax/Alt Phone: ". $row[''.$field_lead.'fax'].""); + ?> +
    +
    + Email: ".$row[''.$field_lead.'email'].""; ?>
    + Website: ".$row[''.$field_lead.'website'].""; ?> +
    + More information"); ?> +

    +
    +
    +
    + + +
    + +
    + + + + diff --git a/site/roadshow/search.php b/site/roadshow/search.php new file mode 100644 index 0000000..6ab7f5a --- /dev/null +++ b/site/roadshow/search.php @@ -0,0 +1,641 @@ + + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Search For A Roadshow Event

    +
    +

    If you would like to search for a roadshow event, please use the form below. None of the fields are mandatory. Checking no box "selects all." Checking regions selects all states in that region. Checking any state's box selects or deselects that state.

    + +

    + +
    +
    +
    +
    Date Override
    +
    +
    + Yes + [overrides keyword search default and allows you to use the date boxes below. Also resets default search to start with today's date.] +
    +
    +
    +
    Start Date
    +
    +
    + + +
    [Leave blank for today's date] +
    +
    +
    +
    End Date
    +
    +
    + + + +
    +
    +
    +
    +
    +
    +

    Local Assets

    +
    +
    +
    +
    Slowtwitch Ambassador(s)
    +
    +
    + Yes +
    +
    +
    +
    Tri Club(s)
    +
    +
    + Yes +
    +
    +
    +
    Coach(es)
    +
    +
    + Yes +
    +
    +
    +
    Race Director(s)
    +
    +
    + Yes +
    +
    +
    +
    Brewery(ies)
    +
    +
    + Yes +
    +
    +
    +
    Fit Bikes
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[fitbike_name]\n"); + } + ?> +
    +
    +
    +
    Saddle Quick Change
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[saddlechange_name]\n"); + } + ?> +
    +
    +
    +
    Motion Capture Systems
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[motioncapture_name]\n"); + } + ?> +
    +
    +
    +
    Custom Footbeds
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[footbed_name]\n"); + } + ?> +
    +
    +
    +
    +
    +
    +

    Brands

    +
    +
    +
    +
    Tri Apparel
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[apparel_tri_name]\n"); + } + ?> +
    +
    +
    +
    Bike Brands
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bike_name]\n"); + } + + ?> +
    +
    +
    +
    Bike Saddles/Footwear/Aerobars/Bike Hydration
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikeaccessory_name]\n"); + } + ?> +
    +
    +
    +
    Bike Helmets/Eyewear
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikehelmet_name]\n"); + } + + ?> +
    +
    +
    +
    Bike Nutritionals/Lubricants/Botanicals
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikebody_name]\n"); + } + + ?> +
    +
    +
    +
    Bike Stationary Trainers
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("$row[biketrainer_name]\n"); + $i++; +} +if(!($i%4)) echo ""; +echo("ANY +"); +echo(""); + + ?> +
    +
    +
    +
    Bike Electronics/Cameras/Metrics
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikeelectronic_name]\n"); + } + ?> +
    +
    +
    +
    Bike Wheels/Tires
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikewheel_name]\n"); + } + ?> +
    +
    +
    +
    Bike Components
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikecomponent_name]\n"); + } + ?> +
    +
    +
    +
    Socks
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[sock_name]\n"); + } + ?> +
    +
    +
    +
    Running Shoes
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[shoe_name]\n"); + } + ?> +
    +
    +
    +
    Run Apparel
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[apparel_run_name]\n"); + } + ?> +
    +
    +
    +
    Run Hydration
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[runhydrate_name]\n"); + } + ?> +
    +
    +
    +
    Wetsuits
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[wetsuit_name]\n"); + } + ?> +
    +
    +
    +
    Swim Apparel/Gear
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[swimgear_name]\n"); + } + + ?> +
    +
    +
    +
    Body Care Tools
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bodycare_name]\n"); + } + + ?> +
    +
    +
    +
    +
    +
    +

    Technology, Community & Education

    +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + Yes +
    +
    +
    +
    Diagnostic Equipment
    +
    +
    + ANY

    "); + while ($row = mysql_fetch_array($results)) { + echo("$row[diagnostic_name]\n"); + } + + ?> +
    +
    +
    +
    Region
    +
    +
    +

    [Selecting a region will select all states in that region. You can then deselect or select any additional states. Only the selected states will be included in your search. Leaving all boxes blank will select races in all states.]

    + $statetag) { + echo("$region\n"); + $i++; + +} +?> + +
    +
    +
    +
    State
    +
    +
    + $row[statelong]\n"; +} +?> +

    [Leave blank to select all.]

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/roadshow/search_X.php b/site/roadshow/search_X.php new file mode 100644 index 0000000..b9ea7d4 --- /dev/null +++ b/site/roadshow/search_X.php @@ -0,0 +1,517 @@ + '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[fitbike] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_fitbike LIKE '%,$value' OR roadshow_fitbike LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[fitbike] AS $value) { + $sql = $sql." AND roadshow_fitbike LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[saddlechange])) { + if (in_array("999", $_POST[saddlechange])) { + $sql = $sql." AND roadshow_saddlechange <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[saddlechange] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_saddlechange LIKE '%,$value' OR roadshow_saddlechange LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[saddlechange] AS $value) { + $sql = $sql." AND roadshow_saddlechange LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[motioncapture])) { + if (in_array("999", $_POST[motioncapture])) { + $sql = $sql." AND roadshow_motioncapture <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[motioncapture] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_motioncapture LIKE '%,$value' OR roadshow_motioncapture LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[motioncapture] AS $value) { + $sql = $sql." AND roadshow_motioncapture LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[footbed])) { + if (in_array("999", $_POST[footbed])) { + $sql = $sql." AND roadshow_footbed <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[footbed] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_footbed LIKE '%,$value' OR roadshow_footbed LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[footbed] AS $value) { + $sql = $sql." AND roadshow_footbed LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[wetsuit])) { + if (in_array("999", $_POST[wetsuit])) { + $sql = $sql." AND roadshow_wetsuit <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[wetsuit] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_wetsuit LIKE '%,$value' OR roadshow_wetsuit LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[wetsuit] AS $value) { + $sql = $sql." AND roadshow_wetsuit LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[bike])) { + if (in_array("999", $_POST[bike])) { + $sql = $sql." AND roadshow_bike <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[bike] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql."roadshow_bike LIKE '%,$value' OR roadshow_bike LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bike] AS $value) { + $sql = $sql." AND roadshow_bike LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[diagnostic])) { + if (in_array("999", $_POST[diagnostic])) { + $sql = $sql." AND roadshow_diagnostic <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[diagnostic] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_diagnostic LIKE '%,$value' OR roadshow_diagnostic LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[diagnostic] AS $value) { + $sql = $sql." AND roadshow_diagnostic LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[shoe])) { + if (in_array("999", $_POST[shoe])) { + $sql = $sql." AND roadshow_shoe <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[shoe] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_shoe LIKE '%,$value' OR roadshow_shoe LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[shoe] AS $value) { + $sql = $sql." AND roadshow_shoe LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[sock])) { + if (in_array("999", $_POST[sock])) { + $sql = $sql." AND roadshow_sock <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[sock] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_sock LIKE '%,$value' OR roadshow_sock LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[sock] AS $value) { + $sql = $sql." AND roadshow_sock LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[apparel_run])) { + if (in_array("999", $_POST[apparel_run])) { + $sql = $sql." AND roadshow_apparel_run <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[apparel_run] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_apparel_run LIKE '%,$value' OR roadshow_apparel_run LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[apparel_run] AS $value) { + $sql = $sql." AND roadshow_apparel_run LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[apparel_tri])) { + if (in_array("999", $_POST[apparel_tri])) { + $sql = $sql." AND roadshow_apparel_tri <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[apparel_tri] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_apparel_tri LIKE '%,$value' OR roadshow_apparel_tri LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[apparel_tri] AS $value) { + $sql = $sql." AND roadshow_apparel_tri LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[swimgear])) { + if (in_array("999", $_POST[swimgear])) { + $sql = $sql." AND roadshow_swimgear <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[swimgear] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_swimgear LIKE '%,$value' OR roadshow_swimgear LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[swimgear] AS $value) { + $sql = $sql." AND roadshow_swimgear LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[bikeaccessory])) { + if (in_array("999", $_POST[bikeaccessory])) { + $sql = $sql." AND roadshow_bikeaccessory <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[bikeaccessory] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_bikeaccessory LIKE '%,$value' OR roadshow_bikeaccessory LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bikeaccessory] AS $value) { + $sql = $sql." AND roadshow_bikeaccessory LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[bikebody])) { + if (in_array("999", $_POST[bikebody])) { + $sql = $sql." AND roadshow_bikebody <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[bikebody] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_bikebody LIKE '%,$value' OR roadshow_bikebody LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bikebody] AS $value) { + $sql = $sql." AND roadshow_bikebody LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[bikecomponent])) { + if (in_array("999", $_POST[bikecomponent])) { + $sql = $sql." AND roadshow_bikecomponent <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[bikecomponent] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_bikecomponent LIKE '%,$value' OR roadshow_bikecomponent LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bikecomponent] AS $value) { + $sql = $sql." AND roadshow_bikecomponent LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[bikeelectronic])) { + if (in_array("999", $_POST[bikeelectronic])) { + $sql = $sql." AND roadshow_bikeelectronic <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[bikeelectronic] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_bikeelectronic LIKE '%,$value' OR roadshow_bikeelectronic LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bikeelectronic] AS $value) { + $sql = $sql." AND roadshow_bikeelectronic LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[bikehelmet])) { + if (in_array("999", $_POST[bikehelmet])) { + $sql = $sql." AND roadshow_bikehelmet <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[bikehelmet] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_bikehelmet LIKE '%,$value' OR roadshow_bikehelmet LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bikehelmet] AS $value) { + $sql = $sql." AND roadshow_bikehelmet LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[biketrainer])) { + if (in_array("999", $_POST[biketrainer])) { + $sql = $sql." AND roadshow_biketrainer <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[biketrainer] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_biketrainer LIKE '%,$value' OR roadshow_biketrainer LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[biketrainer] AS $value) { + $sql = $sql." AND roadshow_biketrainer LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[bikewheel])) { + if (in_array("999", $_POST[bikewheel])) { + $sql = $sql." AND roadshow_bikewheel <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[bikewheel] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_bikewheel LIKE '%,$value' OR roadshow_bikewheel LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bikewheel] AS $value) { + $sql = $sql." AND roadshow_bikewheel LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[runhydrate])) { + if (in_array("999", $_POST[runhydrate])) { + $sql = $sql." AND roadshow_runhydrate <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[runhydrate] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_runhydrate LIKE '%,$value' OR roadshow_runhydrate LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[runhydrate] AS $value) { + $sql = $sql." AND roadshow_runhydrate LIKE '%,$value,%'"; + }**/} +} +if (isset($_POST[bodycare])) { + if (in_array("999", $_POST[bodycare])) { + $sql = $sql." AND roadshow_bodycare <> '0'"; + } else { + $sql = $sql." AND ( "; + $flag = 0; + foreach ($_POST[bodycare] AS $value) { + if ($flag == 1){ + $sql = $sql." OR "; + } + $sql = $sql." roadshow_bodycare LIKE '%,$value' OR roadshow_bodycare LIKE '%,$value,%'"; + $flag = 1; + } + $sql = $sql.")"; + /**foreach ($_POST[bodycare] AS $value) { + $sql = $sql." AND roadshow_bodycare LIKE '%,$value,%'"; + }**/} +} + +// add date range +if (isset($_POST['futuredates']) OR $_POST['keyword'] == "") { + if ($_POST[aftermonth] != 0 AND $_POST[afterday] != 0) { + $afterdate = "$_POST[afteryear]-$_POST[aftermonth]-$_POST[afterday]"; + $sql = $sql." AND date >= '$afterdate'"; } + else { $sql = $sql." AND ".$field_lead."date >= NOW()"; } + if ($_POST[beforemonth] != 0 AND $_POST[beforeday] != 0) { + $beforedate = "$_POST[beforeyear]-$_POST[beforemonth]-$_POST[beforeday]"; + $sql = $sql." AND ".$field_lead."date <= '$beforedate'"; + } +} else { + $last_year = time() - 365*24*60*60; + $sql = $sql." AND date >= '".date('Y-m-d', $last_year)."'"; +} + +// regions are checkboxes that then check off all states within that region +// add states +if (isset($_POST[states])) { + $glue = "','"; + $statelist = "('".implode($glue, $_POST[states])."')"; + $sql = $sql." AND ".$field_lead."state_tag IN $statelist"; +} + +$sql = $sql." ORDER BY ".$field_lead."date ASC"; + +//echo $sql; +//exit(); + +$results = mysql_query($sql); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} +$race_count = mysql_num_rows($results); + + +// set the page title +$pagetitle = "Search Results"; + +// set meta tags +$meta_keywords = "roadshow events in matching a user's search query."; +$meta_description = "A list of matching roadshow events."; +?> + + + + + +
    + +
    +
    + + +
    + + +
    +
    +

    Roadshow Events Match Your Search

    +
    + No races match your search

    "; + } + ?> + + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/roadshow/statelist.php b/site/roadshow/statelist.php new file mode 100644 index 0000000..47e7300 --- /dev/null +++ b/site/roadshow/statelist.php @@ -0,0 +1,101 @@ + + + + + + +
    + + +
    + + + + + +

    +
    + + + +"> + +"> + + +"> + + + +"> + + + + +

    ">
    Address: ".$row[''.$field_lead.'address_two'].""); + } + echo("
    ".$row[''.$field_lead.'city'].", ".$row[''.$field_lead.'state']." ".$row[''.$field_lead.'zip'].""); + ?> +
    ".$row[''.$field_lead.'phone']."
    Fax/Alt Phone: ". $row[''.$field_lead.'fax'].""); + ?> +
    +
    + Email: ".$row[''.$field_lead.'email'].""; ?>
    + Website: ".$row[''.$field_lead.'website'].""; ?> +
    + More information"); ?> +

    +
    +
    +
    + + +
    + +
    + + + + diff --git a/site/roadshow/top.php b/site/roadshow/top.php new file mode 100644 index 0000000..06d4f86 --- /dev/null +++ b/site/roadshow/top.php @@ -0,0 +1,103 @@ + 10 ORDER BY score DESC, votes DESC LIMIT 10") OR die(mysql_error()); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} + +// set the page title +$pagetitle = "Top Bike Fitters"; + +// set meta tags +$meta_keywords = "top ranked open water events"; +$meta_description = "Top ranked open water events based on rankings submitted by the user."; +?> + + + + + +
    + + +
    + + + + + +

    Top Ranked Open Water Events

    +
    + + + +"> + +"> + +"> +"> +"> + +

    ">
    (Avg. rating based on )
    +
    +
    +
    +");} + +if (fist_equipped($row[openwater_id]) == "super_fist") { echo("
    ");} + +?> +
    Address: $row[openwater_address_two]"); } echo("
    $row[openwater_city], $row[openwater_state] $row[openwater_zip]"); ?>
    +$row[openwater_phone]
    Fax/Alt Phone: $row[openwater_fax]"; + +?> +
    +Email: $row[openwater_email]"; ?>
    +Website: $row[openwater_website]"; ?> +
    +">More information +

    +
    + + + +
    + +
    + + + + diff --git a/site/roadshow/validate.php b/site/roadshow/validate.php new file mode 100644 index 0000000..ff226dc --- /dev/null +++ b/site/roadshow/validate.php @@ -0,0 +1,118 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    +

    Unvalidated

    +
    + There are no ".$local_name_lc." waiting to be validated.

    "; + } + ?> +
    + +
    +
    Name
    +
    +
    + "> +
    +
    +
    +
    Address
    +
    +
    + ".$row[''.$field_lead.'address_two']); + } + echo("
    ".$row[''.$field_lead.'city'].", ".$row[''.$field_lead.'state']." ".$row[''.$field_lead.'zip']); + ?> +
    +
    +
    +
    Phone
    +
    +
    + Fax/Alt Phone: ". $row[''.$field_lead.'fax'].""); + ?> +
    +
    +
    +
    E-mail
    +
    +
    + ".$row[''.$field_lead.'email'].""; ?> +
    +
    +
    +
    Website
    +
    +
    + ".$row[''.$field_lead.'website'].""; ?> +
    +
    +
    +
    +
    +
    + Validate this . Delete this . +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/roadshow/validate_X.php b/site/roadshow/validate_X.php new file mode 100644 index 0000000..7f42508 --- /dev/null +++ b/site/roadshow/validate_X.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/site/roadshow/wiki_buttons.php b/site/roadshow/wiki_buttons.php new file mode 100644 index 0000000..20557f3 --- /dev/null +++ b/site/roadshow/wiki_buttons.php @@ -0,0 +1,20 @@ + + +

    +

    + + +
    + +
    + + +
    + +

    diff --git a/site/roadshow/wiki_edit.php b/site/roadshow/wiki_edit.php new file mode 100644 index 0000000..c77d683 --- /dev/null +++ b/site/roadshow/wiki_edit.php @@ -0,0 +1,1835 @@ +format('m'); + $day = $datetime->format('d'); + $year = $datetime->format('Y'); + $hour = $datetime->format('h'); + $minute = $datetime->format('i'); + $ampm = $datetime->format('A'); +} + + + +//Get user's session data information +$username = base64_decode($_SESSION['user']); +$useruid = base64_decode($_SESSION['user_id']); + +if ( !is_admin() || $eventrow[roadshow_valid] != 1 ) { + header('Location: '.$site_url.'/?error=roadshow_not_valid&'); + exit(); +} + +// set the page title +$pagetitle = "Edit A Roadshow Event"; + +// set meta tags +$meta_keywords = "edit a roadshow event"; +$meta_description = "edit screen for roadshow event information"; + +?> + + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + +

    Edit an Roadshow Event: Step 2 of 2

    + +

    Edit an Roadshow Event: Step 1 of 2

    + +

    To edit a roadshow event, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes as a NEW roadshow event (for instance, if you have multiple occurences), hit the "SAVE AS A NEW ROADSHOW EVENT" button. To save changes to the existing roadshow event entry, hit the "SAVE CHANGES TO YOUR ROADSHOW EVENT" button. You will have a chance to review the data before confirming. You will then be prompted to confirm your information before the information is sent to us.

    + +

    + + +
    +
    +
    +
    Name
    +
    +
    + +
    +
    +
    +
    Event Date
    +
    +
    + + + +
    +
    +
    +
    Start Time
    +
    +
    + + : + + +
    +
    +
    +
    Street Address
    +
    +
    + +
    +
    +
    +
    Street Address Two (optional)
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    Override Address With Lat/Lng
    +
    +
    + > Check this if you know your physical address doesn't geocode properly using Google's API. Then enter the desired lat/lng in the boxes below. +
    +
    +
    +
    Latitude
    +
    +
    + +
    +
    +
    +
    Longitude
    +
    +
    + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax/Alternate Phone
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website (including http://)
    +
    +
    + +
    +
    +
    +
    Raffle Link
    +
    +
    + +
    +
    +
    +
    Facebook Event Page
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Local Assets

    +
    +
    +
    +
    Slowtwitch Ambassador(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Tri Club(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Coach(es)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Race Director(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Brewery(ies)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Other
    +
    +
    + +
    +
    +
    +
    Fit Bikes
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[fitbike_name]\n"); + } + ?> +
    +
    +
    +
    Saddle Quick Change
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[saddlechange_name]\n"); + } + ?> +
    +
    +
    +
    Custom Footbeds
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[footbed_name]\n"); + } + ?> +
    +
    +
    +
    +
    +
    +

    Brands

    +
    +
    +
    +
    Tri Apparel
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[apparel_tri_name]\n"); + } + ?> +
    +
    +
    +
    Bike Brands
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bike_name]\n"); + } + ?> +
    +
    +
    +
    Bike Saddles/Footwear/Aerobars/Bike Hydration
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikeaccessory_name]\n"); + } + ?> +
    +
    +
    +
    Bike Helmets/Eyewear
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikehelmet_name]\n"); + } + ?> +
    +
    +
    +
    Bike Nutritionals/Lubricants/Botanicals
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikebody_name]\n"); + } + ?> +
    +
    +
    +
    Bike Stationary Trainers
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[biketrainer_name]\n"); + } + ?> +
    +
    +
    +
    Bike Electronics/Cameras/Metrics
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikeelectronic_name]\n"); + } + ?> +
    +
    +
    +
    Bike Wheels/Tires
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikewheel_name]\n"); + } + ?> +
    +
    +
    +
    Bike Components
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bikecomponent_name]\n"); + } + ?> +
    +
    +
    +
    Socks
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[sock_name]\n"); + } + ?> +
    +
    +
    +
    Running Shoes
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[shoe_name]\n"); + } + ?> +
    +
    +
    +
    Run Apparel
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[apparel_run_name]\n"); + } + ?> +
    +
    +
    +
    Run Hydration
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[runhydrate_name]\n"); + } + ?> +
    +
    +
    +
    Wetsuits
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[wetsuit_name]\n"); + } + ?> +
    +
    +
    +
    Swim Apparel/Gear
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[swimgear_name]\n"); + } + ?> +
    +
    +
    +
    Body Care Tools
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[bodycare_name]\n"); + } + ?> +
    +
    +
    +
    +
    +
    +

    Technology, Community & Education

    +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    F.I.S.T. Tri Fitters(s)
    +
    +
    + >None + >Yes, Their Names: + + +
    +
    +
    +
    Diagnostic Equipment
    +
    +
    + "); + while ($row = mysql_fetch_array($results)) { + echo("$row[diagnostic_name]\n"); + } + ?> +
    +
    +
    +
    +
    +
    +

    Social

    +
    +
    +
    +
    Shop Hours
    +
    +
    + +
    +
    +
    +
    Runs & Classes
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + +
    +
    + + +

    Please confirm your information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your information before submitting.

    + +

    +
    +
    +
    Name
    +
    +
    + + = 50) { + if ($i == false) { + echo ("Duplicate Alert:"); + } + if ($i == true) {echo ("
    ");} + echo ("".$match_row['roadshow_name']." (".$match_row['roadshow_city'].", ".$match_row['roadshow_state'].") (Similarity: ".(round($percent, 0))."%)"); + } + } + } + ?> +
    +
    +
    +
    Date
    +
    +
    + +
    +
    +
    +
    Time
    +
    +
    + +
    +
    +
    +
    Street Address
    +
    +
    + +
    +
    +
    +
    Street Address Two
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    Lat/Lng
    +
    +
    + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax/Alternate Phone
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    Raffle Link
    +
    +
    + +
    +
    +
    +
    Facebook Event Page
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Local Assets

    +
    +
    +
    +
    Slowtwitch Ambassador(s)
    +
    +
    + +
    +
    +
    +
    Tri Club(s)
    +
    +
    + +
    +
    +
    +
    Coach(es)
    +
    +
    + +
    +
    +
    +
    Race Director(s)
    +
    +
    + +
    +
    +
    +
    Brewery(ies)
    +
    +
    + +
    +
    +
    +
    Other
    +
    +
    + +
    +
    +
    +
    Fitbike(s)
    +
    +
    + +
    +
    +
    +
    Saddle Quick Change
    +
    +
    + +
    +
    +
    +
    Motion Capture System(s)
    +
    +
    + +
    +
    +
    +
    Custom Footbed(s)
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Brands

    +
    +
    +
    +
    Triathlon Apparel
    +
    +
    + +
    +
    +
    +
    Bike(s)
    +
    +
    + +
    +
    +
    +
    Bike Saddles/Footwear/Aerobars/Bike Hydration
    +
    +
    + +
    +
    +
    +
    Bike Helmets/Eyewear
    +
    +
    + +
    +
    +
    +
    Bike Nutritionals/Lubricants/Botanicals
    +
    +
    + +
    +
    +
    +
    Bike Stationary Trainer(s)
    +
    +
    + +
    +
    +
    +
    Bike Electronics/Cameras/Metrics
    +
    +
    + +
    +
    +
    +
    Bike Wheels/Tires
    +
    +
    + +
    +
    +
    +
    Bike Component(s)
    +
    +
    + +
    +
    +
    +
    Sock(s)
    +
    +
    + +
    +
    +
    +
    Running Shoe(s)
    +
    +
    + +
    +
    +
    +
    Run Apparel
    +
    +
    + +
    +
    +
    +
    Run Hydration
    +
    +
    + +
    +
    +
    +
    Wetsuit(s)
    +
    +
    + +
    +
    +
    +
    Swim Apparel/Gear
    +
    +
    + +
    +
    +
    +
    Bodycare Tools
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Technology, Community & Education

    +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Tri Fitters(s)
    +
    +
    + +
    +
    +
    +
    Diagnostic Tools
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Social

    +
    +
    +
    +
    Shop Hours
    +
    +
    + +
    +
    +
    +
    General Info & Notes
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    This data will be saved as a NEW ROADSHOW EVENT.

    + + + +

    This data will be saved as a modification to the
    EXISTING ROADSHOW EVENT.

    + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + + + +
    +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/roadshow/wiki_edit_X.php b/site/roadshow/wiki_edit_X.php new file mode 100644 index 0000000..e1bd828 --- /dev/null +++ b/site/roadshow/wiki_edit_X.php @@ -0,0 +1,250 @@ +"; + $errmsg = rtrim($errmsg, ", "); +} + +$start_url = "(http(s)?\:\/\/)?"; // start url +$dots = "([\w_-]{2,}\.)+"; // one or more parts containing a '.' at the end +$last_part = "([\w_-]{2,})"; // last part doesn't contain a dot +$user = "((\/)(\~)[\w_=-]+)?((\/)[\w_=-]+)*"; // maybe subdirectories - possibly with user ~ +$end = "((\/)|(\/)[\w_-]+\.[\w]{2,})?"; // maybe a slash at the end or slash+file+extension +$qstring1 = "((\?[\w_-]+\=([^\#]+)){0,1}"; // querystring - first argument (?a=b) +$qstring2 = "(\&[\w_-]+\=([^\#]+))*)?"; // querystring - following arguments (&c=d) +$bkmrk = "(#[\w_-]+)?"; // bookmark + +$exp = "/^".$start_url.$dots.$last_part.$user.$end.$qstring1.$qstring2.$bkmrk."$/i"; +if( !preg_match($exp, $_POST[website]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
    "; +} +if( !preg_match($exp, $_POST[facebook]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
    "; +} +if( !preg_match($exp, $_POST[raffle]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
    "; +} +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[name]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Please use only letters and numbers in the name
    "; +} + +// begin error message check +if(!$errmsg){ + + $name = trim($_POST[name]); + $name_tag = strtolower(str_replace(" ","", $name)); + //if(strlen($name_tag) > 12){ //Shorten it + $name_tag = substr($name_tag, 0, 12); + //} // need to update a typo here in other dbs + $address = mysql_escape_string(trim($_POST[address])); + $full_address = $address; + if (isset($_POST['address_two'])) { $address_two = mysql_escape_string(trim($_POST[address_two])); } else { $address_two = NULL; $full_address = $full_address.", ".$address_two; } + $city = mysql_escape_string(trim($_POST[city])); + $full_address = $full_address.", ".$city; + $state = $_POST[state]; + $full_address = $full_address.", ".$state; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = mysql_escape_string(trim($_POST[zip])); + $full_address = $full_address." ".$zip; + $latlng_override = $_POST[latlng_override]; + if ($latlng_override == true) { + $lat = $_POST[lat]; + $lng = $_POST[lng]; + } else { + //geocode + //echo ($full_address); + $geocode_status = geocode($full_address); + //echo (is_array($geocode_status)); + if (is_array($geocode_status)) { + $geocode_error = false; + $lat = $geocode_status[0]; + $_POST[lat] = $lat; + $lng = $geocode_status[1]; + $_POST[lng] = $lng; + //echo ($lat.", ".$lng); + } else { + $geocode_error = true; + $lat = 0; + $_POST[lat] = $lat; + $lng = 0; + $_POST[lng] = $lng; + $geocode_message = $geocode_status; + } + } + $phone = mysql_escape_string(trim($_POST[phone])); + $fax = mysql_escape_string(trim($_POST[fax])); + $email = mysql_escape_string(trim($_POST[email])); + $website = mysql_escape_string(trim($_POST[website])); + $raffle = mysql_escape_string(trim($_POST[raffle])); + $facebook = mysql_escape_string(trim($_POST[facebook])); + + $stambassador = mysql_escape_string(trim($_POST[stambassador])); + $stambassador_names = mysql_escape_string(trim($_POST[stambassador_names])); + $triclub = mysql_escape_string(trim($_POST[triclub])); + $triclub_names = mysql_escape_string(trim($_POST[triclub_names])); + $coach = mysql_escape_string(trim($_POST[coach])); + $coach_names = mysql_escape_string(trim($_POST[coach_names])); + $racedirector = mysql_escape_string(trim($_POST[racedirector])); + $racedirector_names = mysql_escape_string(trim($_POST[racedirector_names])); + $brewery = mysql_escape_string(trim($_POST[brewery])); + $brewery_names = mysql_escape_string(trim($_POST[brewery_names])); + $local = mysql_escape_string(trim($_POST[local])); + $fitbike = $_POST[fitbike]; + $saddlechange = $_POST[saddlechange]; + $motioncapture = $_POST[motioncapture]; + $footbed = $_POST[footbed]; + $wetsuit = $_POST[wetsuit]; + $bike = $_POST[bike]; + $trispecific = mysql_escape_string(trim($_POST[trispecific])); + $trispecific_names = mysql_escape_string(trim($_POST[trispecific_names])); + $fist = mysql_escape_string(trim($_POST[fist])); + $fist_names = mysql_escape_string(trim($_POST[fist_names])); + $diagnostic = $_POST[diagnostic]; + $shoe = $_POST[shoe]; + $sock = $_POST[sock]; + $apparel_run = $_POST[apparel_run]; + $apparel_tri = $_POST[apparel_tri]; + $swimgear = $_POST[swimgear]; + $bikeaccessory = $_POST[bikeaccessory]; + $bikebody = $_POST[bikebody]; + $bikecomponent = $_POST[bikecomponent]; + $bikeelectronic = $_POST[bikeelectronic]; + $bikehelmet = $_POST[bikehelmet]; + $biketrainer = $_POST[biketrainer]; + $bikewheel = $_POST[bikewheel]; + $runhydrate = $_POST[runhydrate]; + $bodycare = $_POST[bodycare]; + $hours = mysql_escape_string(trim($_POST[hours])); + + $activity = mysql_escape_string(nl2br(substr(trim($_POST[activity]), 0, 4096))); + + $hour = $_POST[hour]; + if($_POST[daypart] == 1){ $hour = $hour + 12; } + $minute = $_POST[minute]; + $year = $_POST[year]; + $month = $_POST[month]; + $day = $_POST[day]; + $date = "$year-$month-$day $hour:$minute:00"; + + $submitted_by = $_POST[submitted_by]; + + $id = $_POST[$field_lead.'id']; + $edited_by = $_POST['edited_by']; + $edit_timestamp = time(); + + // BEGIN CONFIRM ENTRY CHECK + if($_POST[insert_roadshow] == true){ + if(isset($_POST[new_roadshow])){ + $sql = "INSERT INTO ".$prefix."Roadshow (roadshow_date, roadshow_name, roadshow_name_tag, roadshow_address, roadshow_address_two, roadshow_city, roadshow_state, roadshow_state_tag, roadshow_zip, roadshow_lat, roadshow_lng, roadshow_phone, roadshow_fax, roadshow_email, roadshow_website, roadshow_raffle, roadshow_facebook, roadshow_stambassador, roadshow_stambassador_names, roadshow_triclub, roadshow_triclub_names, roadshow_coach, roadshow_coach_names, roadshow_racedirector, roadshow_racedirector_names, roadshow_brewery, roadshow_brewery_names, roadshow_local, roadshow_fitbike, roadshow_saddlechange, roadshow_motioncapture, roadshow_footbed, roadshow_wetsuit, roadshow_bike, roadshow_trispecific, roadshow_trispecific_names, roadshow_fist, roadshow_fist_names, roadshow_diagnostic, roadshow_shoe, roadshow_sock, roadshow_apparel_run, roadshow_apparel_tri, roadshow_swimgear, roadshow_bikeaccessory, roadshow_bikebody, roadshow_bikecomponent, roadshow_bikeelectronic, roadshow_bikehelmet, roadshow_biketrainer, roadshow_bikewheel, roadshow_runhydrate, roadshow_bodycare, roadshow_hours, roadshow_activity, roadshow_submitted_by, roadshow_valid) VALUES ('$date', '$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$lat', '$lng', '$phone', '$fax', '$email', '$website', '$raffle', '$facebook', '$stambassador', '$stambassador_names', '$triclub', '$triclub_names', '$coach', '$coach_names', '$racedirector', '$racedirector_names', '$brewery', '$brewery_names', '$local', '$fitbike', '$saddlechange', '$motioncapture', '$footbed', '$wetsuit', '$bike', '$trispecific', '$trispecific_names', '$fist', '$fist_names', '$diagnostic', '$shoe', '$sock', '$apparel_run', '$apparel_tri', '$swimgear', '$bikeaccessory', '$bikebody', '$bikecomponent', '$bikeelectronic', '$bikehelmet', '$biketrainer', '$bikewheel', '$runhydrate', '$bodycare', '$hours', '$activity', $submitted_by, 0)"; + //echo("new open water event entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + //header('Location: '.$site_url.'/add.php?confirmed=yes'); + } elseif(isset($_POST[save_changes])) { + $sql = "INSERT INTO ".$prefix."RoadshowEdits (roadshow_id_fk, edit_user_id_fk, edit_timestamp, roadshow_date, roadshow_name, roadshow_name_tag, roadshow_address, roadshow_address_two, roadshow_city, roadshow_state, roadshow_state_tag, roadshow_zip, roadshow_lat, roadshow_lng, roadshow_phone, roadshow_fax, roadshow_email, roadshow_website, roadshow_raffle, roadshow_facebook, roadshow_stambassador, roadshow_stambassador_names, roadshow_triclub, roadshow_triclub_names, roadshow_coach, roadshow_coach_names, roadshow_racedirector, roadshow_racedirector_names, roadshow_brewery, roadshow_brewery_names, roadshow_local, roadshow_fitbike, roadshow_saddlechange, roadshow_motioncapture, roadshow_footbed, roadshow_wetsuit, roadshow_bike, roadshow_trispecific, roadshow_trispecific_names, roadshow_fist, roadshow_fist_names, roadshow_diagnostic, roadshow_shoe, roadshow_sock, roadshow_apparel_run, roadshow_apparel_tri, roadshow_swimgear, roadshow_bikeaccessory, roadshow_bikebody, roadshow_bikecomponent, roadshow_bikeelectronic, roadshow_bikehelmet, roadshow_biketrainer, roadshow_bikewheel, roadshow_runhydrate, roadshow_bodycare, roadshow_hours, roadshow_activity, roadshow_submitted_by, roadshow_valid) VALUES ('$id', '$edited_by', '$edit_timestamp', '$date', '$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$lat', '$lng', '$phone', '$fax', '$email', '$website', '$raffle', '$facebook', '$stambassador', '$stambassador_names', '$triclub', '$triclub_names', '$coach', '$coach_names', '$racedirector', '$racedirector_names', '$brewery', '$brewery_names', '$local', '$fitbike', '$saddlechange', '$motioncapture', '$footbed', '$wetsuit', '$bike', '$trispecific', '$trispecific_names', '$fist', '$fist_names', '$diagnostic', '$shoe', '$sock', '$apparel_run', '$apparel_tri', '$swimgear', '$bikeaccessory', '$bikebody', '$bikecomponent', '$bikeelectronic', '$bikehelmet', '$biketrainer', '$bikewheel', '$runhydrate', '$bodycare', '$hours', '$activity', $submitted_by, 0)"; + //echo("edit to open water event entered!"); + echo($sql); + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/individual.php?roadshow_id='.$id.'&wiki_change=success'); + } else { + header('Location: '.$site_url.'/individual.php?roadshow_id='.$id.'&changes=failure'); + } + } else { + //echo("open water event NOT entered."); + $confirm_roadshow = true; + } + // END CONFIRM ENTRY CHECK +} +// END ERROR MESSAGE CHECK +?> diff --git a/site/roadshow/wiki_validate.php b/site/roadshow/wiki_validate.php new file mode 100644 index 0000000..6c8f395 --- /dev/null +++ b/site/roadshow/wiki_validate.php @@ -0,0 +1,134 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    +

    Unvalidated Public Edits

    +
    + There are no edits waiting to be validated.

    "; + } ?> + +
    + +
    +
    Name
    +
    +
    + "> +
    +
    +
    +
    Edited on
    +
    +
    + by ".$editor_user_username.""; if ($boolEditorIsOwner) { echo " (original ".$local_singular_lc." submitter)"; } else { echo ""; } ?> +
    +
    +
    +
    Info
    +
    +
    + 400){ + $phrase = "…"; + } + else { + $phrase = ""; + } + + echo substr(htmlspecialchars(strip_tags(stripslashes($row[$field_lead.'info']))), 0, 160)."…"; + echo $phrase; + ?> +
    +
    +
    +
    Location
    +
    +
    + 400){ + $phrase = "…"; + } + else{ + $phrase = ""; + } + + echo substr(htmlspecialchars(strip_tags(stripslashes($row[$field_lead.'info']))), 0, 160)."…"; + echo $phrase; + ?> +
    +
    +
    +
    +
    +
    + Validate this edit. Delete this edit.
    +
    +
    + +
    + +
    + +
    + +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/roadshow/wiki_validate_X.php b/site/roadshow/wiki_validate_X.php new file mode 100644 index 0000000..6e516b5 --- /dev/null +++ b/site/roadshow/wiki_validate_X.php @@ -0,0 +1,174 @@ + \ No newline at end of file diff --git a/site/roadshow/wiki_view.php b/site/roadshow/wiki_view.php new file mode 100644 index 0000000..191df18 --- /dev/null +++ b/site/roadshow/wiki_view.php @@ -0,0 +1,867 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + + +
    +
    +
    Editor
    +
    +
    + ".$strEditor.""; ?> +
    +
    +
    +
    Edit Date
    +
    +
    + +
    +
    +
    +
    Date
    +
    +
    + + format('Y-m-d'); ?> +
    +
    +
    +
    Time
    +
    +
    + format('g:i A'); ?> +
    +
    +
    +
    Street Address
    +
    +
    + +
    +
    +
    +
    Street Address Two
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax/Alt. Phone
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + + $website"; ?> +
    +
    +
    +
    +
    +
    +

    Local Assets

    +
    +
    +
    +
    Slowtwitch Ambassador(s)
    +
    +
    + +
    +
    +
    +
    Tri Club(s)
    +
    +
    +
    +
    +
    +
    +
    Coach(es)
    +
    +
    +
    +
    +
    +
    +
    Race Director(s)
    +
    +
    +
    +
    +
    +
    +
    Brewery(ies)
    +
    +
    +
    +
    +
    +
    +
    Other
    +
    +
    +
    +
    +
    +
    +
    Fitbike(s)
    +
    +
    + +
    +
    +
    +
    Saddle Quick Change
    +
    +
    + +
    +
    +
    +
    Motion Capture System(s)
    +
    +
    + +
    +
    +
    +
    Custom Footbed(s)
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Brands

    +
    +
    +
    +
    Triathlon Apparel
    +
    +
    + +
    +
    +
    +
    Bike(s)
    +
    +
    + +
    +
    +
    +
    Bike Saddles/Footwear/Aerobars/Bike Hydration
    +
    +
    + +
    +
    +
    +
    Bike Helmets/Eyewear
    +
    +
    + +
    +
    +
    +
    Bike Nutritionals/Lubricants/Botanicals
    +
    +
    + +
    +
    +
    +
    Bike Stationary Trainer(s)
    +
    +
    + +
    +
    +
    +
    Bike Electronics/Cameras/Metrics
    +
    +
    + +
    +
    +
    +
    Bike Wheels/Tires
    +
    +
    + +
    +
    +
    +
    Bike Component(s)
    +
    +
    + +
    +
    +
    +
    Socks
    +
    +
    + +
    +
    +
    +
    Running Shoe(s)
    +
    +
    + +
    +
    +
    +
    Run Apparel
    +
    +
    + +
    +
    +
    +
    Run Hydration
    +
    +
    + +
    +
    +
    +
    Wetsuit(s)
    +
    +
    + +
    +
    +
    +
    Swim Apparel/Gear
    +
    +
    + +
    +
    +
    +
    Bodycare Tools
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Technology, Community & Education

    +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + +
    +
    +
    +
    F.I.S.T. Tri Fitters(s)
    +
    +
    + +
    +
    +
    +
    Diagnostic Tools
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Social

    +
    +
    +
    +
    Shop Hours
    +
    +
    + +
    +
    +
    +
    Runs & Classes
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/runshops/add.php b/site/runshops/add.php new file mode 100644 index 0000000..98d6aec --- /dev/null +++ b/site/runshops/add.php @@ -0,0 +1,404 @@ + + + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + + +

    Thank You

    +

    Thank you. Your shop should be added within 24 hours. You will now be redirected back to the homepage page.

    + + +

    Add a Shop: Step 2 of 2

    + +

    Add a Shop: Step 1 of 2

    + +

    Thank you

    + +
    + + + +

    If you would like to add your triathlon/running shop to our website, simply fill out the form below. Be sure to fill out every field. After filling out each field, click submit. You will then be prompted to confirm your information before the information is sent to us.

    + + + +
    +

    +
    +
    +
    Store Name
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Address 2
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    Online Shopping Cart
    +
    +
    + (Must be a fully functional ecommerce system) +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + + +
    +
    +
    +
    Diagnostic Equipment
    +
    +
    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[diagnostic_name]"); +} +?> +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Running Shoes
    +
    +
    +

    IMPORTANT: Running shoe brands of which you'll have almost + full size runs in stock of most of the important run models at almost all + times.

    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[shoe_name]"); +} +?> +
    +
    +
    +
    Socks
    +
    +
    +

    IMPORTANT: Sock brands you'll keep in stock almost all the time.

    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[sock_name]"); +} +?> +
    +
    +
    +
    Run Focused Apparel
    +
    +
    +

    IMPORTANT: Run focus apparel brands you'll keep in stock, full size runs, almost all the time, season-appropriate.

    +"); +while ($row = mysql_fetch_array($results)) { + echo(" $row[apparel_run_name]"); +} +?> +
    +
    +
    +
    Tri Focused Apparel
    +
    +
    +

    IMPORTANT: Run/tri apparel brands you'll keep in stock, full size runs, almost + all the time, season-appropriate.

    +"); +while ($row = mysql_fetch_array($results)) { + echo(" $row[apparel_tri_name]"); +} +?> +
    +
    +
    +
    Swim Gear
    +
    +
    +

    IMPORTANT: Swimwear/Goggles: Brands you carry wide and deep, with models that are + swim-specific.

    +"); +while ($row = mysql_fetch_array($results)) { + echo("$row[swimgear_name]\n"); +} +?> +
    +
    +
    +
    Wetsuits
    +
    +
    +

    IMPORTANT: Wetsuit brands of which you'll have 12 or more continually in stock during the season.

    +"); +while ($row = mysql_fetch_array($results)) { + echo(" $row[wetsuit_name]"); +} +?> +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Store Hours
    +
    +
    + +
    +
    +
    +
    Runs & Classes
    +
    +
    + +
    +
    +
    +
    Shop Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + Thank you. Your shop should be added within 24 hours. You will now be redirected back to the home page.

    "; + echo ""; + } + + if ($confirm == 1) { + $confirm = 0; + include("include_add_confirm.php"); + } + } ?> + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/runshops/add_X.php b/site/runshops/add_X.php new file mode 100644 index 0000000..c9c3656 --- /dev/null +++ b/site/runshops/add_X.php @@ -0,0 +1,124 @@ +"; +} +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[name]) ) { + // Contains invalid characters. + $errmsg = "Please use only letters and numbers in the name"; +} +if(!$errmsg){ + $name = mysql_real_escape_string(trim($_POST[name])); + $name_tag = mysql_real_escape_string(strtolower(str_replace(" ","", $name))); + if(strlen($nametag) > 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = mysql_real_escape_string(trim($_POST[address])); + $address_two = mysql_real_escape_string(trim($_POST[address_two])); + $city = mysql_real_escape_string(trim($_POST[city])); + $state = mysql_real_escape_string($_POST[state]); + $state_tag = mysql_real_escape_string(strtolower(str_replace(" ","", $state))); + $zip = mysql_real_escape_string(trim($_POST[zip])); + $phone = mysql_real_escape_string(trim($_POST[phone])); + $fax = mysql_real_escape_string(trim($_POST[fax])); + $email = mysql_real_escape_string(trim($_POST[email])); + $website = mysql_real_escape_string(trim($_POST[website])); + $cart = mysql_real_escape_string(trim($_POST[cart])); + $contact = mysql_real_escape_string($_POST[contact]); + if ( $contact == 0 ){ $contact_names = NULL; }else{ $contact_names = mysql_real_escape_string(trim($_POST[contact_names])); } + /* Need to ltrim and rtrim commas before insertion --> or ltrim/rtrim before implosion*/ + $diagnostics = mysql_real_escape_string($_POST[diagnostics]); + $shoes = mysql_real_escape_string($_POST[shoes]); + $socks = mysql_real_escape_string($_POST[socks]); + $apparelrun = mysql_real_escape_string($_POST[apparel_run]); + $appareltri = mysql_real_escape_string($_POST[apparel_tri]); + $swimgear = mysql_real_escape_string($_POST[swimgear]); + $wetsuits = mysql_real_escape_string($_POST[wetsuits]); + $hours = mysql_real_escape_string(trim($_POST[hours])); + $classes = mysql_real_escape_string(nl2br(substr(trim($_POST[classes]), 0, 4096))); + $info = mysql_real_escape_string(nl2br(substr(trim($_POST[info]), 0, 4096))); + $directions = mysql_real_escape_string(nl2br(substr(trim($_POST[directions]), 0, 4096))); + $submitted_by = mysql_real_escape_string($_POST[submitted_by]); + + if($_POST[confirm1] == 1){ + $sql = "INSERT INTO ".$prefix."Runshops (runshop_name, runshop_name_tag, runshop_address, runshop_address_two, runshop_city, runshop_state, runshop_state_tag, runshop_zip, runshop_phone, runshop_fax, runshop_email, runshop_website, runshop_cart, runshop_contact, runshop_contact_names, runshop_diagnostics, runshop_shoes, runshop_socks, runshop_apparel_run, runshop_apparel_tri, runshop_swimgear, runshop_wetsuits, runshop_hours, runshop_classes, runshop_info, runshop_directions, runshop_submitted_by, runshop_valid) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', '$cart', $contact, '$contact_names', ',$diagnostics,', ',$shoes,', ',$socks,', ',$apparelrun,', ',$appareltri,', ',$swimgear,', ',$wetsuits,', '$hours', '$classes', '$info', '$directions', $submitted_by, 0)"; + //echo("shop entered!"); + //echo($sql); + //exit(); + mysql_query($sql) OR die(mysql_error()); + //exit(); + }else{ + //echo("shop NOT entered."); + $confirm = 1; + } +} +?> diff --git a/site/runshops/ajax.rate.item.php b/site/runshops/ajax.rate.item.php new file mode 100644 index 0000000..694db67 --- /dev/null +++ b/site/runshops/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/runshops/comments_add.php b/site/runshops/comments_add.php new file mode 100644 index 0000000..bd506e2 --- /dev/null +++ b/site/runshops/comments_add.php @@ -0,0 +1,31 @@ + + +
    + + + + +
    + +Add A Comment +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    + + +
    diff --git a/site/runshops/comments_add_X.php b/site/runshops/comments_add_X.php new file mode 100644 index 0000000..8bf2bb1 --- /dev/null +++ b/site/runshops/comments_add_X.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/site/runshops/comments_show.php b/site/runshops/comments_show.php new file mode 100644 index 0000000..9696d5c --- /dev/null +++ b/site/runshops/comments_show.php @@ -0,0 +1,8 @@ + + + diff --git a/site/runshops/comments_validate.php b/site/runshops/comments_validate.php new file mode 100644 index 0000000..6196b7d --- /dev/null +++ b/site/runshops/comments_validate.php @@ -0,0 +1,84 @@ + + + + + + +
    + + +
    + + + + + +

    Unvalidated Comments

    +
    +
    + + + + "> + + + +
    Reviewed by: ".$commenter_user_username.""; echo " on ".date("F j, Y g:i A", $arrComments[comment_time]); echo " about ".$runshop_name."";?>
    + +
    Validate this comment. Delete this comment.
    +
    + +
    +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/site/runshops/comments_validate_X.php b/site/runshops/comments_validate_X.php new file mode 100644 index 0000000..2f66848 --- /dev/null +++ b/site/runshops/comments_validate_X.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/site/runshops/config.php b/site/runshops/config.php new file mode 100644 index 0000000..90945fd --- /dev/null +++ b/site/runshops/config.php @@ -0,0 +1,85 @@ += '4.0.4pl1' && strstr($_SERVER["HTTP_USER_AGENT"],'compatible')) { + if (extension_loaded('zlib')) { + ob_end_clean(); + ob_start('ob_gzhandler'); + } +} else if ($phpver > '4.0') { + if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) { + if (extension_loaded('zlib')) { + $do_gzip_compress = TRUE; + ob_start(array('ob_gzhandler',5)); + ob_implicit_flush(0); + header('Content-Encoding: gzip'); + } + } +} +$phpver = explode(".", $phpver); +$phpver = "$phpver[0]$phpver[1]"; +if ($phpver >= 41) { + $PHP_SELF = $_SERVER['PHP_SELF']; +} + +if (!ini_get("register_globals")) { + /*import_request_variables('GPC'); */ +} + +$sql = "SELECT * FROM ".$prefix."ResourceStates ORDER BY stateid"; +$result = mysql_query($sql) OR die(mysql_error()); +$state_list = array(); +$state_tag_list = array(); +while ($row = mysql_fetch_array($result)) { + $state_list[$row['stateid']] = $row['statelong']; + $state_tag_list[] = $row['statetag']; +} + +function curPageURL() { + $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); + $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); + $port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : ''; + $url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.$_SERVER["REQUEST_URI"]; + return $url; +} + +?> diff --git a/site/runshops/delete_X.php b/site/runshops/delete_X.php new file mode 100644 index 0000000..33927dd --- /dev/null +++ b/site/runshops/delete_X.php @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/site/runshops/include_add_confirm.php b/site/runshops/include_add_confirm.php new file mode 100644 index 0000000..caae9b1 --- /dev/null +++ b/site/runshops/include_add_confirm.php @@ -0,0 +1,324 @@ +

    +Please confirm your shop information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your shop information before submitting. +

    + + +
    +
    +
    Store Name
    +
    +
    +
    +
    +
    Address
    +
    +
    +
    +
    +
    Address 2
    +
    +
    +
    +
    +
    City
    +
    +
    +
    +
    +
    State
    +
    +
    +
    +
    +
    Zip
    +
    +
    +
    +
    +
    Phone
    +
    +
    +
    +
    +
    Fax
    +
    +
    +
    +
    +
    E-mail
    +
    +
    +
    +
    +
    Website
    +
    +
    +
    +
    +
    Cart
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + +
    +
    +
    +
    Diagnostic Equipment
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Running Shoes
    +
    +
    + +
    +
    +
    +
    Socks
    +
    +
    + +
    +
    +
    +
    Run Focused Apparel
    +
    +
    + +
    +
    +
    +
    Tri-Focused Apparel
    +
    +
    + +
    +
    +
    +
    Swim Gear
    +
    +
    + +
    +
    +
    +
    Wetsuits
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Store Hours
    +
    +
    + +
    +
    +
    +
    Runs & Classes
    +
    +
    + +
    +
    +
    +
    Shop Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    diff --git a/site/runshops/include_breadcrumb.php b/site/runshops/include_breadcrumb.php new file mode 100644 index 0000000..6fd8bc5 --- /dev/null +++ b/site/runshops/include_breadcrumb.php @@ -0,0 +1,12 @@ + diff --git a/site/runshops/include_buttons.php b/site/runshops/include_buttons.php new file mode 100644 index 0000000..0dd69b9 --- /dev/null +++ b/site/runshops/include_buttons.php @@ -0,0 +1,116 @@ + + +
    + + + + + + +
    +
    " style="display: inline;"> + +
    + +
    " style="display: inline;"> + +
    + + +
    + + +
    + +
    Entered By: $username"); +} +// end is_admin check +?> diff --git a/site/runshops/include_common_content.php b/site/runshops/include_common_content.php new file mode 100644 index 0000000..6f26052 --- /dev/null +++ b/site/runshops/include_common_content.php @@ -0,0 +1,27 @@ + + + +> + + +
    +
    + + + + + + + diff --git a/site/runshops/include_common_footer.php b/site/runshops/include_common_footer.php new file mode 100644 index 0000000..7812696 --- /dev/null +++ b/site/runshops/include_common_footer.php @@ -0,0 +1 @@ + diff --git a/site/runshops/include_common_head.php b/site/runshops/include_common_head.php new file mode 100644 index 0000000..a507ec0 --- /dev/null +++ b/site/runshops/include_common_head.php @@ -0,0 +1,14 @@ + + + + + +Slowtwitch.com Running Store Database: <? echo $pagetitle; ?> + + + + diff --git a/site/runshops/include_edit_confirm.php b/site/runshops/include_edit_confirm.php new file mode 100644 index 0000000..a173be5 --- /dev/null +++ b/site/runshops/include_edit_confirm.php @@ -0,0 +1,384 @@ +

    + Please confirm your shop information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your shop information before submitting. +

    + +

    + + +
    +
    +
    Store Name
    +
    +
    +
    +
    +
    Address
    +
    +
    +
    +
    +
    Address 2
    +
    +
    +
    +
    +
    City
    +
    +
    +
    +
    +
    State
    +
    +
    +
    +
    +
    Zip
    +
    +
    +
    +
    +
    Phone
    +
    +
    +
    +
    +
    Fax
    +
    +
    +
    +
    +
    E-mail
    +
    +
    +
    +
    +
    Website
    +
    +
    +
    +
    +
    Cart
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + +
    +
    +
    +
    Diagnostic Equipment
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Shoes
    +
    +
    + +
    +
    +
    +
    Socks
    +
    +
    + +
    +
    +
    +
    Run Focused Apparel
    +
    +
    + +
    +
    +
    +
    Tri-Focused Apparel
    +
    +
    + +
    +
    +
    +
    Swim Gear
    +
    +
    + +
    +
    +
    +
    Wetsuits
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Store Hours
    +
    +
    + +
    +
    +
    +
    Runs & Classes
    +
    +
    + +
    +
    +
    +
    Shop Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This data will be saved as a NEW RETAILER. + + + + This data will be saved as a modification to the EXISTING RETAILER. + + + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    diff --git a/site/runshops/include_navigation.php b/site/runshops/include_navigation.php new file mode 100644 index 0000000..743ba5c --- /dev/null +++ b/site/runshops/include_navigation.php @@ -0,0 +1,71 @@ + + +
    +

    Choose Listing

    +
    +$currentregion ($regioncount)$state_string"; + echo ("
    " . $currentregion . " (" . $regioncount . ")+
    "); + echo $tempstring; + echo ("
    \n"); + } + $currentregion = $rowregionlist[regionlong]; + $currentrid = $rowregionlist[regionid]; + $currenttag = $rowregionlist[regionname]; + $regioncount = 0; + $tempstring = ''; + $state_string = ''; + } + + if ($selected_item == $rowregionlist[statetag]) { + $selected_state = ' selected="selected"'; + } + $state_string .= ""; + $tempstring = $tempstring. "$rowregionlist[statelong] ($rowregionlist[numshops])\n"; + $regioncount += $rowregionlist[numshops]; +} + +echo ("
    ".$currentregion." (".$regioncount.")+
    "); +echo $tempstring; +echo ('
    '); +if ( $selected_item == 'top') { $selected_region = ' selected="selected"'; } +$region_dropdown .= ""; +?> + + +
    +
    diff --git a/site/runshops/include_region_list.php b/site/runshops/include_region_list.php new file mode 100644 index 0000000..a3b6889 --- /dev/null +++ b/site/runshops/include_region_list.php @@ -0,0 +1,4 @@ +
    + +
    +
    diff --git a/site/runshops/include_sidebar.php b/site/runshops/include_sidebar.php new file mode 100644 index 0000000..a53933d --- /dev/null +++ b/site/runshops/include_sidebar.php @@ -0,0 +1,14 @@ + + +
    + + + +
    + + diff --git a/site/runshops/include_starfunc.php b/site/runshops/include_starfunc.php new file mode 100644 index 0000000..25d66b1 --- /dev/null +++ b/site/runshops/include_starfunc.php @@ -0,0 +1,44 @@ += 0)or($tut_rating == 0)) && ($tut_rating <= 0.50)){ + echo "Not Rated"; + } + if((($tut_rating >= 0.50)or($tut_rating == 0.50)) && ($tut_rating <= .99)){ + echo ""; + } + if((($tut_rating >= 1.00)or($tut_rating == 1.50)) && ($tut_rating <= 1.49)){ + echo ""; + } + if((($tut_rating >= 1.50)or($tut_rating == 1.50)) && ($tut_rating <= 1.99)){ + echo ""; + } + if((($tut_rating >= 2.00)or($tut_rating == 2.00)) && ($tut_rating <= 2.49)){ + echo ""; + } + + if((($tut_rating >= 2.50)or($tut_rating == 2.50)) && ($tut_rating <= 2.99)){ + echo ""; + } + + if((($tut_rating >= 3.00)or($tut_rating == 3.00)) && ($tut_rating <= 3.49)){ + echo ""; + } + + if((($tut_rating >= 3.50)or($tut_rating == 3.50)) && ($tut_rating <= 3.99)){ + echo ""; + } + if((($tut_rating >= 4.00)or($tut_rating == 4.00)) && ($tut_rating <= 4.49)){ + echo ""; + } + if((($tut_rating >= 4.50)or($tut_rating == 4.50)) && ($tut_rating <= 4.99)){ + echo ""; + } + if($tut_rating == 5.0){ + echo ""; + } +} +?> diff --git a/site/runshops/include_status.php b/site/runshops/include_status.php new file mode 100644 index 0000000..015e353 --- /dev/null +++ b/site/runshops/include_status.php @@ -0,0 +1,10 @@ +Validate Entries (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Edits")); + echo("
    Validate Edits (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Comment WHERE comment_valid = 0")); + echo("
    Validate Comments (".$unvalid_count.")
    "); + echo("
    "); +} ?> + diff --git a/site/runshops/include_store.php b/site/runshops/include_store.php new file mode 100644 index 0000000..ae68ed5 --- /dev/null +++ b/site/runshops/include_store.php @@ -0,0 +1,20 @@ +
    +
    +

    ">

    +
    +
    + $row[runshop_address_two]"); } + echo("
    $row[runshop_city], $row[runshop_state] $row[runshop_zip]"); + ?> +
    Phone: +
    Fax: +
    +
    + Email: $row[runshop_email]"; ?>
    + Website: $row[runshop_website]"; ?>
    + "); } ?> + ">More info > +
    +
    diff --git a/site/runshops/index.php b/site/runshops/index.php new file mode 100644 index 0000000..f80b301 --- /dev/null +++ b/site/runshops/index.php @@ -0,0 +1,138 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Running Stores

    + + + Add Retailer + +
    + + +
    +
    +
    + + +

    Welcome to Slowtwitch.com's North American Multisport Running Store Database

    +

    running stores and counting. This collection of running stores is the most complete and comprehensive + selection of tri-specific running stores in North America. The purpose is to + introduce triathletes to the dealers they should know, and to present as + much pertinent information about them as possible. +

    + +

    Searching the database

    +

    + Our Advanced Search is very potent, and will help you drill down to that set + of runnning stores conforming to a specific purpose you have in mind. For + example, you could search for those stores that have a motion capture system; and a treadmill; and that carry Nike and Zoot; and that are in either Wisconsin or + Illinois. Or you could search for stores in Georgia that stock Quintana Roo + wetsuits. The search parameters are yours to choose. +

    + +

    Browsing the database

    +

    + You do not need to log in to do this. You'll find a list of running stores in + your region by clicking the regional links on the left. Click the (+) sign + and the region will expand to expose the individual states. Click on the + state to show that list of running stores in it. If you want to see running stores in multiple states, but not those states we've aggregated into the regions you see at left, you may do this via our Advanced Search. +

    + +

    Showing solidarity with your local running store

    +

    + When you see your local running store listed here, you may click the "I SHOP + HERE" button. Your User Name will be added to the store's list of customers, + just like your User Name appends to those races you choose when you build + your Slowtwitch Personal Race Calendar. Likewise, your Forum User Profile + will show that you patronize this store. +

    + + +

    How to enter a running store

    +

    + You must be a registered user to add a running store to the database. There is + one common type of registration on Slowtwitch, and if you are registered to + post on our Reader Forum you are one of + + who have made a registration, + and this means you're able to add running stores to our database. However, this + is not like adding a race to our calendar. There are a lot of technical + elements to this entry, and almost certainly the running store will want to do this on their own. Therefore, it is wisest not to make an entry on behalf of + your preferred running store, but to urge them to do so themselves. +

    + If you're not registered, the login prompt is to the left of the page, near + the top. The registration process is straightforward, easy, and free. It + will require you to receive an email and click on a link to complete your + registration. All this should take you only a minute or two. Then... +

    + 1. Click the ADD A SHOP button to begin adding to the database. +

    + 2. Once you SUBMIT your store, you'll also need to CONFIRM your submission + via a link at the bottom of the page. +

    + 3. Once you successfully add your store, it will not immediately be visible + to you. We must validate the addition on our end before anyone can see it. + We do this so that spammers won't use the store registration as a way to spam + our database. +

    +

    How to edit published information about a running store

    +

    + Any registered user may edit information for a listing. We will review the full contents of each update before confirming any changes that are made. A list of all editors who have made changes is visible at the bottom of each listing. If an entry has been updated, but those changes have not yet been confirmed, this is evident via a note on the individual page for that particular entry. This is to prevent conflicting updates from occuring simultaneously. If you wish to update an entry with pending changes, please wait until we have had a chance to review those changes first. Someone may have already changed the information you were going to change yourself. +

    +

    How to comment on a running store

    +

    + Any registered user may make a comment on a running store. These comments are subject to validation by an administrator before being published. +

    + +

    Global run shop map

    +

    + The map below shows the location of all registered Slowtwitch running shops around the globe. You can drag the map, zoom-in, zoom-out, and use any other of the standard Google Maps features. Anywhere you see a red icon, you can click to see the name of that running shop and a street address. +

    + +
    +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/runshops/individual.php b/site/runshops/individual.php new file mode 100644 index 0000000..d093b24 --- /dev/null +++ b/site/runshops/individual.php @@ -0,0 +1,297 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Running Stores

    + +
    + +
    + + Back +
    + +
    +
    +

    +
    +
    + Comment +
    +
    +
    +
    + "); } ?> + ,
    + Phone:
    + Fax: +
    +
    + Email:
    + Website: +
    +
    + +

    Commenter: your comments have been submitted and will be validated within 24 hours.

    + + +

    Editor: your changes have been submitted and will be validated within 24 hours.

    + + +

    Group Edits: there are group edits waiting to be validated.

    + +
    +
    + +
    +
    +

    Key Tri-Specific Contact(s)

    +
    + +
    +
    +
    +

    Diagnostic Equipment

    +
    + +
    +
    +
    +

    Brands

    +
    + Running Shoes: +
    + Socks: +
    + Run Focused Apparel: +
    + Tri Focused Apparel: +
    + Swim Gear: +
    + Wetsuits: +
    +
    +
    +
    +

    General Information

    +
    + Store Hours:
    + Runs & Classes:
    +

    Shop Info

    +

    Directions:

    +
    +
    +
    +
    +
    + +
    + + Map location is based off of a geocode of the addressed entered using Google's Google Maps API. If your address does not geocode properly, you can either update the address (we will attempt to re-geocode after any updates to your entry) or you can use Google's geocoding tool found here: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html to obtain a lat/long for your location and enter that. To use the utility, type in an address that is close to your location and then drag-and-drop the marker to obtain the desired lat/long. If you choose to enter a lat/long, you must check the box on the edit page that says, "override geocode with entered lat/long." + +
    +
    +
    +

    Who Shops Here?

    +
    + + + + 0) { + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if ( $i > 1 ) { echo ", "; } + echo "$temprow[user_username]"; + } + $i++; + } + ?> + +
    +
    +
    + +
    + = 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i >= 1) { echo "
    "; } + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + } + $i++; + } + if ($numcount <= 0) { echo "No users"; } + ?> +
    +
    +
    + +
    + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/runshops/logout.php b/site/runshops/logout.php new file mode 100644 index 0000000..7596104 --- /dev/null +++ b/site/runshops/logout.php @@ -0,0 +1,7 @@ + diff --git a/site/runshops/mod_rewrite.txt b/site/runshops/mod_rewrite.txt new file mode 100644 index 0000000..b8d3858 --- /dev/null +++ b/site/runshops/mod_rewrite.txt @@ -0,0 +1,15 @@ + + ServerName forum.slowtwitch.com + DocumentRoot /srv/www/htdocs/trifind + Options +FollowSymLinks + RewriteEngine On + RewriteRule ^/racereports/(.*)-([0-9]+).html$ /indivreport.php?report=$2 + RewriteRule ^/racereports/page([0-9]+).html$ /racereports.php?page=$1 + RewriteRule ^/editprofile/(.*).html$ /editprofile.php?username1=$1 + RewriteRule ^/profiles/(.*).html$ /profile.php?username1=$1 + RewriteRule ^/blogs/(.*)-([0-9]+).html$ /indivblog.php?blog=$2 + RewriteRule ^/(.*)/(.*)-([0-9]+).html$ /individual.php?uid=$3 + RewriteRule ^/state/(.*).html$ /statelist.php?state=$1 + RewriteRule ^/blogs/page([0-9]+).html$ /blog.php?page=$1 + RewriteRule ^/(.*).html$ /$1.php + diff --git a/site/runshops/mysql.class.php b/site/runshops/mysql.class.php new file mode 100644 index 0000000..fc69db7 --- /dev/null +++ b/site/runshops/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/runshops/phpthumb/cache/index.php b/site/runshops/phpthumb/cache/index.php new file mode 100644 index 0000000..cee9927 --- /dev/null +++ b/site/runshops/phpthumb/cache/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/runshops/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg b/site/runshops/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg new file mode 100644 index 0000000..af7980d Binary files /dev/null and b/site/runshops/phpthumb/cache/phpThumb_cache_test.slowtwitch.com_srccc53ea79e8e8b04741ba1a278879194c_parbdeee61a025433c524d6d995a659221d_dat1143166197.jpeg differ diff --git a/site/runshops/phpthumb/cache/source/index.php b/site/runshops/phpthumb/cache/source/index.php new file mode 100644 index 0000000..cee9927 --- /dev/null +++ b/site/runshops/phpthumb/cache/source/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/runshops/phpthumb/demo/index.php b/site/runshops/phpthumb/demo/index.php new file mode 100644 index 0000000..266a496 --- /dev/null +++ b/site/runshops/phpthumb/demo/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/site/runshops/phpthumb/demo/phpThumb.demo.check.php b/site/runshops/phpthumb/demo/phpThumb.demo.check.php new file mode 100644 index 0000000..7dd987c --- /dev/null +++ b/site/runshops/phpthumb/demo/phpThumb.demo.check.php @@ -0,0 +1,278 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.check.php // +// James Heinrich // +// // +// Configuration analyzer for phpThumb settings and server // +// settings that may affect phpThumb performance // +// Live demo is at http://phpthumb.sourceforge.net/demo/ // +// // +////////////////////////////////////////////////////////////// + +$ServerInfo['gd_string'] = 'unknown'; +$ServerInfo['gd_numeric'] = 0; +ob_start(); +if (!@include_once('../phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.functions.php")'); +} +if (!@include_once('../phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.class.php")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +if (include_once('../phpThumb.config.php')) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + } +} +$ServerInfo['gd_string'] = phpthumb_functions::gd_version(true); +$ServerInfo['gd_numeric'] = phpthumb_functions::gd_version(false); +$ServerInfo['im_version'] = $phpThumb->ImageMagickVersion(); +$gd_info = gd_info(); + +?> + + + + phpThumb configuration analyzer + + + + +This demo analyzes your settings (phpThumb.config.php and server/PHP) for phpThumb().
    +
    + + + + + + + + + + + + +
    <-- bad to good -->
                                    
    + + phpthumb_functions::SafeURLread('http://phpthumb.sourceforge.net/?latestversion=1', $dummy), + 'this' => $phpThumb->phpthumb_version, +); +foreach ($versions['raw'] as $key => $value) { + eregi('^([0-9\.]+)\-?(([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))?', $value, $matches); + @list($huge, $major, $minor) = @explode('.', @$matches[1]); + @list($year, $month, $day, $hour, $min) = @$matches[3]; + $versions['base'][$key] = $matches[1]; + $versions['huge'][$key] = $huge; + $versions['major'][$key] = $major; + $versions['minor'][$key] = $minor; + $versions['stamp'][$key] = $matches[2]; + $versions['year'][$key] = $year; + $versions['month'][$key] = $month; + $versions['day'][$key] = $day; + $versions['hour'][$key] = $hour; + $versions['min'][$key] = $min; + $versions['date'][$key] = @mktime($hour, $min, 0, $month, $day, $year); +} + +$downloadlatest = 'Download the latest version from http://phpthumb.sourceforge.net'; +echo ''; +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +echo ''; + + +?> +
    Latest phpThumb version:'.$versions['raw']['latest'].''.$downloadlatest.'
    This phpThumb version:info@silisoftware.com'; +} elseif (($versions['base']['latest'] == $versions['base']['this']) && ($versions['stamp']['this'] > $versions['stamp']['latest'])) { + // new than latest, must be beta version + echo 'lightblue'; + $message = 'You must be using a pre-release beta version. Please report bugs to info@silisoftware.com'; +} elseif ($versions['base']['latest'] == $versions['base']['this']) { + // latest version + echo 'lime'; + $message = 'You are using the latest released version.'; +} elseif ($versions['huge']['latest'].$versions['major']['latest'] == $versions['huge']['this'].$versions['major']['this']) { + echo 'olive'; + $message = 'One (or more) minor version(s) have been released since this version.
    '.$downloadlatest; +} elseif (floatval($versions['huge']['latest'].str_pad($versions['major']['latest'], 2, '0', STR_PAD_LEFT)) < floatval($versions['huge']['this'].str_pad($t_major, 2, '0', STR_PAD_LEFT))) { + echo 'yellow'; + $message = 'One (or more) major version(s) have been released since this version, you really should upgrade.
    '.$downloadlatest; +} else { + echo 'orange'; + $message = 'Fundamental changes have been made since this version.
    '.$downloadlatest; +} +echo '">'.$phpThumb->phpthumb_version; +echo '
    '.$message.'.
    PHP version:'.phpversion(); +echo 'PHP5 is ideal (support for numerous built-in filters which are much faster than my code).
    PHP v4.3.2+ supports ImageSaveAlpha which is required for proper PNG/ICO output.
    ImageRotate requires PHP v4.3.0+ (but buggy before v4.3.3).
    EXIF thumbnail extraction requires PHP v4.2.0+.
    Most things will work back to PHP v4.1.0, and mostly (perhaps buggy) back to v4.0.6, but no guarantees for any version older than that.
    GD version:'.@$ServerInfo['gd_string']; +echo 'GD2-bundled version is ideal.
    GD2 (non-bundled) is second choice, but there are a number of bugs in the non-bundled version.
    GD1 will also (mostly) work, at much-reduced image quality and several features disabled. phpThumb can perform basic resizing with ImageMagick only, even if GD is not available.
    ImageMagick version:'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a'); +echo 'ImageMagick is faster than GD, can process larger images without PHP memory_limit issues, can resize animated GIFs. phpThumb can perform basic resizing with ImageMagick only, even if GD is not available.
    GD features:'; +$GDfeatures['red'] = array('JPG Support', 'PNG Support'); +$GDfeatures['orange'] = array('GIF Read Support', 'GIF Create Support', 'FreeType Support'); +foreach ($GDfeatures as $missingcolor => $features) { + foreach ($features as $dummy => $feature) { + echo '
    '.htmlentities($feature).'
    '; + } +} +echo '
    PNG support is required for watermarks, overlays, calls to ImageMagick and other internal operations.
    JPG support is obviously quite useful, but ImageMagick can substitute
    GIF read support can be bypassed with ImageMagick and/or internal GIF routines.
    GIF create support can be bypassed with ImageMagick (if no filters are applied)
    FreeType support is needed for TTF overlays.
    GD extension "EXIF"'.(extension_loaded('exif') ? 'TRUE' : 'FALSE'); +echo 'EXIF extension required for auto-rotate images. Also required to extract EXIF thumbnail to use as source if source image is too large for PHP memory_limit and ImageMagick is unavailable.
    magic_quotes_runtime:'.$phpThumb->phpThumbDebugVarDump((bool) @get_magic_quotes_runtime()); +echo 'This setting is evil. Turn it off.
    magic_quotes_gpc:'.$phpThumb->phpThumbDebugVarDump((bool) @get_magic_quotes_gpc()); +echo 'This setting is bad. Turn it off, if possible. phpThumb will attempt to work around it if it is enabled
    safe_mode:'.$phpThumb->phpThumbDebugVarDump((bool) @ini_get('safe_mode')); +echo 'Best if off. Calls to ImageMagick will be disabled if on (limiting max image resolution, no animated GIF resize).
    allow_url_fopen:'.$phpThumb->phpThumbDebugVarDump((bool) @ini_get('allow_url_fopen')); +echo 'Best if on. HTTP source images will be unavailable if disabled and CURL is unavailable.
    curl_version:'.(function_exists('curl_version') ? curl_version() : 'n/a') ; +echo 'Best if available. HTTP source images will be unavailable if CURL unavailable and allow_url_fopen is also disabled.
    disable_functions:'.eregi_replace('(shell_exec|system|passthru|exec)(,|$)', '\\1(\\2)', $disable_functions); +echo 'Best if nothing disabled. Calls to ImageMagick will be prevented if exec+system+shell_exec+passthru are disabled.
    memory_limit:'.($memory_limit ? $memory_limit : 'unlimited'); +echo 'The higher the better. Divide by 5 to get maximum megapixels of source image that can be thumbnailed (without ImageMagick).'.($memory_limit ? ' Your setting ('.$memory_limit.') allows images up to approximately '.number_format($memory_limit / 5, 1).' megapixels' : '').'
    + + \ No newline at end of file diff --git a/site/runshops/phpthumb/demo/phpThumb.demo.demo.php b/site/runshops/phpthumb/demo/phpThumb.demo.demo.php new file mode 100644 index 0000000..e8a70d2 --- /dev/null +++ b/site/runshops/phpthumb/demo/phpThumb.demo.demo.php @@ -0,0 +1,249 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.demo.php // +// James Heinrich // +// // +// Demo showing a wide variety of parameters that can be // +// passed to phpThumb.php // +// Live demo is at http://phpthumb.sourceforge.net/demo/ // +// // +////////////////////////////////////////////////////////////// +$ServerInfo['gd_string'] = 'unknown'; +$ServerInfo['gd_numeric'] = 0; +ob_start(); +if (!@include_once('../phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.functions.php")'); +} +if (!@include_once('../phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("../phpthumb.class.php")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +if (include_once('../phpThumb.config.php')) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + } +} +$ServerInfo['phpthumb_version'] = $phpThumb->phpthumb_version; +$ServerInfo['im_version'] = $phpThumb->ImageMagickVersion();; +$ServerInfo['gd_string'] = phpthumb_functions::gd_version(true); +$ServerInfo['gd_numeric'] = phpthumb_functions::gd_version(false); +unset($phpThumb); +?> + + + + Demo of phpThumb() - thumbnails created by PHP using GD and/or ImageMagick + + + + +This is a demo of phpThumb() (current version: v)
    +
    +Note: this server is working on GD "= 2) { + echo ', so images should be of optimal quality.'; +} else { + echo ', so images (especially watermarks) do not look as good as they would on GD v2.'; +} +?>
    + +
    +phpThumb.demo.showpic.php demo here
    +Difference between GD1 and GD2
    +
    +
    + The following images have the textured background behind them to illustrate transparency effects. + Note that some browsers, notably Internet Explorer, are incapable of displaying alpha-channel PNGs. + See my page on the PNG transparency problem. + Other modern browsers such as Mozilla/Firefox display alpha-transparent PNGs with no problems. +

    + + + +PNG transparency problem in Internet Explorer'; +$only_gd = '
    (only works with GD (any version), this server is '.($ServerInfo['gd_string'] ? 'running GD "'.$ServerInfo['gd_string'].'" so it will' : 'not running any recognized version of GD so it will not').' work)'; +$only_gd2 = '
    (only works with GD v2.0+, this server is running GD "'.($ServerInfo['gd_string'] ? $ServerInfo['gd_string'] : 'n/a').'" so it '.(($ServerInfo['gd_numeric'] >= 2) ? 'will' : 'will not').' work)'; +$only_php42 = '
    (only works with PHP v4.2.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.2.0', '>=') ? 'will' : 'will not').' work)'; +$only_php43 = '
    (only works with PHP v4.3.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.3.0', '>=') ? 'will' : 'will not').' work)'; +$only_php432 = '
    (only works with PHP v4.3.2+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.3.2', '>=') ? 'will' : 'will not').' work (correctly))'; +$only_php500 = '
    (only works with PHP v5.0.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '5.0.0', '>=') ? 'will' : 'will not').' work (correctly))'; +$php5_or_IM = '
    (only works with PHP v5.0.0+ or ImageMagick, this server is running PHP v'.phpversion().' and "'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a').'" so it '.(($ServerInfo['im_version'] && version_compare(phpversion(), '5.0.0', '>=')) ? 'will' : 'will not').' work (correctly))'; +$only_exif = '
    (only works when the EXIF extension is loaded, so on this server it '.(extension_loaded('exif') ? 'will' : 'will not').' work)'; +$only_im = '
    (requires ImageMagick, this server is running "'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a').'" so it '.($ServerInfo['im_version'] ? 'will' : 'will not').' work)'; + +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200'), 'description' => 'width=200px'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&q=10'), 'description' => 'width=200px, JPEGquality=10%'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['watermark'].'&w=400&aoe=1&bg=ffffff'), 'description' => 'width=400px, AllowOutputEnlargement enabled'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=250&sx=600&sy=5&sw=100&sh=100&aoe=1'), 'description' => 'section from (600x5 - 700x105) cropped and enlarged by 250%, AllowOutputEnlargement enabled'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.urlencode('http://silisoftware.com/images/SiliSoft.gif').'&w=100'), 'description' => 'HTTP source image'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&fltr[]=wmi|'.$img['watermark'].'|BL'), 'description' => 'width=200px, watermark (bottom-left, 75% opacity)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['square'].'&w=200&fltr[]=wmi|'.$img['watermark'].'|*|25'), 'description' => 'width=200px, watermark (tiled, 25% opacity)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=png', $phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=gif', $phpThumbBase.'src='.$img['watermark'].'&bg=00FFFF&f=jpeg'), 'description' => 'source image (GIF) transpancy with transparent output (PNG, GIF) vs. specified background color (JPEG)'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['anigif'], $phpThumbBase.'src='.$img['anigif'].'&w=25&f=gif', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=png', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=ico', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=bmp', $phpThumbBase.'src='.$img['anigif'].'&w=25&f=jpeg'), 'description' => 'resize animated GIF. Notice how output format affects the result: GIF is animated and transparent; PNG and ICO are tranparent but not animated (first frame is rendered as a still image); JPEG and BMP are neither transparent nor animated. Any filters will disable animated resizing (may be fixed in a future version).
    '.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['alpha'].'&f=png', $phpThumbBase.'src='.$img['alpha'].'&f=ico', $phpThumbBase.'src='.$img['alpha'].'&f=gif', $phpThumbBase.'src='.$img['alpha'].'&f=jpeg'), 'description' => 'PNG alpha transparency test, using test image from the PNG transparency test page'.$only_php432); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=usm|80|0.5|3'), 'description' => 'normal vs. unsharp masking at default settings'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=blur|1', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=blur|5'), 'description' => 'normal vs. blur at default (1) and heavy (5)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gblr', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sblr'), 'description' => 'normal vs. gaussian blur vs. selective blur'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=L&bg=0000FF&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['landscape'].'&w=100&h=100&far=T&bg=FF0000&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=C&bg=0000FF&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['landscape'].'&w=100&h=100&far=B&bg=FF0000&f=png&fltr[]=bord|1', $phpThumbBase.'src='.$img['portrait'].'&w=100&h=100&far=R&bg=0000FF&f=png&fltr[]=bord|1'), 'description' => 'Forced Aspect Ratio, colored background, PNG output'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=150&ar=L', $phpThumbBase.'src='.$img['landscape'].'&w=150&ar=L'), 'description' => 'auto-rotate counter-clockwise to landscape from portrait & lanscape'.$only_php42.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&hp=100&wl=200', $phpThumbBase.'src='.$img['landscape'].'&hp=100&wl=200'), 'description' => 'auto-selection of W and H based on source image orientation'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['unrotated'].'&w=150&h=150', $phpThumbBase.'src='.$img['unrotated'].'&w=150&h=150&ar=x'), 'description' => 'original image vs. auto-rotated based on EXIF data'.$only_php42.$only_exif.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&ra=30&bg=0000FF', $phpThumbBase.'src='.$img['landscape'].'&w=200&ra=30&f=png', $phpThumbBase.'src='.$img['alpha'].'&ra=30&f=png', $phpThumbBase.'src='.$img['alpha'].'&ra=30&f=gif'), 'description' => 'Rotated 30° (counter-clockwise), width=200px, blue background vs. transparent background vs. rotated image with pre-existing alpha'.$only_php42.$only_gd); +//$Examples[] = array('getstrings' => array($phpThumbBase.'src=images/1-bit.gif&ra=30&f=png', $phpThumbBase.'src=images/4-bit.gif&ra=30&f=png', $phpThumbBase.'src=images/8-bit.gif&ra=30&f=png'), 'description' => '2-color, 16-color, 256-color transparent GIFs'.$only_php42.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&h=300&far=1&bg=CCCCCC', $phpThumbBase.'src='.$img['landscape'].'&w=200&h=300&iar=1'), 'description' => 'Normal resize behavior (left) vs. Forced non-proportional resize (right)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=150&h=150&zc=1', $phpThumbBase.'src='.$img['portrait'].'&w=150&h=150&zc=1'), 'description' => 'Zoom-Crop'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bord|2|20|10|009900&f=png'), 'description' => '2px border, curved border corners (20px horizontal radius, 10px vertical radius)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ric|50|20&f=png'), 'description' => 'curved border corners (20px vertical radius, 50px horizontal radius)
    '.$png_alpha.$only_gd2.$only_php432); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sat|75', $phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sat|-100'), 'description' => 'saturation -75% vs. normal vs. -100%'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ds|75', $phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=ds|-100'), 'description' => 'desaturated 75% vs. normal vs. -100%'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=clr|25|00FF00'), 'description' => 'colorized 25% to green (#00FF00)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gray', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=sep'), 'description' => 'grayscale vs. sepia'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask3'].'&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask1'].'&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask2'].'&f=jpeg&bg=9900CC&q=100'), 'description' => 'Assorted alpha masks (seen below) applied
    '.$png_alpha.$only_php432.'
    JPEG/GIF output is flattened to "bg" background color'.$only_gd2.'
    '); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=drop|5|10|000000|225&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask3'].'&fltr[]=drop|5|10|000000|225&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=drop|5|10|000000|225&fltr[]=elip&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&fltr[]=drop|5|10|000000|225&f=png'), 'description' => 'Drop shadow. Note how the order in which filters are applied matters.'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=elip&f=jpeg&bg=00FFFF'), 'description' => 'Elipse
    '.$png_alpha.$only_php432.'
    JPEG/GIF output is flattened to "bg" background color'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|x', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|y', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=flip|xy'), 'description' => 'flipped on X, Y and X+Y axes'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bvl|10|FFFFFF|000000', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=bvl|10|000000|FFFFFF'), 'description' => '10px bevel edge filter'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=fram|3|2|CCCCCC|FFFFFF|000000', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=fram|3|2|CC9966|333333|CCCCCC'), 'description' => '3+2px frame filter'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=neg'), 'description' => 'Negative filter (inverted color)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=th|105', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask1'].'&fltr[]=th|105&f=png'), 'description' => 'Threshold filter; showing preserved alpha channel'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=150', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=rcd|16|1', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=rcd|16|0', $phpThumbBase.'src='.$img['portrait'].'&w=150&fltr[]=gray&fltr[]=rcd|8|1'), 'description' => 'ReduceColorDepth filter; original vs. 16-color dither vs. 16-color nodither vs. 4-gray dither'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['levels'].'&w=200', $phpThumbBase.'src='.$img['levels'].'&w=200&fltr[]=lvl'), 'description' => 'original vs. Levels filter (default settings)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=200', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=wb', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=wb&fltr[]=lvl'), 'description' => 'original vs. White Balance vs. White Balance + Levels'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=hist|rgb', $phpThumbBase.'src='.$img['levels'].'&w=200&fltr[]=hist|*'), 'description' => 'histograms of RGB vs. grayscale'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=edge'), 'description' => 'Edge Detect filter'.$php5_or_IM.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=emb'), 'description' => 'Emboss filter'.$php5_or_IM.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=mean'), 'description' => 'Mean Removal filter'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=300&fltr[]=smth'), 'description' => 'Smooth filter'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gam|0.6', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=gam|1.6'), 'description' => 'Gamma corrected to 0.6 vs. 1.6'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=brit|50', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=brit|-50'), 'description' => 'Brightness filter (original vs. +50 vs. -50)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=cont|50', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=cont|-50'), 'description' => 'Contrast filter (original vs. +50 vs. -50)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=over|'.$img['frame1'].'|0', $phpThumbBase.'src='.$img['portrait'].'&w=200&fltr[]=over|'.$img['frame2'].'|1'), 'description' => 'Overlay vs. Underlay

    Original over/under images:
    '.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|phpThumb|18|C|FF0000|loki.ttf|100|5|20&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|copyright+'.date('Y').'|3|BR|00FFFF||50&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|copyright+'.date('Y').'%0AphpThumb()|3|L|00FFFF&f=png'), 'description' => 'Text overlay, TTF and built-in fonts, multiple lines, metacharacters (height, width)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|thumbnail+=+^Xx^Y|3|BR|00FFFF||50&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|click%0Ahere%0A^FkkB|10|L|FF00FF|arial.ttf|100|0||333399|50|y&f=png', $phpThumbBase.'src='.$img['landscape'].'&w=200&fltr[]=wmt|resized:+^Xx^Y+to+^xx^y|10|B|FFFFFF|arial.ttf|100|0||000000|100|x&f=png'), 'description' => 'metacharacters (height, width), background color, background extend'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'new=FF0000&w=100&h=50&fltr[]=bvl|10&fltr[]=wmt|hello|14|C|00FFFF|arial.ttf&f=png', $phpThumbBase.'new=FF0000|25&w=150&h=50&fltr[]=bvl|10&fltr[]=wmt|25%+opaque|14|C|0066FF|arial.ttf&f=png'), 'description' => 'Image created with "new", red background, bevel, TTF text'.$only_gd); + +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['bmp'].'&w=200'), 'description' => 'BMP source, width=200px'); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['tiff'], $phpThumbBase.'src='.$img['tiff'].'&w=200&aoe=1'), 'description' => 'TIFF source, width=200px'.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'src='.$img['wmf'].'&w=200'), 'description' => 'WMF source, width=200px'.$only_im); +//$Examples[] = array('getstrings' => array(''), 'description' => ''); + +foreach ($Examples as $key => $ExamplesArray) { + echo '#'.$key.''; + echo '
    '; + foreach ($ExamplesArray['getstrings'] as $dummy => $GETstring) { + echo ''; + echo ''; + echo ' '; + } + echo '
    '; + echo '<img src="'.implode('">'."\n".'<img src="', $ExamplesArray['getstrings']).'">'; + echo $ExamplesArray['description'].'
    '; + echo '


    '; +} + +echo '#pathinfo'; +echo '
    '; +echo ''; +echo '
    '; +echo '<img src="../phpThumb.php/fltr[]=sep;200x200;'.$img['portrait'].'">'; +echo 'PATH_INFO example
    '; +echo '


    '; + +?> + + +
    + + + + + + + + + + + + + + + + +
    + Illustration of potential difference between GD1.x and GD2.x
    + In most cases the thumbnails produced by phpThumb() on GD v1.x are perfectly + acceptable, but in some cases it may look ugly. Diagonal lines and reducing a + very large source image increase chance for bad results (the house/sky picture + has both problems). Here are three static examples: +
    GD v2.0.15kayak.jpg generated with phpThumb() on GD v2.0.15bottle.jpg generated with phpThumb() on GD v2.0.15sky.jpg generated with phpThumb() on GD v2.0.15
    GD v1.6.2kayak.jpg generated with phpThumb() on GD v1.6.2bottle.jpg generated with phpThumb() on GD v1.6.2sky.jpg generated with phpThumb() on GD v1.6.2

    +
    +
    + +Demo of phpThumb.demo.showpic.php
    +
    +Small picture (400x300), window opened at wrong size (640x480):
    + +
    +
    +Big picture (2272x1704), window opened at wrong size (640x480):
    + +
    +
    +
    + +'; +foreach ($img as $key => $value) { + echo '
  • '.basename($value).'
  • '; +} +echo '
    '; + +?> + + \ No newline at end of file diff --git a/site/runshops/phpthumb/demo/phpThumb.demo.object.php b/site/runshops/phpthumb/demo/phpThumb.demo.object.php new file mode 100644 index 0000000..39ae163 --- /dev/null +++ b/site/runshops/phpthumb/demo/phpThumb.demo.object.php @@ -0,0 +1,72 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.object.php // +// James Heinrich // +// // +// Example of how to use phpthumb.class.php as an object // +// // +////////////////////////////////////////////////////////////// + +// Note: phpThumb.php is where the caching code is located, if +// you instantiate your own phpThumb() object that code is +// bypassed and it's up to you to handle the reading and +// writing of cached files. + + + +require_once('../phpthumb.class.php'); + +// create 3 sizes of thumbnail +$thumbnail_widths = array(160, 320, 640); +foreach ($thumbnail_widths as $thumbnail_width) { + + // Note: If you want to loop through and create multiple + // thumbnails from different image sources, you should + // create and dispose an instance of phpThumb() each time + // through the loop and not reuse the object. + $phpThumb = new phpThumb(); + + // set data + $phpThumb->setSourceFilename($_FILES['userfile']['tmp_name']); + // or $phpThumb->setSourceData($binary_image_data); + // or $phpThumb->setSourceImageResource($gd_image_resource); + + // set parameters (see "URL Parameters" in phpthumb.readme.txt) + $phpThumb->w = $thumbnail_width; + //$phpThumb->h = 100; + //$phpThumb->fltr[] = 'gam|1.2'; + + // set options (see phpThumb.config.php) + // here you must preface each option with "config_" + $phpThumb->config_output_format = 'jpeg'; + $phpThumb->config_imagemagick_path = '/usr/local/bin/convert'; + //$phpThumb->config_allow_src_above_docroot = true; // needed if you're working outside DOCUMENT_ROOT, in a temp dir for example + + // generate & output thumbnail + $output_filename = './thumbnails/'.basename($_FILES['userfile']['name']).'_'.$thumbnail_width.'.'.$phpThumb->config_output_format; + if ($phpThumb->GenerateThumbnail()) { // this line is VERY important, do not remove it! + if ($output_filename) { + if ($phpThumb->RenderToFile($output_filename)) { + // do something on success + echo 'Successfully rendered:
    '; + } else { + // do something with debug/error messages + echo 'Failed (size='.$thumbnail_width.'):
    '.implode("\n\n", $phpThumb->debugmessages).'
    '; + } + } else { + $phpThumb->OutputThumbnail(); + } + } else { + // do something with debug/error messages + echo 'Failed (size='.$thumbnail_width.'):
    '.implode("\n\n", $phpThumb->debugmessages).'
    '; + } + + // remember to unset the object each time through the loop + unset($phpThumb); +} + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/demo/phpThumb.demo.random.php b/site/runshops/phpthumb/demo/phpThumb.demo.random.php new file mode 100644 index 0000000..40e3209 --- /dev/null +++ b/site/runshops/phpthumb/demo/phpThumb.demo.random.php @@ -0,0 +1,95 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.random.php // +// James Heinrich // +// // +// Display a random image from a specified directory. // +// Run with no parameters for usage instructions. // +// // +////////////////////////////////////////////////////////////// + +function SelectRandomImage($dirname='.', $portrait=true, $landscape=true, $square=true) { + // return a random image filename from $dirname + // the last 3 parameters determine what aspect ratio of images + // may be returned + $possibleimages = array(); + if ($dh = opendir($dirname)) { + while ($file = readdir($dh)) { + if (is_file($dirname.'/'.$file) && eregi('\.(jpg|jpeg|gif|png|tiff|bmp)$', $file)) { + if ($gis = @GetImageSize($dirname.'/'.$file)) { + if ($portrait && ($gis[0] < $gis[1])) { + // portrait + $possibleimages[] = $file; + } elseif ($landscape && ($gis[0] > $gis[1])) { + // landscape + $possibleimages[] = $file; + } elseif ($square) { + // square + $possibleimages[] = $file; + } + } + } + } + closedir($dh); + } + if (empty($possibleimages)) { + return false; + } + if (phpversion() < '4.2.0') { + mt_srand(time()); + } + $randkey = mt_rand(0, count($possibleimages) - 1); + return realpath($dirname.'/'.$possibleimages[$randkey]); +} + +if (@$_REQUEST['dir']) { + if (is_dir($_REQUEST['dir'])) { + + if (!@$_REQUEST['o']) { + $_REQUEST['o'] = 'PLS'; + } + $_REQUEST['o'] = strtoupper($_REQUEST['o']); + $portrait = (strpos(@$_REQUEST['o'], 'P') !== false); + $landscape = (strpos(@$_REQUEST['o'], 'L') !== false); + $square = (strpos(@$_REQUEST['o'], 'S') !== false); + $randomSRC = SelectRandomImage($_REQUEST['dir'], $portrait, $landscape, $square); + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + $randomSRC = str_replace('\\', '/', eregi_replace('^'.realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath($randomSRC))); + } else { + $randomSRC = str_replace(realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath($randomSRC)); + } + + $otherParams = array(); + foreach ($_GET as $key => $value) { + if (($key == 'dir') || ($key == 'o')) { + continue; + } + if (is_array($value)) { + foreach ($value as $vkey => $vvalue) { + $otherParams[] = urlencode($key).'['.urlencode($vkey).']='.urlencode($vvalue); + } + } else { + $otherParams[] = urlencode($key).'='.urlencode($value); + } + } + header('Location: ../phpThumb.php?src='.urlencode($randomSRC).'&'.implode('&', $otherParams)); + exit; + + } else { + die($_REQUEST['dir'].' is not a directory'); + } + +} else { + + echo 'Usage: '.basename($_SERVER['PHP_SELF']).'?dir=<directory>&<phpThumb parameters>&o=(P|L|S)

    Examples:
      '; + echo '
    • '.basename($_SERVER['PHP_SELF']).'?./images/&o=L (landscape images only)
    • '; + echo '
    • '.basename($_SERVER['PHP_SELF']).'?./images/&o=PS (portrait or square images only)
    • '; + echo '
    '; + +} + +?> diff --git a/site/runshops/phpthumb/demo/phpThumb.demo.showpic.php b/site/runshops/phpthumb/demo/phpThumb.demo.showpic.php new file mode 100644 index 0000000..e7162f3 --- /dev/null +++ b/site/runshops/phpthumb/demo/phpThumb.demo.showpic.php @@ -0,0 +1,98 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +// // +// phpThumb.demo.showpic.php // +// James Heinrich // +// 23 Feb 2004 // +// // +// This code is useful for popup pictures (e.g. thumbnails // +// you want to show larger, such as a larger version of a // +// product photo for example) but you don't know the image // +// dimensions before popping up. This script displays the // +// image with no window border, and resizes the window to // +// the size it needs to be (usually better to spawn it // +// large (600x400 for example) and let it auto-resize it // +// smaller), and if the image is larger than 90% of the // +// current screen area the window respawns itself with // +// scrollbars. // +// // +// Usage: // +// window.open('showpic.php?src=big.jpg&title=Big+picture', // +// 'popupwindowname', // +// 'width=600,height=400,menubar=no,toolbar=no') // +// // +// See demo linked from http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +?> + + + + <?php echo @$_GET['title']; ?> + + + + +'."\n"; + echo 'if (((screen.width * 1.1) > '.$imgdata[0].') || ((screen.height * 1.1) > '.$imgdata[1].')) {'."\n"; + // screen is large enough to fit whole picture on screen with 10% margin + echo 'document.writeln(\'\');'; + echo 'CrossBrowserResizeInnerWindowTo('.$imgdata[0].', '.$imgdata[1].');'."\n"; + echo '} else {'."\n"; + // image is too large for screen: add scrollbars by putting the image inside an IFRAME + echo 'document.writeln(\'\');'; + echo '}'."\n"; + echo ''; + +} else { + + // cannot determine correct window size, or correct size too large: add scrollbars by putting the image inside an IFRAME + echo ''; + +} + +?> + + \ No newline at end of file diff --git a/site/runshops/phpthumb/demo/readme.demos.txt b/site/runshops/phpthumb/demo/readme.demos.txt new file mode 100644 index 0000000..483dfc1 --- /dev/null +++ b/site/runshops/phpthumb/demo/readme.demos.txt @@ -0,0 +1,41 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb() included and related demos // +// /// +////////////////////////////////////////////////////////////// + +The phpThumb() distribution includes several demos, and it +should be self-evident what they do when you run them: + +* phpThumb.demo.demo.php - shows a wide variety of samples, + basically all the different features and filters of phpThumb. + Note: sample image files are not included in the distribution + but can be downloaded from http://phpthumb.sourceforge.net/demo + +* phpThumb.demo.check.php - configuration checker, will check + your config file and server configuration and warn of any + potential problems + +* phpThumb.demo.object.php - example of how to call phpThumb + as an object. + +* phpThumb.demo.random.php - select & display a random thumbnail + from a directory of images. + +* phpThumb.demo.showpic.php - auto-resizes a popup window to + match the dimensions of the image it is displaying + + + +Other people have created useful demos and/or extensions to +phpThumb(). Some of these I know of are: + +* iManager - http://www.j-cons.com/news/ +* iBrowser - http://www.j-cons.com/news/ +* ThumbnailSelector - http://www.silisoftware.com/scripts/ThumbnailSelector + +If you know of any others you think should be mentioned here +please let me know: info@silisoftware.com \ No newline at end of file diff --git a/site/runshops/phpthumb/docs/phpthumb.changelog.txt b/site/runshops/phpthumb/docs/phpthumb.changelog.txt new file mode 100644 index 0000000..e75aa7f --- /dev/null +++ b/site/runshops/phpthumb/docs/phpthumb.changelog.txt @@ -0,0 +1,1040 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// + +¤ = structure change or important new feature +* = less important new feature or change + +v1.7.0 - February 15, 2006 + ¤ ImageMagick output is used directly far more frequently + for much improved speed and minor quality improvement. + ¤ ImageMagick now processes most of the image filters if + possible (will fall back to GD methods if unavailable) + ¤ GD support is now optional if ImageMagick is installed. + Known limitations include: + - no support for HTTP source images + - ICO output is buggy (in some ImageMagick versions) + - most &fltr[] filters don't work at all + - 'ar', 'ra', 'far' don't work + ¤ Added output support for ICO (icon) format (&f=ico). + Currently only supports single-image icons, but multi- + resolution support may be added in future versions + New file: phpthumb.ico.php + ¤ Added output support for BMP (bitmap) format (&f=bmp). + Currently only supports 24-bit RGB format (for simplicity) + ¤ Added new configuration & compatability checker + New file: demo/phpThumb.demo.check.php + * ImageMagick-generated thumbnails now have extra hidden + contents (EXIF data, etc) stripped (by using -thumbnail + instead of -resize) resulting in smaller filesizes + * Added background fill color, opacity and extent options to + 'wmt' filter (thanks craigØpc-fanatics*com) + * Added metacharacter (^*) support for 'wmt', currently: + source filesize in bytes (^Fb), kB (^Fk), MB (^Fm), + source image width (^X), source image height (^Y), + thumbnail width (^x), thumbnail height (^y) and caret (^^) + (Feature Request #1357815) + (thanks ticklemeozmoØusers*sourceforge*net) + * Moved ImageDestroy call from OutputThumbnail to end of + phpThumb.php to allow multiple calls to OutputThumbnail + * Added config_http_user_agent for site with browsersniffers + (thanks redrobØgmail*com) + * Added $PHPTHUMB_CONFIG['disable_pathinfo_parsing'] (default + false) which disables parsing $_SERVER[PATH_INFO] for + parameters. If you want to parse PATH_INFO, set to false + * Added $PHPTHUMB_CONFIG['disable_imagecopyresampled'] (default + false) which replaces ImageCopyResampled with + ImageCopyResampleBicubic for buggy PHP-GD versions + (thanks g*pelagattiØnetface*it) + * Added $PHPTHUMB_CONFIG['cache_prefix'] to allow sharing of + cache files across virtual servers (Feature Request #1395332) + (thanks doggyfrØusers*sourceforge*net) + * Added $PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] with + default=true (increased speed) to allow direct passthru of + images that don't have GD support. (Feature Request #1396446) + (thanks zedboyØusers*sourceforge*net) + * Removed $PHPTHUMB_CONFIG['cache_differentiate_offsite'] because + it is now automatically tied in with nooffsitelink_enabled + (thanks doggysworldØlibertysurf*fr) + * Removed phpThumb.demo.cacheconvert2.php + * Debug messages are now passed back from filters + * $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] now + defaults to true for much-improved cached performance + (thanks redrobØgmail*com) + * $PHPTHUMB_CONFIG['cache_differentiate_offsite'] now defaults + to false + * Added $PHPTHUMB_DEFAULTS['ar']='x' to phpThumb.config.php.default + * Added ImageDestroy($this->gdimg_source) to GenerateThumbnail() + to save memory before applying image filters + * gd_info() no longer member of phpthumb_functions + * cache files now default to using SERVER_NAME without 'www.' + * phpUnsharpMask::applyUnsharpMask() should be faster under PHP5 by + using ImageFilter(IMG_FILTER_GAUSSIAN_BLUR) when radius==1 + * Added alternate CURL method for HTTP source images if + allow_url_fopen is disabled (thanks webweberØmotiondraw*com) + * Replaced $this->osslash with DIRECTORY_SEPARATOR constant + * Bugfix: [#1398327] 'new' got broken (1x1 images) + * Bugfix: [#1412552] HTTP source images with special characters were + not getting urlencoded + * Bugfix: ImageSaveAlpha errors on GD v2.0.0 + * Bugfix: phpThumbDebug now entirely disabled if high_security=true + * Bugfix: source images with transparency lost transparency when + rotated (thanks roalklØyahoo*com) + * Bugfix: square source images were not resized when only (w|h)(p|l) + parameters passed + * Bugfix: source images are passed through unmodified in more cases + * Bugfix: ImageMagick not used on systems where it exists outside + defined open_basedir + * Bugfix: ImageMagickVersion() now returns correct versionstring + * Bugfix: ImageMagick warnings no longer cause ImageMagick to fail + * Bugfix: ErrorImage no longer fatal to phpThumbDebug + * Bugfix: "Array to string conversion" in foreach($a as $v) loops + (thanks zeeshanØtargetedmedia*co*uk) + * Bugfix: safe mode warnings in ImageCreateFromStringReplacement + (thanks adminØalex-home*net) + * Bugfix: nooffsitelink broken if !nooffsitelink_require_refer + (thanks depronØgmx*net) + * Bugfix: phpThumb failed when magic_quotes_runtime=true + (thanks stansawyerØyahoo*com) + * Bugfix: several issues with HTTP image sources + (thanks redrobØgmail*com) + * Bugfix: phpThumb_tempnam() would return incomplete temp filenames + under Windows, which may result in orphaned zero-byte temp files + in C:\ if multiple drives exist + +v1.6.2 - November 24, 2005 + ¤ Animated GIF output is now possible if ImageMagick is + available and no filters (other than resize) are applied + (thanks brandenbassØgmail*com for idea) + * Added $PHPTHUMB_CONFIG['cache_force_passthru'] to work + around cached-image-only-works-second-time issue + (thanks yakoØ11y11*com) + * Bugfix: black borders on some image edges + (thanks atelierØdelirius*ch && chuckØcatalyststudio*com) + * Bugfix: uncaught PHP warning in RenderToFile DebugMessage + * Bugfix: allow phpThumbDebug in noGD PHP installations + * Bugfix: 'hash' warning in high_security mode + (thanks bernhardØwtf*at) + * Bugfix: non-TTF rotated text watermarks now work (unrotated) + with no warnings if ImageRotate is unavailable + (thanks aparviaiØusers*sourceforge*net) + +v1.6.1 - August 26, 2005 + ¤ Filters now use GD functions where available (using + ImageFilter, only available in PHP v5.0.0+ with bundled + version of GD). Enabled for: colorize, negative, + grayscale, brightness, contrast, gaussian blur, selective + blur, mean removal (thanks donlaurØmac*com) + ¤ Added config_prefer_imagemagick (defaults=true) + ¤ Added phpthumb_filters::Grayscale() 'gray' + ¤ Added phpthumb_filters::ReduceColorDepth() 'rcd' + ¤ Added phpthumb_filters::Brightness() 'brit' + ¤ Added phpthumb_filters::Contrast() 'cont' + ¤ Added phpthumb_filters::Saturation() 'sat' + ¤ Added phpthumb_filters::EdgeDetect() 'edge' [PHP5 only] + ¤ Added phpthumb_filters::BlurGaussian() 'gblr' [PHP5 only] + ¤ Added phpthumb_filters::BlurSelective() 'gblr' [PHP5 only] + ¤ Added phpthumb_filters::MeanRemoval() 'mean' [PHP5 only] + ¤ Added phpthumb_filters::Smooth() 'smth' [PHP5 only] + * New timing debug info in phpThumbDebug + * Added config_cache_differentiate_offsite + * config_die_on_error now defaults to false + * ResolveSource works better + * cache filenames with 'fltr' parameters have changed + * Filters now skip processing if amount=0 or similar + * [#1263051] 'far' now accepts L,R,T,B,C as values giving + alignment of left/right/top/bottom/center respectively. + Old value of '1' defaults to centered + (thanks webgrappaØusers*sourceforge*net) + * Bugfix: RenderToFile() now fails properly when output format + is unknown + * Bugfix: PNG transparency wasn't working with 'far' + * Bugfix: source images with EXIF thumbnails that differ in + aspect ratio no longer use EXIF thumbnails as source unless + no other options exist + * Bugfix: setting 'src' with setParameter now invokes + setSourceFilename to properly set $this->sourceFilename + (thanks Gazou) + * Bugfix: 'zc' had poor quality when used with ImageMagick + * Bugfix: 'aoe' parameter broken when not using ImageMagick + (thanks frankieali4Øhotmail*com) + * Bugfix: fixed issue with symbolic links + (thanks hornet136Øgmail*com) + * Bugfix: config_max_source_pixels now defaults to same + calculation as used in phpThumb.config.php + (thanks vukshaØhotmail*com) + * Bugfix: Offsite cached thumbnails no longer use unique + referer (now either nothing or "_offsite") + (thanks swaayeØyahoo*com) + * Bugfix: "Unknown image type identified by “] + where is the target hex color to white balance + on, this color is what "should be" white, or light + gray. The filter attempts to maintain brightness so + any gray color can theoretically be used. If is + omitted the filter guesses based on brightest pixels + in each of RGB + ¤ Cached files are used by a Location header instead of + being passed through phpThumb.php using readfile + (thanks newtnØthrillnerds*com) + * Added 'cache_source_filemtime_ignore_local' and + 'cache_source_filemtime_ignore_remote' configurations + to ignore source modification and/or removal + (thanks raynerapeØgmail*com) + * Added 'md5s' parameter, which is the MD5 hash of the + source image -- if this parameter is passed with the + hash of the source image then the source image is not + checked for existance or modification and the cached + file is used (if available). If 'md5s' is passed an + empty string then phpThumb.php dies and outputs the + correct MD5 hash value. This parameter is the single- + file equivalent of 'cache_source_filemtime_ignore_*' + configuration paramters (thanks raynerapeØgmail*com) + * Added /demo/phpThumb.demo.object.php + * Unused parameter 'bgt' removed + * Added empty /cache/source/ directory to distribution + * Added /demo/ and /docs/ and /fonts/ directories + * Set default config_use_exif_thumbnail_for_speed = false + * Bugfix: Wrapped output buffering around all + include_once calls to prevent headers getting sent + accidentally + * Bugfix: md5_file and imagecolorallocatealpha calls + were undefined under PHP v4.1.x (thanks tomØemile*com) + * Bugfix: default 'f' parameter ('jpeg') overrode + config_output_format in object mode + (thanks mailØmmjaeger*com) + * Bugfix: suppressed error message for IIS shell_exec + errors (thanks tomØemile*com) + * Bugfix: Added PHP version check for stream_set_timeout + for HTTP sources (thanks raynerapeØgmail*com) + * Bugfix: overlay margins of 0.5-1.0 cause invalid image + dimensions error (thanks mailØmmjaeger*com) + * Bugfix: underlay margins were not working + (thanks mailØmmjaeger*com) + * Bugfix: [#1187735] EXIF thumbnails were incorrectly + output to the browser directly if requested thumbnail + exactly matched EXIF dimensions + (thanks rebootØusers*sourceforge*net) + +v1.5.2 - April 20, 2005 + ¤ phpThumb.config.php is renamed to + phpThumb.config.php.default to prevent accidental + overwriting. Please migrate your old settings to the new + file, delete your old config and rename the default to + phpThumb.config.php + ¤ Added new filters: + - 'blur' (Blur) [ex: &fltr[]=blur|] + where (0 < < 25) (default = 1) + (thanks thoensiØnetcom*no for code) + - 'hist' (Histogram) + [ex: &fltr[]=hist|||||||] + Where is the color band(s) to display, from back + to front (one or more of "rgba*" for Red Green Blue + Alpha and Grayscale respectively); + is a semicolon-seperated list of hex colors to + use for each graph band (defaults to FF0000, 00FF00, + 0000FF, 999999, FFFFFF respectively); + and are the width and height of the overlaid + histogram in pixels, or if <= 1 then percentage of + source image width/height; + is the alignment (same as for "wmi" and "wmt"); + is opacity from 0 to 100; + is the edge (and inter-tile) margin in percent + - 'over' (OVERlay/underlay image) overlays an image on + the thumbnail, or overlays the thumbnail on another + image (to create a picture frame for example) + [ex: &fltr[]=over||||] + where is the image filename; is "0" (default) + for overlay the image on top of the thumbnail or "1" + for overlay the thumbnail on top of the image; is + the margin - can be absolute pixels, or if < 1 is a + percentage of the thumbnail size [must be < 0.5] + (default is 0 for overlay and 10% for underlay); + is opacity (0 = transparent, 100 = opaque) + (thanks raynerapeØgmail*com, shabazz3Ømsu*edu) + - 'gray' (GRAYscale) [ex: &fltr[]=gray] + is an alias to 100% desaturation + * New configuration 'cache_source_directory' allows the + unprocessed source image to be cached when source is + HTTP or from a database (thanks raynerapeØgmail*com) + * Added 'cache' subdirectory to phpThumb distribution + since this is the default location for the cache + folder. + * Default value for config_error_die_on_source_failure + changed to true (thanks shabazz3Ømsu*edu) + * Added checks to make sure $this->gdimg_output is a + resource before allowing calls to RenderToFile or + OutputThumbnail + * Better error messages when phpThumb.config.php missing + * Bugfix: watermark overlay margins were wrong + * Bugfix: 'lvl' filter no longer processes if not needed + * Bugfix: off-server thumbnail error message was wrong + * Bugfix: several PHP safe mode fixes + (thanks virginiaØalertbutnotalarmed*com) + * Bugfix: cache filenames broken for filter parameters + with paths (thanks srcericØusers.sourceforge.net) + +v1.5.1 - April 06, 2005 + * Added some security upgrades: + - 'config_*' parameters cannot be passed by GETstring + - 'config_nooffsitelink_require_refer' is a new option + (disabled by default) that only allows calls to + phpThumb() from a refering domain listed in + 'config_nooffsitelink_valid_domains' + - disallowed paramters now generate an error image if + present in the GETstring + - 'high_security_enabled' if set to true enabled new + mode of verification, and requires a small function + to generate a hash for calls to phpThumb: + echo ''; + This function is supplied at the bottom of + phpThumb.config.php (thanks paulØstonie*co*uk) + ¤ Added new parameter "new" (phpThumb.php only) which can + create a new image without using "src" parameter. Set + "&new=|" where is the background hex color, + is (optional) opacity (0=transparent, 100=opaque). + (thanks mailØmmjaeger*com) + ¤ Added new filters: + - 'sep' (Sepia) [ex: &fltr[]=sep||] + where is a number between 0 and 100 for the + amount of colorization (default=50), and is + the hex color to colorize to (default=A28065). + (thanks mailØmmjaeger*com) + - 'lvl' (Levels) [ex: &fltr[]=lvl||| + where can be one of 'r', 'g', 'b', 'a' (for + Red, Green, Blue, Alpha respectively), or '*' for all + channels based on average grayscale value (default). + and are the clip points for the levels + (range = 0-255) and are set to clip 0.1% of each end + by default. Use -1 for min and/or max to invoke auto- + detect mode. Using default parameters (&fltr[]=lvl) + is similar to Auto Contrast in Adobe Photoshop. + * Bugfix: Image MIME header was incorrect for cached + images. + * Bugfix: Cache was broken for images pulled from a + database in phpThumb.php + (thanks dragutin*cvetkovicØdragontech-ltd*com) + * Bugfix: Hotlink/Offsite prevention was broken when + image was already cached. + * Bugfix: ImageMagick path was incorrect in some cases + (thanks joshgØtwcny*rr*com) + * Bugfix: ProportionalResize() in phpthumb.functions.php + had a broken check for default values + (thanks Bert*ClaeysØarinso*com) + * Bugfix: transparency now preserved for GIF & PNG input + (thanks tristanØcyrax*ch) + * Bugfix: transparency now supported for GIF output + (thanks j_ivanovØabv*bg) + * Bugfix: alpha transparency could be lost in ApplyMask() + (thanks analyzerxØgmail*com) + * Bugfix: errors on 16/32-bit BMPs + (thanks mattØhellstrominc*com) + * Bugfix: Added datestamp to cached filenames for remote + (HTTP) files, and better warning for caching + (thanks a*gambinoØabramo*it) + * Faster BMP parsing (thanks sgeppertØmail*utexas*edu) + * Added 'error_die_on_source_failure' configuration to + allow invalid source images to show an error rather + than output unmodified source image. + (thanks mindpixelØgmail*com) + * Added $phpThumb->fatalerror which will contain the + text of the fatal error if 'error_die_on_error' is + false. (thanks mindpixelØgmail*com) + +v1.5.0 - February 4, 2005 + * Added new filter parameter 'fltr' that is an array and + can apply multiple effects in sequence. Current filters + that can be called are: + - 'gam' (Gamma Correction) [ex: &fltr[]=gam|] + where can be a number >0 to 10+ (default 1.0) + - 'ds' (DeSaturate) [ex: &fltr[]=ds|] + where is a number between zero (no change) + and 100 (complete desaturation -- grayscale), or it + can be a negative number for saturation boost. + (thanks mailØmmjaeger*com) + - 'clr' (Colorize) [ex: &fltr[]=clr||] + where is a number between 0 and 100 for the + amount of colorization, and is the hex color + to colorize to. (thanks mailØmmjaeger*com) + - 'neg' (Negative) [ex: &fltr[]=neg] + inverts the color + - 'th' (ThresHold) [ex: &fltr[]=th|] (range 0-255) + every grayscale pixel brighter than is set to + white, every darker pixel is set to black + (thanks mailØmmjaeger*com) + - 'usm' (UnSharpMask) [ex: &fltr[]=usm|||] + where is the amount (default = 80), is the + radius (default = 0.5), is the threshold + (default = 3). + - 'wmi' (WaterMarkImage) + [ex: &fltr[]=wmi||||] where is the + filename of the image to overlay, is the + alignment (one of BR, BL, TR, TL, C, R, L, T, B, * + where B=bottom, T=top, L=left, R=right, C=centre, + *=tile), is opacity from 0 to 100, is the + edge (and inter-tile) margin in percent + - 'wmt' (WaterMarkText) + [ex: &fltr[]=wmt||||||||] + where: + is the text to use as a watermark, + is the font size (1-5 for built-in font, or point + size for TrueType fonts), + is the alignment (one of BR, BL, TR, TL, C, R, L, + T, B, * where B=bottom, T=top, L=left, R=right, + C=centre, *=tile), + is the hex color of the text + is the filename of the TTF file (optional, if + omitted a built-in font will be used) + is opacity from 0 to 100, + is the edge (and inter-tile) margin in percent + is the angle + (thanks mailØmmjaeger*com) + - 'flip' [ex: &fltr[]=flip|x or &fltr[]=flip|y] + flip image on X or Y axis + (thanks mailØmmjaeger*com) + - 'elip' [ex: &fltr[]=elip] + similar to rounded corners but more extreme + (thanks mailØmmjaeger*com) + - 'mask' [ex: &fltr[]=mask|filename.png] + greyscale values of mask are applied as the alpha + channel to the main image. White is opaque, black + is transparent. + - 'bvl' (BeVeL) [ex: &fltr[]=bvl|||] + where is the bevel width, is the hex color + for the top and left shading, is the hex color + for the bottom and right shading + (thanks mailØmmjaeger*com) + - 'fram' (FRAMe) draws a frame, similar to border but + more configurable (thanks mailØmmjaeger*com) + [ex: &fltr[]=fram|||||] + where is the width of the main border, is + the width of each side of the bevel part, is the + hex color of the main border, is the highlight + bevel color, is the shadow bevel color + - 'drop' (DROP shadow) + [ex: &fltr[]=drop||||] + where is distance from image to shadow, is + width of shadow fade (not yet implemented), is + the hex color of the shadow, and is the angle of + the shadow (default=225) + - 'ric' (Rounded Image Corners) + [ex: &fltr[]=ric||] + where is the horizontal corner radius, + is the vertical corner radius + * Split out filter functions into phpthumb.filters.php + * 'usa','usr','ust' parameters have been removed and + replaced with the 'fltr' call (see above) + * 'wmf','wma','wmp','wmm' parameters have been removed + and replaced with the 'fltr' call (see above) + * 'brx','bry','bw' parameters have been removed + and replaced with the 'fltr' call (see above) + * 'bw=0' to force aspect ratio has been replaced by + 'far=1' (force aspect ratio) + * Filters that produce transparent sections (such as + Rounded Corners, Ellipse, Mask, Rotate) are now output + as 32-bit/alpha PNG, or flattened with "bg" background + color for JPEG/GIF output (thanks mailØmmjaeger*com) + * Added 'zc' (Zoom Crop) parameter + (thanks arcookeØgmail*com, mailØmmjaeger*com, + pl16056Ømacnews*de, kezzasmØusers*sourceforge*net, etc) + * AutoRotate now can use EXIF orientation tag ('ar=x') + * Added 'ttf_directory' configuration parameter for + TrueType watermarks (thanks mailØmmjaeger*com) + * Added "Last-Modified" header to cache portion of + phpThumb.php which should allow better user-side + caching of thumbnails. (thanks derekØnetsimple*net) + * Added 'cache_disable_warning' configuration which will + cause an error image to be displayed if the cache + directory isn't configured, unless explicitly disabled + * Added 'nooffsitelink_enabled' configuration which + prevents linking to thumbnails on your server from + another domain. Defaults to watermaking linked images + with text warning message. + (thanks anteØabstraktmedia*com) + * Added 'error_image_width' & 'error_image_height' + config variables (thanks mailØmmjaeger*com) + * Rounded image corners now requires GD v2.0.1 and PHP + v4.3.2. Corners are transparent (for PNG output) and + antialiased. + * Rotate by arbitary angle ('ra') now has a transparent + background for PNG output + * Cached filenames now have an additional component for + applied filters + * Cached filenames now have an additional component for + HTTP referer, but only if the refering domain does not + match the domain of the server (designed to prevent + imaged linked from offsite with error message being + cached the same as the local cached version) + * Added setSourceImageResource() to allow use of an + existing GD image resource for thumbnailing + (thanks danØgonmad*co*uk) + * Now including phpThumb.demo.demo1.php (main demo page) + and phpThumb.demo.demo2.php (configurable demo page) + in the phpThumb() distribution + (thanks mailØmmjaeger*com) + * Added many more debugging/tracing message points + * Added set_time_limit(30) to phpThumb.php + * Bugfix: ImageMagick not used if `which convert` points + to a link and not a file (thanks bkainersØgmail*com) + * Bugfix: 'bgt' parameter was sometimes misspelled 'bct' + * Bugfix: 'wmm' couldn't be set to zero + * Bugfix: 'wmm' parameter was only applied to top/left of + image + * Bugfix: auto-detection of document_root failed on + Windows (thanks xbartvØhotmail*com) + * Bugfix: phpThumbDebug could be bypassed if EXIF + thumbnail present (thanks olgradinØcheckfree*com) + * Bugfix: cache file wasn't being written if EXIF data + was used directly (thanks olgradinØcheckfree*com) + * Bugfix: phpThumb.demo.showpic.php was broken by popup + blockers for images larger than the screen. + (thanks mailØmmjaeger*com) + +v1.4.11 - October 11, 2004 + * Changed sx/sy/sw/sh parameters to allow decimal values + (>0 but <1) to represent percent of source image + (thanks mordorØdefault*co*yu) + * Added config_error_silent_die_on_error for no-output + die on fatal errors (thanks johannesØformformat*se) + * Added auto-detection of probable 'document_root' if + that key is not available in $_SERVER + * Bugfix: Check `which convert` failing with error + message (thanks chadØchadshome*com) + * Bugfix: Image cropping to invalid areas outside source + image caused text output (thanks mordorØdefault*co*yu) + +v1.4.10 - August 22, 2004 + * Bugfix: cached files not written in most cases + (thanks kizerØcourtkizer*com, snuffØinbox*ru) + * Bugfix: ApacheLookupURIarray() crashes in CGI mode + (thanks hanskrentelØyahoo*de) + * Bugfix: phpthumb_bmpfile2gd() was broken + (thanks iØmindlace*net) + +v1.4.9 - August 9, 2004 + * Bugfix: changed destination filename in RenderToFile() + (thanks alextkØwalla*com) + * Bugfix: problems with HTTP image source when called as + an object (thanks alextkØwalla*com) + +v1.4.8 - August 4, 2004 + * $this->error has changed to $this->errors and is now + an array of strings (instead of a single string) + * A lot more error conditions (invalid cache directory, + etc) are now reported in $this->errors + (thanks aidan*slingsbyØlineone*net) + * Removed all define(CONSTANT) in the phpThumb() + constructor - you can now access: + - PHPTHUMB_VERSION == $this->phpthumb_version; + - PHPTHUMB_OSSLASH == $this->osslash; + - PHPTHUMB_ISWINDOWS == $this->iswindows; + * Bugfix: Error message from apache_lookup_uri() failing + under Apache2 now reported cleanly + (thanks derbaffØyahoo*com) + * Bugfix: missing phpthumb_functions:: class name for + ImageTypeToMIMEtype() call in ExtractEXIFgetImageSize() + (thanks aidan*slingsbyØlineone*net) + * Bugfix: ImageTypeToMIMEtype() was broken for PHP older + than v4.3.0 (thanks georg*schreiberØbatch-pc*es) + * Bugfix: RenderToFile() now returns false if it fails + (thanks phpthumbØsendthemtomir*com) + * Bugfix: Corrupt JPEG/PNG/GIF files that failed + ImageCreateFrom*() were not being passed to ImageMagick + for fallback, nor passed through unmodified if IM was + unavailable or failed (thanks r*chongØmogenic*net) + * Bugfix: Improved backtick safe-mode limit detection + (thanks 1Øadamcarrington*com) + * Bugfix: EXIF thumbnails were being used as source when + they should not be (thanks aidan*slingsbyØlineone*net) + * Bugfix: Cached files were not being created or used + properly (thanks aidan*slingsbyØlineone*net) + * Bugfix: max_source_pixels not set correct on some PHP + versions (thanks derbaffØyahoo*com) + * Bugfix: 'down' parameter ignored for unprocessed and + cached files (thanks aidan*slingsbyØlineone*net) + +v1.4.7 - July 27, 2004 + * Included a modified version of "module.graphic.bmp.php" + from getID3() [http://getid3.sourceforge.net] as + "phpthumb.bmp.php" for BMP reading support without + ImageMagick. It works, but it's *very* slow, especially + for large images (as in 640x480 or larger). + * Added check to prevent error messages when shell_exec + is disabled (thanks webmasterØneester*com) + +v1.4.6 - July 22, 2004 + * Added new section to phpthumb.config.php where you can + easily specify defaults for any parameter you can set + in the URL. Normally URL parameters override these + default values, unless you set + $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE to false + * Renamed phpthumb.config.php to phpThumb.config.php + since it's part of phpThumb.php, not part of + phpthumb.class.php (change of case only, will not + affect Windows servers, but will affect *nix) + * Changed cached filename of rawImageData-source images + from urlencode('') to md5(rawImageData). This should + make caching thumbnails from non-file sources more + reliable. + * Added ImageMagick debugging information + * Removed unneccesary default values from cached + filenames. This may invalidate some previously cached + files. phpthumb.demo.cacheconvert.php has been updated + to handle v1.4.1-1.4.5 => v1.4.6+ cache filenames. + * Bugfix: Cached filename did not have file-modified + datestamp when used as implmented in phpThumb.php + * Bugfix: RenderToFile() now accepts relative filenames + (thanks aidan*slingsbyØlineone*net) + * Bugfix: AllowOutputEnlargment setting was ignored when + falling back to ImageMagick + * Bugfix: IgnoreAspectRatio setting was ignored when + falling back to ImageMagick + * Bugfix: config_temp_directory was ignored in gd_info() + in PHP < v4.3.0 when phpinfo() returns no GD + information (due to safe mode restrictions) + (thanks mimyrtekØmyrtek*com) + +v1.4.5 - June 28, 2004 + * Added new parameter 'down' where you can specify a + filename and OutputThumbnail() will cause the file + to be downloaded rather than displayed in the browser. + Demo images on silisoftware.com/scripts/phpThumb/demo/ + can all be downloaded to show off this feature. + (thanks stuartscrumpØyahoo*co*uk) + * Added ability to remove old files from cache directory + based on last-access time and/or number of cached files + and/or total size of cached files + (thanks jrmhaigØyahoo*co*uk) + * Added public CleanUpCacheDirectory() for cache cleaning + (see above) if you need to call it manually + * Included new file phpThumb.demo.cacheconvert.php to + convert old-style cache names to the current (and + hopefully last!) standard naming convention. + (thanks joshgØtwcny*rr*com) + * Added configuration value 'document_root' for rare case + when $_SERVER['DOCUMENT_ROOT'] return incorrect value + (thanks joshgØtwcny*rr*com) + * Now tries to create thumbnail with ImageMagick if + ImageCreateFromJPEG etc fails, before falling back to + outputting unmodified source data. + * Bugfix: HTTP image sources were broken + (thanks fritz*weisshartØt-online*de) + * Bugfix: ImageMagick callout wasn't being used if EXIF + thumbnail was available + (thanks joshgØtwcny*rr*com) + * Bugfix: HTTP src with space in filename was broken + (thanks drØrhodes360*com) + * Bugfix: version_compare_replacement() was broken for + PHP v4.1.0+ + +v1.4.4 - June 8, 2004 + * Bugfix: network-share (Windows) source filenames were + not possible. Now works, but you must use the network + name and not a mapped drive name, for example: + \\othercomputer\file.jpg - good + \\192.168.2.1\file.jpg - good + z:\file.jpg - won't work + This is a PHP limitation (see www.php.net/file-exists) + Note: you may want to use "/" slashes instead of "\" if + you have magic_quotes_gpc enabled to avoid stripslashes + problems. + (thanks drØrhodes360*com) + * Bugfix: missing "phpthumb_functions::" in + ImageCreateFromStringReplacement() + (thanks zapletalØsoftwaremedia*cz) + +v1.4.3 - May 25, 2004 + * Added new configuration variable 'config_temp_directory' + to allow you to specify a writable directory name for + temp files if you do not have access to the system temp + directory on your server (Safe Mode restrictions etc) + (thanks nickØregenmag*com) + * Added new configuration variable + 'config_error_die_on_error' which can be set to false if + you want to retrieve the error message without having it + dumped as an image - the error message is now available + in $phpThumb->error + * Images are passed through directly with no processing + and no caching if no parameters are passed to alter the + image (resize, crop, sharpening, etc) + (thanks nchmuraØusers*sourceforge*net) + * Added new configuration variable 'config_disable_debug' + which disabled phpThumbDebug from working if you have + security concerns about the displayed information + * Bugfix: Added detection at the top of phpThumb.php for + no-GD errors to avoid parse errors later in the code + (thanks nickØregenmag*com) + * Bugfix: RoundedImageCorners() had some off-by-1 errors + (thanks ola*thunbergØhome*se) + +v1.4.2 - May 10, 2004 + * Added IE-compatability mode for transparent corners + (set 'bct=256') + * Bugfix: version_compare_replacement() was broken in PHP + older than 4.1.0 + (thanks nickØregenmag*com) + +v1.4.1.1 - May 9, 2004 + * Bugfix: Removed ImageTrueColorToPalette hack. + See http://bugs.php.net/bug.php?id=28341 + * Bugfix: 'maxb' option for PNG/GIF output incorrect + bit depth under some circumstances + +v1.4.1 - May 9, 2004 + * Added 'maxb' (MAXimum Bytes) option to auto-set the + output image quality (JPEG) or bit depth (PNG/GIF) so + that the output thumbnail is less than 'maxb' bytes + (thanks e_belleØhotmail*com) + * Added 'bgt' parameter to make rounded corners from + 'brx'/'bry' option transparent when used with PNG + output. Note: PHP/GD appears buggy at this time, so this + option must force output to 256-color mode for this + to work. The feature will be updated when a non-broken + version of PHP/GD is released. + (thanks javierØircorion*net) + * Bugfix: Caching was broken + (thanks mikeØgdaymate*nl, jurewiczØgo3*pl) + +v1.4.0 - April 30, 2004 + * Rewritten as a PHP class. Split into several files: + - phpthumb.class.php = most processing code + - phpthumb.functions.php = support functions + - phpthumb.readme.txt = usage instructions + - phpthumb.changelog.txt = this file + - phpthumb.config.php = configuration file + - phpthumb.gif.php = Non-GD GIF reading support + - phpthumb.unsharp.php = Unsharp Masking support + - phpThumb.php = demo script that works + exactly as previous versions; this is a drop-in + replacement for existing phpThumb() installations + - phpThumb.demo.showpic.php = demo script that auto- + resizes a popup window to the size of the image + shown. Useful if you want popup images but do not + know the large image size beforehand + * Added optional call-out to ImageMagick (if avaible) if + source image is larger than PHP memory restrictions + allow. ImageMagick installation should be auto-detected + under *nix, but you should configure 'imagemagick_path' + for use under Windows. + * 'max_source_pixels' is now auto-calculated from PHP + configuration settings. Due to various server-level + restrictions that may override PHP settings this + calculated value may not always be correct, and you may + have to specify the value manually. + * Added rounded-corner border option. You must specify + both 'brx' (horizontal radius) and 'bry' (vertical + radius) as well as 'bw' (border width). If 'bw' is + greater than zero, the image will be shrunk to fit + inside the border with a margin of background color. + If 'bw' is zero, the corners of the image will be + cut off and filled with background color. + (thanks javierØircorion*net) + * Minor speed improvement for unsharp masking + +v1.3.7 - March 28, 2004 + * Bugfix: GD version detection was broken on PHP <4.3.0 + on servers where phpinfo() was disabled + (thanks javierØircorion*net) + * Bugfix: Non-GD GIF support was broken on restricted + PHP configurations + (thanks javierØircorion*net) + * Bugfix: phpThumb.gif.php output error messages if PHP + was running in Safe Mode + * Added 'iar' parameter (Ignore Aspect Ratio) to allow + non-proportional resizing (stretch image to fit). + You must specify 'h' and 'w' to use this option. + (thanks javierØircorion*net) + +v1.3.6 - March 14, 2004 + * Bugfix: was broken when register_globals turned on + (thanks joshgØtwcny*rr*com) + * Bugfix: Images with transparent backgrounds now have + the background color filled with the color specified + by the 'bg' parameter + * Bugfix: ImageCreateFromString() is broken in the + non-bundled GD. Added workaround, but please use + the bundled version of GD if possible + (thanks dnØxbe*ch) + * Bugfix: EXIF thumbnail caching was broken + * Bugfix: EXIF thumbnail handling was broken for PHP + v4.2.x + (thanks smithk1Øshaw*ca) + * Bugfix: Image borders with GD2 were misaligned + * Bugfix: virtual paths/filenames like /~user/foo.jpg + should now work properly, if PHP is installed as an + Apache module (see www.php.net/apache-lookup-uri) + * Bugfix: contents of any non-image file could be + displayed (including PHP & HTML files) + (thanks arsyanØarsyan*com) + * Added rotation parameters 'ra' and 'ar' + (thanks drØrhodes360*com) + * Added $CONFIG['output_allow_enlarging'], defaulted + to false, to prevent smaller-than-max-size images + from being enlarged beyond their original size. If + you want to be able to enlarge images, set this to + false. Can be overridden with the 'aoe' parameter + (thanks dnØxbe*ch) + * Changed all configuration variables to be under one + array named $CONFIG + * Moved color and font options for ErrorImage() to + $CONFIG variables + * Changed cached filename structure (again) to a more + flexible format that can handle future expansion + (old cached files are invalid and will be recreated) + * Added more debugging code to phpThumbDebug + +v1.3.5 - February 29, 2004 + * Added capability to use EXIF thumbnail that may be + embedded in source image (often is in digital camera + JPEGs) and source image dimensions are larger than + $config_max_source_pixels. This will overcome the + limitation where PHP runs out of memory processing + large images (usually >1600x1200). EXIF thumbnail + extraction requires PHP v4.2.0 or higher and EXIF + support compiled into PHP (or php_exif extension) + * Eliminated intermediate read-file-to-memory stage if + image is created from local file. Should allow + larger images to be processed without running out of + memory. + * Added optional 'goto' parameter to be used with the + 'file' parameter, where 'goto' is a URL that is + redirected to after image is rendered to file + (thanks wimbleØwebdonors*com) + * Added optional 'xto' parameter that will bypass all + processing and just return the embedded EXIF + thumbnail, if available. + * Added error-handling if ImageTypes() is unavailable + +v1.3.4 - February 15, 2004 + * Custom error image option (&err=img.jpg) which can + also be set as $config_error_message_image_default + (thanks carlØ4thstar*net) + * &f=text will now output plain-text error messages + * ErrorImage() now used for anti-hotlink messages (if + $config_nohotlink_erase_image is true) + +v1.3.3 - February 5, 2004 + * Bugfix: Added stripslashes() to filenames if + magic_quotes_gpc is enabled + (thanks arsyanØarsyan*com) + * Output can now be rendered to a file only (not to + browser) specified by the 'file' parameter + (thanks arsyanØarsyan*com) + * JPEG quality now has a maximum of 95%, as specified + in the GD documentation + +v1.3.2.1 - February 3, 2004 + * Bugfix: gd_version() was broken for GD v2.0+ + * Bugfix: removed debugging code + +v1.3.2 - February 3, 2004 + * Bugfix: when borders are enabled, portait images + with no width constraint, or landscape images with + no height constraint were smaller than neccesary by + double the border width + (thanks jjjØxs4all*nl) + * Added unsharp mask option thanks to Torstein Hønsi: + http://www.vikjavev.com/hovudsida/umtestside.php + Note: requires GD v2.x to function + (thanks jjjØxs4all*nl) + * Updated cache filenames to reflect new parameters, + this means old cached files will need to be deleted + (or not, they just will never get called again) and + new cached versions will be created. + * Added caching to gd_info() calls for minor speedup + +v1.3.1 - February 2, 2004 + * Added optional border (width and color configurable) + (thanks arsyanØarsyan*com) + * Added option to create fixed-dimension thumbnails + regardless of source aspect ration. Set the 'bw' + (BorderWidth) parameter (even to 0) and this will be + enabled. Outside the actual image will be filled + with 'bg' color (default FFFFFF) + (thanks arsyanØarsyan*com) + +v1.3.0 - January 27, 2004 + * Added watermarking option to overlay thumbnails with + a semi-transparent watermark image (copied from a + seperate source watermark image) + (thanks arsyanØarsyan*com) + * Added option for absolute filenames (on both Windows + and *nix) outside the DOCUMENT_ROOT directory + * Added debug output dump for diagnosing problems) + +v1.2.8 - January 19, 2004 + * added ability to specify relative pathnames as well + as absolute pathnames (pathname is relative to the + location of phpThumb.php if the passed source does + not begin with "/" + +v1.2.7 - January 7, 2004 + * Added patch to allow use of PHP older than 4.1.0 + (or GD without PNG support) for non-GD GIF support + (thanks hostwebserverØhotmail*com) + +v1.2.6 - January 4, 2004 + * Added patch to allow use of PHP older than 4.1.0 + (without the superglobals arrays) + +v1.2.5 - December 26, 2003 + * Added configuration options for default output image + format and max width/height + +v1.2.4 - December 20, 2003 + * Bugfix: temp directory for non-native GD support not + always returning valid directory + * Caching feature reintroduced (see configuration) + +v1.2.3 - December 19, 2003 + * Added anti-hotlink code so the thumbnail script on + one domain cannot be used by another domain. The + list of allowed domains defaults to the current + domain but is configurable below as + $config_nohotlink_valid_domains. The message, text + size, colors and whether to blank the image or not + are also configurable + * Bugfix: URL image sources were not able to use the + non-GD GIF-reading functions + +v1.2.2 - December 17, 2003 + * Added option to use http:// URL as image source + +v1.2.1 - December 11, 2003 + * Added option to get source data from a database + rather than a physical file + * Bugfix: resize not proportional when wide image + limited more by max height than max width + Thanks mathias_strasserØgmx*net + * Removed caching code + +v1.2.0 - December 10, 2003 + * Added GIF support for versions of GD that do not + have built-in GIF support (v1.6.x) via the "GIF + Util" class by Fabien Ezber (www.yamasoft.com) + GD's built-in GIF-reading functions are faster, and + are present in PHP v4.3.0 or newer, but all versions + of GD can display resized GIF thumbnails now. + +v1.1.2 - October 26, 2003 + * check for source image existance to prevent text + error messages + * if GD not available, a GIF saying "no GD" is shown + instead of showing the original image + * Cache feature introduced + +v1.1.1 - September 28, 2003 + * better resize code by sfisher10Øcox*net + +v1.1.0 - September 1, 2003 + * initial public release + * thumbnails can now be larger than source image + * graphical error messages + +v1.0.0 - January 7, 2002 + * initial private release diff --git a/site/runshops/phpthumb/docs/phpthumb.faq.txt b/site/runshops/phpthumb/docs/phpthumb.faq.txt new file mode 100644 index 0000000..070fb99 --- /dev/null +++ b/site/runshops/phpthumb/docs/phpthumb.faq.txt @@ -0,0 +1,203 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// Frequently Asked Questions (FAQ) about phpThumb() // +// /// +////////////////////////////////////////////////////////////// + + +Q: My question isn't answered here and I can't find any + forums, how do I get support? +A: Please email me directly at info@silisoftware.com with + any questions, suggestions, donations, etc. + + +Q: What is the GPL? Can I use this for commercial sites? +A: See the GPL FAQ: http://www.gnu.org/licenses/gpl-faq.html + In general, if you just want to call phpThumb.php in the + standard manner + then there is no problem, you're free to do this no matter + if you site is commercial or not, or what license your code + is released under. + If you're calling phpThumb() as an object then you will + probably run into license issues, so consult the above FAQ + and the GPL itself. + No matter if you use phpThumb() commercially or not, no + payment is required. However, donations are always welcome + and can be made at http://phpthumb.sourceforge.net + + +Q: Some images generate thumbnails, but some fail (the original + non-resized image is output instead). +A: Your PHP installation does not have a high enough memory_limit + and ImageMagick is not installed on the server. The PHP memory + required is 5 times the number of pixels in the image. + For example: + 640x480x5 = 1.5MB + 1600x1200x5 = 9.2MB + You can adjust the PHP memory limit in php.ini (if you have + permission on your server to do so), or (better yet) install + ImageMagick on the server and that will bypass the memory limit + issue. If you can't do either of the above, you can resize the + images manually (with your favourite image editor) to a size + that your memory_limit setting can handle, and/or you can + re-save the images with an image editor that can embed an EXIF + thumbnail (Photoshop for example) which phpThumb can use as an + image source (lower image quality, but perhaps better than + nothing). + + +Q: I'm getting is this error message: + Failed: RenderToFile() failed because + !is_resource($this->gdimg_output) +A: You missed the call to GenerateThumbnail() before + RenderToFile() or OutputThumbnail. + See /demo/phpThumb.demo.object.php for an example. + + +Q: I'm trying to save a phpThumb-generated image in Internet + Explorer and it saves in BMP format, why? +A: This is not phpThumb's fault, it is an IE issue: + http://support.microsoft.com/default.aspx?scid=kb;en-us;810978 + http://support.microsoft.com/default.aspx?scid=kb;en-us;260650 + + +Q: PNG images with transparent areas show up with gray background + in the areas that are supposed to be transparent. +A: Internet Explorer has had a broken PNG alpha-channel display + implementation for a decade, so it may never get fixed. Other + major browsers generally handle alpha-transparent PNGs fine. + See http://www.silisoftware.com/png_transparency/ + For an alpha-channel PNG display in IE hack, see this page: + http://www.koivi.com/ie-png-transparency/ + + +Q: I'm getting " does not exist" when I know the + file does exist +A: Check these two values are present and properly configured + in phpThumb.config.php (introduced in v1.6.0): + $PHPTHUMB_CONFIG['allow_src_above_docroot'] (default=false) + $PHPTHUMB_CONFIG['allow_src_above_phpthumb'] (default=true) + If your images are outside DOCUMENT_ROOT then you will have + to configure 'allow_src_above_docroot' to true. + + +Q: Should I use phpThumb.php, or use phpThumb() as an object? +A: phpThumb.php is easier to use (less coding) for basic uses. + phpThumb.php handles all caching; your own object will need + to have its own caching code. If you just want to display a + thumbnailed version of an existing image, use phpThumb.php + If you want to render one (or more) thumbnails to static + files (during upload, for example), that's an appropriate + use for the object mode. Also, phpThumb.config.php is only + used by phpThumb.php, so if you instantiate your own object + you need to manually set all configuration options because + phpThumb.config.php has NO effect. So, to repeat: + **always use phpThumb.php unless you NEED to have an object** + + +Q: Are there any front-end GUI interfaces to phpThumb()? +A: See /demo/readme.demo.txt + + +Q: Are there / have there been any security issues in phpThumb? +A: http://secunia.com/product/5199/ + + +Q: Why can't Flash work with images output from phpThumb()? +A: Flash doesn't like progressive JPEG. Set: + $PHPTHUMB_CONFIG['output_interlace'] = false; + + +Q: Image quality is not very good - why? +A: If you're using GD v1.x, no way around it. Upgrade to GD v2.x + + +Q: Image quality is very bad, very pixelated -- why? +A: You may be trying to resize images larger than the available + PHP memory, so phpThumb is simply extracting and using the + EXIF thumbnail as the image source, which is usually about + 160x120 (so if you resize it to 640x480 it will look very bad). + To calculate the required size for memory_limit in php.ini, + calculate the number of pixels in the image and multiply by 5: + For example, 1600x1200 = 1600 * 1200 * 5 = 9600000 = 10M + + +Q: Can I save the generated thumbnail to a file? +A: Yes, there are several ways to do so; the best way is to call + phpThumb as an object and call RenderToFile() to save the + thumbnail to whatever filename you want. + See /demo/phpThumb.demo.object.php for an example. + The other way is to use the 'file' parameter (see + /docs/phpthumb.readme.txt) but this parameter is deprecated + and may not exist in future versions of phpThumb(). + + +Q: "Off-server thumbnailing is not allowed" -- how do I enable it? +A: By default, phpThumb() only makes thumbnails for the same domain + that it is running on. To allow it to make thumbnails for a limited + number of other domains, add them (in phpThumb.config.php) like this: + $PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array( + @$_SERVER['HTTP_HOST'], 'example.com', 'www.example.com', + 'subdomain.example.net', 'example.org'); + To disable off-server thumbnail blocking, just set: + $PHPTHUMB_CONFIG['nohotlink_enabled'] = false; + + +Q: Is it possible to set the parameters (like w/h/fltr[]) in the config, + so that they can't be changed over the URL? +A: Take a look at $PHPTHUMB_DEFAULTS at the bottom of phpThumb.config.php + You'll want to set $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE=false, + possibly also $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS=true. + You may also want to investigate $PHPTHUMB_CONFIG['high_security_enabled'] + (see the example at the bottom of phpThumb.config.php for how to call + images in HighSecurity mode. + + +Q: Is there a way to use phpThumb() object to create thumbnails without the + parameters in the URL showing the location of the image etc? +A: There is a demo in /demo/phpThumb.demo.object.php. You could modify this + into your own file, but there still remains the problem of passing + parameters to the file, whether it's phpThumb.php or your own instantiation + of a phpThumb() object. I would suggest is putting as many of the common + parameters into phpThumb.config.php as possible under $PHPTHUMB_DEFAULTS, + so you then don't have to pass them for each image. If you don't want people + modifying the parameters, turn on $PHPTHUMB_CONFIG['high_security_enabled'] + and set a password (you'll need to generate the tags with phpThumbURL() + provided at the bottom of phpThumb.config.php). If you don't want people + accessing your source images at all, you can place them outside DOCUMENT_ROOT + on your server (as long as phpThumb/PHP has read access to the directory). + The other option is to put your source images in a MySQL database and set + $PHPTHUMB_CONFIG['mysql_query'] and related parameters in phpThumb.config.php + to pull your source images from the database. That way it's impossible to + retrieve the images except through phpThumb.php, and if high_security is enabled, + then nobody can modify the parameters to view anything except what you want to show. + So, yes, it's possible to use your own object, but it's probably better to use + phpThumb.php if possible -- one notable issue is that phpThumb.php handles all + the caching, so you're on your own to deal with that if you create your own object. + + +Q: phpThumb runs slowly, as if the images aren't cached, when I use HTTP source + images (not on my server). How can I make it go faster? +A: $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; + // if true, remote source images will not be checked for modification date and + // cached image will be used if available, even if source image is changed or removed + + +Q: What does the "cache_default_only_suffix" configuration option do? +A: Cache files are normally created with big ugly names like + "phpThumb_cache_www.example.com_src1a482c2c760463795ff18faf073b389f_par3e099041c2f4a73041a7f5d7e7fc481a_dat1119952152.jpeg" + but if cache_default_only_suffix is enabled, cache filenames are simplified to + "pic_thumb.jpg" (for example). The problem is that only one version of that + thumbnail is possible, and you can never call it again with a different size, + or different filters, etc. Generally you don't want that enabled, but it's + there because some people asked for it. + + +Q: Why is the visual size of rotated images smaller than the unrotated images? +A: phpThumb fits the rotated image into the 'w' and 'h' dimensions. + Try not specifying a 'w' parameter: phpThumb.php?src=file.png&ra=15 + That should leave the image the apparent same size as the unrotated image + (in actual fact the canvas size is enlarged to fit the rotated image in it). diff --git a/site/runshops/phpthumb/docs/phpthumb.license.txt b/site/runshops/phpthumb/docs/phpthumb.license.txt new file mode 100644 index 0000000..9fec808 --- /dev/null +++ b/site/runshops/phpthumb/docs/phpthumb.license.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/site/runshops/phpthumb/docs/phpthumb.readme.txt b/site/runshops/phpthumb/docs/phpthumb.readme.txt new file mode 100644 index 0000000..01e6839 --- /dev/null +++ b/site/runshops/phpthumb/docs/phpthumb.readme.txt @@ -0,0 +1,527 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// This code is released under the GNU GPL: // +// http://www.gnu.org/copyleft/gpl.html // +// // +// +-----------------------------------------------+ // +// | phpThumb() is free to use according to the | // +// | terms of the GPL. Donations also gratefully | // +// | GPL FAQ: http://gnu.org/licenses/gpl-faq.html | // +// | | // +// | Donations are gratefully accepted from happy | // +// | users :) See http://phpthumb.sourceforge.net | // +// | | // +// | If you like phpThumb(), please consider | // +// | writing a review at HotScripts.com: | // +// | http://www.hotscripts.com/Detailed/25654.html | // +// | | // +// | If you do use this code somewhere, send me | // +// | an email and tell me how/where you used it. | // +// +-----------------------------------------------+ // +// /// +////////////////////////////////////////////////////////////// + +============ +Description: +============ + +phpThumb() uses the GD library to create thumbnails from +images (GIF, PNG or JPEG) on the fly. The output size is +configurable (can be larger or smaller than the source), +and the source may be the entire image or only a portion +of the original image. True color and resampling is used +if GD v2.0+ is available, otherwise low-color and simple +resizing is used. Source image can be a physical file on +the server or can be retrieved from a database. GIFs are +supported on all versions of GD even if GD does not have +native GIF support thanks to the GIFutil class by Fabien +Ezber. AntiHotlinking feature prevents other people from +using your server to resize their thumbnails, or link to +your images from another server. The cache feature +reduces server load. + + +====== +Usage: +====== + +Call phpThumb() just like you would a normal image. +Examples: + + +See the "demo" link on http://phpthumb.sourceforge.net +for more usage examples). Parameters that can be passed +are listed below under "URL Parameters". + +NOTE: It's recommended you use the local image filename +wherever possible (rather than http://) because performance +is much better, less (or no) use of temp files, and the +last-modified check for cached files doesn't work for +remote files. + +To access files over a LAN with Windows share names you +must use the network name (or IP) and not a mapped drive +name, for example: + //othercomputer/file.jpg - good + //192.168.2.1/file.jpg - good + z:/file.jpg - won't work +This is a PHP limitation (see www.php.net/file-exists) +Note: you may want to use "/" slashes instead of "\" if +you have magic_quotes_gpc enabled to avoid stripslashes +problems, although either slash should work if +magic_quotes_gpc is disabled + + +================================ +Alternate PATH_INFO-style Usage: +================================ + +phpThumb.php can also be called by passing parameters not +after the usual "?" but like this: + phpThumb.php/=;x; +For example: + phpThumb.php/100;pic.jpg + phpThumb.php/100;images/pic.jpg + phpThumb.php/100;/images/pic.jpg + phpThumb.php/100x200;pic.jpg + phpThumb.php/x200;pic.jpg + phpThumb.php/f=jpeg;q=50;100x200;pic.jpg + phpThumb.php/fltr[]=usm;100;pic.jpg + + must be the last item. Dimensions must be the second- +last item. As many key/value pairs for parameters can be +passed before those last two items, with each pair joined by +equals ("=") and seperated by semicolon (";") + + +============== +Configuration: +============== + +There are some configuration options you may (but are +not required to) change. Most configuration options can +be set when you call phpThumb() - see list below), but +default configuration options (such as cache directory) +are in phpThumb.config.php - this is the only file you +should ever modify. + +The configuration file is distributed as +phpThumb.config.php.default to prevent accidental +overwriting of old configuration settings. Please +migrate your old settings to the new file (if upgrading), +or delete your old config and rename the default to +phpThumb.config.php + + +The amount of memory required for phpThumb depends on +several factors: the dimensions of the source image, +the dimensions of the output image, whether unsharp +masking is applied, whether watermarks are applied, etc. +The auto-detection of memory limits works as a general +"safe" value. You may be able to exceed the auto value +by a small or large amount, depending on whether you +apply watermarks and/or sharpening, and the output size +of your thumbnails. I do not currently have a reliable +formula for calculating such things, but I will attempt +to craft one for future versions of phpThumb(). Until +then, set "max_source_pixels" in phpThumb.config.php to a +value that works well for you (or leave it alone if the +defaults give you no problems). + +The configuration options you should maybe modify are: +* cache_directory - thumbnailing is slow and processor- + intensive. Enabling caching will dramatically speed + up future thumbnail serving +* max_source_pixels - This should be auto-detected, but + if auto-detection fails and you get an invalid image + from large source images, set this to about 20% of + your available PHP memory limit. +* imagemagick_path - If the source image is larger than + max_source_pixels allows, but ImageMagick is available + phpThumb() will use it to generate the thumbnail. + + +/////////////////////////////////////////////////////////// +Note: High-Security mode is recommended enabled if possible. + Set $PHPTHUMB_CONFIG['high_security_enabled'] in + phpThumb.config.php to enable it. Each call to phpThumb + needs to be made through the function supplied at the + bottom of phpThumb.config.php which create the hash: + require_once('phpThumb.config.php'); + echo ''; +/////////////////////////////////////////////////////////// + + +============================================== +Calling as an object (not using phpThumb.php): +============================================== + +NOTE: most people don't need to and should not do this. +If you just want to display resized images, please just +use phpThumb.php, not the object mode. To render output +to one (or more) files instead of the browser, you should +skip phpThumb.php and instantiate your own object. Please +take a look at /demo/phpThumb.demo.object.php for details. + +Note: phpThumb.php is where the caching code is located, if + you instantiate your own phpThumb() object that code is + bypassed and it's up to you to handle the reading and + writing of cached files. + + +=============== +URL Parameters: +=============== + + src = filename of source image + new = create new image, not thumbnail of existing image. + Requires "w" and "h" parameters set. + [ex: &new=FF0000|75] - red background, 75% opacity + Set to hex color string of background. Opacity is + optional (defaults to 100% opaque). + w = max width of output thumbnail in pixels + h = max height of output thumbnail in pixels + wp = max width for portrait images + hp = max height for portrait images + wl = max width for landscape images + hl = max height for landscape images + ws = max width for square images + hs = max height for square images + f = output image format ("jpeg", "png", or "gif") + q = JPEG compression (1=worst, 95=best, 75=default) + sx = left side of source rectangle (default = 0) + (values 0 < sx < 1 represent percentage) + sy = top side of source rectangle (default = 0) + (values 0 < sy < 1 represent percentage) + sw = width of source rectangle (default = fullwidth) + (values 0 < sw < 1 represent percentage) + sh = height of source rectangle (default = fullheight) + (values 0 < sh < 1 represent percentage) + zc = zoom-crop. Will auto-crop off the larger dimension + so that the image will fill the smaller dimension + (requires both "w" and "h"). Set "zc=1" to enable. + (overrides both "iar" and "far") + bg = background hex color (default = FFFFFF) + bc = border hex color (default = 000000) +fltr = filter system. Call as an array as follows: + - "brit" (Brightness) [ex: &fltr[]=brit|] + where is the amount +/- to adjust brightness + (range -255 to 255) + Availble in PHP5 with bundled GD only. + - "cont" (Constrast) [ex: &fltr[]=cont|] + where is the amount +/- to adjust contrast + (range -255 to 255) + Availble in PHP5 with bundled GD only. + - "gam" (Gamma Correction) [ex: &fltr[]=gam|] + where can be a number >0 to 10+ (default 1.0) + Must be >0 (zero gives no effect). There is no max, + although beyond 10 is pretty useless. Negative + numbers actually do something, maybe not quite the + desired effect, but interesting nonetheless. + - "sat" (SATuration) [ex: &fltr[]=sat|] + where is a number between zero (no change) + and -100 (complete desaturation = grayscale), or it + can be any positive number for increased saturation. + - "ds" (DeSaturate) [ex: &fltr[]=ds|] + is an alias for "sat" except values are inverted + (positive values remove color, negative values boost + saturation) + - "gray" (Grayscale) [ex: &fltr[]=gray] + remove all color from image, make it grayscale + - "th" (Threshold) [ex: &fltr[]=th|] + makes image greyscale, then sets all pixels brighter + than (range 0-255) to white, and all pixels + darker than to black + - "rcd" (Reduce Color Depth) [ex: &fltr[]=rcd||] + where is the number of colors (2-256) you want + in the output image, and is "1" for dithering + (deault) or "0" for no dithering + - "clr" (Colorize) [ex: &fltr[]=clr||] + where is a number between 0 and 100 for the + amount of colorization, and is the hex color + to colorize to. + - "sep" (Sepia) [ex: &fltr[]=sep||] + where is a number between 0 and 100 for the + amount of colorization (default=50), and is + the hex color to colorize to (default=A28065). + Note: this behaves differently when applied by + ImageMagick, in which case 80 is default, and lower + values give brighter/yellower images and higher + values give darker/bluer images + - "usm" (UnSharpMask) [ex: &fltr[]=usm|||] + where is the amount (default = 80), is the + radius (default = 0.5), is the threshold + (default = 3). + - "blur" (Blur) [ex: &fltr[]=blur|] + where (0 < < 25) (default = 1) + - "gblr" (Gaussian Blur) [ex: &fltr[]=gblr] + Availble in PHP5 with bundled GD only. + - "sblr" (Selective Blur) [ex: &fltr[]=gblr] + Availble in PHP5 with bundled GD only. + - "smth" (Smooth) [ex: &fltr[]=smth|] + where is the weighting value for the matrix + (range -10 to 10, default 6) + Availble in PHP5 with bundled GD only. + - "lvl" (Levels) [ex: &fltr[]=lvl||| + where can be one of 'r', 'g', 'b', 'a' (for + Red, Green, Blue, Alpha respectively), or '*' for all + channels based on average grayscale value (default). + and are the clip points for the levels + and are set to clip 0.1% of each end by default. + (range = 0-255) and are set to clip 0.1% of each end + by default. Use -1 for min and/or max to invoke auto- + detect mode. Using default parameters (&fltr[]=lvl) + is similar to Auto Contrast in Adobe Photoshop. + - "wb" (White Balance) [ex: &fltr[]=wb|] + where is the target hex color to white balance + on, this color is what "should be" white, or light + gray. The filter attempts to maintain brightness so + any gray color can theoretically be used. If is + omitted the filter guesses based on brightest pixels + in each of RGB + - "hist" (Histogram) + [ex: &fltr[]=hist|||||||] + Where is the color band(s) to display, from back + to front (one or more of "rgba*" for Red Green Blue + Alpha and Grayscale respectively); + is a semicolon-seperated list of hex colors to + use for each graph band (defaults to FF0000, 00FF00, + 0000FF, 999999, FFFFFF respectively); + and are the width and height of the overlaid + histogram in pixels, or if <= 1 then percentage of + source image width/height; + is the alignment (same as for "wmi" and "wmt"); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent + - "over" (OVERlay/underlay image) overlays an image on + the thumbnail, or overlays the thumbnail on another + image (to create a picture frame for example) + [ex: &fltr[]=over||||] + where is the image filename; is "0" (default) + for overlay the image on top of the thumbnail or "1" + for overlay the thumbnail on top of the image; is + the margin - can be absolute pixels, or if < 1 is a + percentage of the thumbnail size [must be < 0.5] + (default is 0 for overlay and 10% for underlay); + is opacity (0 = transparent, 100 = opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + (thanks raynerapeØgmail*com, shabazz3Ømsu*edu) + - "wmi" (WaterMarkImage) + [ex: &fltr[]=wmi||||] where + is the filename of the image to overlay; + is the alignment (one of BR, BL, TR, TL, C, + R, L, T, B, *) where B=bottom, T=top, L=left, + R=right, C=centre, *=tile); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent + - "wmt" (WaterMarkText) + [ex: &fltr[]=wmt|||||||||||] + where: + is the text to use as a watermark; + Any instance of metacharacters will be replaced + with their calculated value. Currently supported: + ^Fb = source image filesize in bytes + ^Fk = source image filesize in kilobytes + ^Fm = source image filesize in megabytes + ^X = source image width in pixels + ^Y = source image height in pixels + ^x = thumbnail width in pixels + ^y = thumbnail height in pixels + ^^ = the character ^ + is the font size (1-5 for built-in font, or point + size for TrueType fonts); + is the alignment (one of BR, BL, TR, TL, C, R, L, + T, B, * where B=bottom, T=top, L=left, R=right, + C=centre, *=tile); + is the hex color of the text; + is the filename of the TTF file (optional, if + omitted a built-in font will be used); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent; + is the angle + is the hex color of the background; + is background opacity from 0 (transparent) to + 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the direction(s) in which the background is + extended (either 'x' or 'y' (or both, but both + will obscure entire image)) + Note: works with TTF fonts only, not built-in + (thanks mailØmmjaeger*com, craigØpc-fanatics*com) + - "flip" [ex: &fltr[]=flip|x or &fltr[]=flip|y] + flip image on X or Y axis + - "ric" [ex: &fltr[]=ric||] + rounds off the corners of the image (to transparent + for PNG output), where is the horizontal radius + of the curve and is the vertical radius + - "elip" [ex: &fltr[]=elip] + similar to rounded corners but more extreme + - "mask" [ex: &fltr[]=mask|filename.png] + greyscale values of mask are applied as the alpha + channel to the main image. White is opaque, black + is transparent. + - "bvl" (BeVeL) [ex: &fltr[]=bvl|||] + where is the bevel width, is the hex color + for the top and left shading, is the hex color + for the bottom and right shading + - "bord" (BORDer) [ex: &fltr[]=bord|||| + where is the width in pixels, and are + horizontal and vertical radii for rounded corners, + and is the hex color of the border + - "fram" (FRAMe) draws a frame, similar to "bord" but + more configurable + [ex: &fltr[]=fram|||||] + where is the width of the main border, is + the width of each side of the bevel part, is the + hex color of the main border, is the highlight + bevel color, is the shadow bevel color + - "drop" (DROP shadow) + [ex: &fltr[]=drop||||] + where is distance from image to shadow, is + width of shadow fade (not yet implemented), is + the hex color of the shadow, and is the angle of + the shadow (default=225) +file = if set then thumbnail will be rendered to this + filename, not output and not cached. + (Deprecated. Disabled by default since v1.6.0. + You should instantiate your own object instead) +goto = URL to redirect to after rendering image to file + * Must begin with "http://" + * Requires file parameter set + (Deprecated. Disabled by default since v1.6.0. + You should instantiate your own object instead) + err = custom error image filename instead of showing + error messages (for use on production sites) +md5s = MD5 hash of the source image -- if this parameter is + passed with the hash of the source image then the + source image is not checked for existance or + modification and the cached file is used (if + available). If 'md5s' is passed an empty string then + phpThumb.php dies and outputs the correct MD5 hash + value. This parameter is the single-file equivalent + of 'cache_source_filemtime_ignore_*' configuration + paramters + xto = EXIF Thumbnail Only - set to only extract EXIF + thumbnail and not do any additional processing + ra = Rotate by Angle: angle of rotation in degrees + positive = counterclockwise, negative = clockwise + ar = Auto Rotate: set to "x" to use EXIF orientation + stored by camera. Can also be set to "l" or "L" + for landscape, or "p" or "P" for portrait. "l" + and "P" rotate the image clockwise, "L" and "p" + rotate the image counter-clockwise. + aoe = Output Allow Enlarging - override the setting for + $CONFIG['output_allow_enlarging'] (1=on, 0=off) + ("far" and "iar" both override this and allow output + larger than input) + iar = Ignore Aspect Ratio - disable proportional resizing + and stretch image to fit "h" & "w" (which must both + be set). (1=on, 0=off) (overrides "far") + far = Force Aspect Ratio - image will be created at size + specified by "w" and "h" (which must both be set). + Alignment: L=left,R=right,T=top,B=bottom,C=center + BL,BR,TL,TR use the appropriate direction if the + image is landscape or portrait. +maxb = MAXimum Byte size - output quality is auto-set to + fit thumbnail into "maxb" bytes (compression + quality is adjusted for JPEG, bit depth is adjusted + for PNG and GIF) +down = filename to save image to. If this is set the + browser will prompt to save to this filename rather + than display the image + + + +============== +General Notes: +============== + +* Always use the local image filename wherever possible + rather than a full http:// URL because performance is + much better, less (or no) use of temp files, and the + last-modified check for cached files doesn't work for + remote files. For example: + good: phpThumb.php?src=/images/nicepic.jpg + bad: phpThumb.php?src=/home/httpd/example/images/nicepic.jpg + worse: phpThumb.php?src=http://example.com/images/nicepic.jpg + +* Thumbnails will be scaled proportionately to fit in a + box of at most (width * height) pixels + (unless "iar" is set) + +* Thumbnail caching for URL or database sources requires + an absolute directory name for $config_cache_directory + Physical file cached thumbnails will be recreated if + the source file changes, but remote/database files + cannot (modification time isn't readily available) + +* If you need a GUI interface to phpThumb(), or for a user + to specify crop settings, or something like that please + see the list of known programs in /demo/readme.demos.txt + +* Cropping images can be specified with either exact pixel + values for sx/sy/sw/sh parameters, or if those are set + to a value >0 and <1 then these are interpreted as a + percentage of the source image width/height. For example, + to crop 25% off all sides, you would specify parameters: + phpThumb.php?src=pic.jpg&sx=.25&sy=.25&sw=.5&sh=.5 + +* phpThumb() may have tempfile access issues on servers + where Safe Mode is enabled, specificly when accessing + a file over HTTP, or when a non-bundled version of GD + is in use. Specifying "config_temp_directory" may help + +* Properly resolving /~user/ style filenames requires + apache_lookup_uri(), which is missing or broken in + Apache2, or if PHP is not installed as an Apache module. + phpThumb() does try and work around this if it is + unavailble, but you may have to specify a full filename + for "src" if you encounter problems. + +* phpThumb() should work with PHP v4.0.6+, but seems to + have a few quirks before v4.1.0 + EXIF thumbnail extraction requires PHP v4.2.0+ + Image rotation requires PHP v4.3.0+. There have been + reports of problems with PHP older than v4.3.3 + Some image filters require PHP v5.0.0+ + Run /demo/phpThumb.demo.check.php to examine your server + +* phpThumb() works better and faster when ImageMagick is + available. Most functions will work with only GD2, but + speed is much faster with ImageMagick, and much larger + images can be processed with ImageMagick than GD. + +* phpThumb() works with GD v1.x, but works better with + GD v2.0+ because of the true-color image support + and ImageCopyResampled(). Also, there appears to be a + bug in ImageCopyResized() which is used with GD v1.x + where the bottom and/or right line of pixels is set + to the background color (due to a rounding error?) + NOTE: Please use the bundled version of GD if at all + possible (with PHP v4.3.0+) because the non-bundled + version has bugs which may cause PHP to crash: + * http://bugs.php.net/bug.php?id=21518 + * http://bugs.php.net/bug.php?id=24174 + phpThumb() has a workaround for the above bug but + there may be other bugs, and the workaround is slow. + Alpha transparent output requires GD >= 2.0.1 and + PHP >= 4.3.2 + Most (if not all) filters require GD v2.x to function + at all. But many filters can be handled by ImageMagick + instead of GD. + +* Filters handled by ImageMagick or GD: + - brit;cont;ds;sat;gray;clr;sep;gam;neg;th;rcd;flip;edge; + emb;lvl;blur;gblr;usm; +* Filters handled only by ImageMagick: + - none yet +* Filters handled only by GD + PHP5: + - sblr;mean;smth; +* Filters handled only by GD2: + - bvl;wmi;wmt;over;wb;hist;fram;drop;mask;elip;ric;bord; diff --git a/site/runshops/phpthumb/fonts/readme.txt b/site/runshops/phpthumb/fonts/readme.txt new file mode 100644 index 0000000..2e5ef72 --- /dev/null +++ b/site/runshops/phpthumb/fonts/readme.txt @@ -0,0 +1,5 @@ +This is the default location for TTF fonts. + +You can safely delete or ignore this directory if you're not using +TTF fonts for text watermarks. You can also specify an alternate +directory in phpThumb.config.php \ No newline at end of file diff --git a/site/runshops/phpthumb/index.php b/site/runshops/phpthumb/index.php new file mode 100644 index 0000000..a722861 --- /dev/null +++ b/site/runshops/phpthumb/index.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/site/runshops/phpthumb/lee.jpg b/site/runshops/phpthumb/lee.jpg new file mode 100644 index 0000000..dcc65fb Binary files /dev/null and b/site/runshops/phpthumb/lee.jpg differ diff --git a/site/runshops/phpthumb/phpThumb.config.php b/site/runshops/phpthumb/phpThumb.config.php new file mode 100644 index 0000000..2a0a8ce --- /dev/null +++ b/site/runshops/phpthumb/phpThumb.config.php @@ -0,0 +1,241 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!file_exists(dirname(__FILE__).'/phpthumb.functions.php') || !include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once(phpthumb.functions.php) - realpath="'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'"'); +} +ob_end_clean(); + +// START USER CONFIGURATION SECTION: + +// * DocumentRoot configuration +// phpThumb() depends on $_SERVER['DOCUMENT_ROOT'] to resolve path/filenames. This value is usually correct, +// but has been known to be broken on some servers. This value allows you to override the default value. +// Do not modify from the auto-detect default value unless you are having problems. +//$PHPTHUMB_CONFIG['document_root'] = '/home/httpd/httpdocs'; +//$PHPTHUMB_CONFIG['document_root'] = 'c:\\webroot\\example.com\\www'; +//$PHPTHUMB_CONFIG['document_root'] = $_SERVER['DOCUMENT_ROOT']; +//$PHPTHUMB_CONFIG['document_root'] = realpath((@$_SERVER['DOCUMENT_ROOT'] && file_exists(@$_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'])) ? $_SERVER['DOCUMENT_ROOT'] : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', realpath('.')))); +$PHPTHUMB_CONFIG['document_root'] = realpath((getenv('DOCUMENT_ROOT') && ereg('^'.preg_quote(realpath(getenv('DOCUMENT_ROOT'))), realpath(__FILE__))) ? getenv('DOCUMENT_ROOT') : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__)))); + +// * Cache directory configuration (choose only one of these - leave the other lines commented-out): +// Note: this directory must be writable (usually chmod 777 is neccesary) for caching to work. +// If the directory is not writable no error will be generated but caching will be disabled. +$PHPTHUMB_CONFIG['cache_directory'] = dirname(__FILE__).'/cache/'; // set the cache directory relative to the phpThumb() installation +//$PHPTHUMB_CONFIG['cache_directory'] = $PHPTHUMB_CONFIG['document_root'].'/phpthumb/cache/'; // set the cache directory to an absolute directory for all source images +//$PHPTHUMB_CONFIG['cache_directory'] = './cache/'; // set the cache directory relative to the source image - must start with '.' (will not work to cache URL- or database-sourced images, please use an absolute directory name) +//$PHPTHUMB_CONFIG['cache_directory'] = null; // disable thumbnail caching (not recommended) + +$PHPTHUMB_CONFIG['cache_disable_warning'] = false; // If [cache_directory] is non-existant or not writable, and [cache_disable_warning] is false, an error image will be generated warning to either set the cache directory or disable the warning (to avoid people not knowing about the cache) + + +// * Cache culling: phpThumb can automatically limit the contents of the cache directory +// based on last-access date and/or number of files and/or total filesize. + +//$PHPTHUMB_CONFIG['cache_maxage'] = null; // never delete cached thumbnails based on last-access time +$PHPTHUMB_CONFIG['cache_maxage'] = 86400 * 30; // delete cached thumbnails that haven't been accessed in more than [30 days] (value is maximum time since last access in seconds to avoid deletion) + +//$PHPTHUMB_CONFIG['cache_maxsize'] = null; // never delete cached thumbnails based on byte size of cache directory +$PHPTHUMB_CONFIG['cache_maxsize'] = 10 * 1024 * 1024; // delete least-recently-accessed cached thumbnails when more than [10MB] of cached files are present (value is maximum bytesize of all cached files) + +//$PHPTHUMB_CONFIG['cache_maxfiles'] = null; // never delete cached thumbnails based on number of cached files +$PHPTHUMB_CONFIG['cache_maxfiles'] = 200; // delete least-recently-accessed cached thumbnails when more than [500] cached files are present (value is maximum number of cached files to keep) + + +// * Source image cache configuration +$PHPTHUMB_CONFIG['cache_source_enabled'] = false; // if true, source images obtained via HTTP are cached to $PHPTHUMB_CONFIG['cache_source_directory'] +$PHPTHUMB_CONFIG['cache_source_directory'] = dirname(__FILE__).'/cache/source/'; // set the cache directory for unprocessed source images + +// * cache source modification date configuration +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_local'] = false; // if true, local source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; // if true, remote source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed. WARNING: cached performance MUCH slower if this is set to false. + + +// * Simplified cache filename configuration +// Instead of creating unique cache filenames for all parameter combinations, create "simple" cache files (eg: "pic_thumb.jpg") +// If cache_default_only_suffix is non-empty, GETstring parameters (except 'src') are ignored and only $PHPTHUMB_DEFAULTS +// parameters (set at the bottom of phpThumb.config.php) are used for processing. +// The '*' character MUST be used to represent the source image name +$PHPTHUMB_CONFIG['cache_default_only_suffix'] = ''; // cached in normal phpThumb manner +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = '*_thumb'; // cache 'pic.jpg' becomes 'pic_thumb.jpg' (or 'pic_thumb.png' if PNG output is selected, etc) +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = 'small-*'; // cache 'pic.jpg' becomes 'small-pic.jpg' (or 'small-pic.png' if PNG output is selected, etc) + +$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache_'.str_replace('www.', '', @$_SERVER['SERVER_NAME']); +//$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache'; // allow phpThumb to share 1 set of cached files even if accessed under different servername/domains on same server + +$PHPTHUMB_CONFIG['cache_force_passthru'] = true; // if true, cached image data will always be passed to browser; if false, HTTP redirect will be used instead + + + +// * Temp directory configuration +// phpThumb() may need to create temp files. Usually the system temp dir is writable and can be used. +// Leave this value as NULL in most cases. If you get errors about "failed to open for writing" +// you should change this to a full pathname to a directory you do have write access to. +//$PHPTHUMB_CONFIG['temp_directory'] = '/tmp/'; +$PHPTHUMB_CONFIG['temp_directory'] = null; + + +// maximum number of pixels in source image to attempt to process entire image. +// If this is zero then no limit on source image dimensions. +// If this is nonzero then this is the maximum number of pixels the source image +// can have to be processed normally, otherwise the embedded EXIF thumbnail will +// be used (if available) or an "image too large" notice will be displayed. +// This is to be used for large source images (> 1600x1200) and low PHP memory +// limits. If PHP runs out of memory the script will usually just die with no output. +// To calculate this number, multiply the dimensions of the largest image +// you can process with your memory limitation (e.g. 1600 * 1200 = 1920000) +// As a general guideline, this number will be about 20% of your PHP memory +// configuration, so 8M = 1,677,722; 16M = 3,355,443; 32M = 6,710,886; etc. +if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && !defined('memory_get_usage') && !@ini_get('memory_limit')) { + // memory_get_usage() will only be defined if your PHP is compiled with the --enable-memory-limit configuration option. + $PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit +} else { + // calculate default max_source_pixels as 20% of memory limit configuration + $PHPTHUMB_CONFIG['max_source_pixels'] = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); + //$PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 1920000; // allow 1600x1200 images (2Mpx), no larger (about 10MB memory required) + //$PHPTHUMB_CONFIG['max_source_pixels'] = 3355443; // 16MB memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 3871488; // allow 2272x1704 images (4Mpx), no larger (about 16MB memory required) +} + + +// ImageMagick configuration +// If source image is larger than available memory limits as defined above in +// 'max_source_pixels' AND ImageMagick's "convert" program is available, phpThumb() +// will call ImageMagick to perform the thumbnailing of the source image to bypass +// the memory limitation. Leaving the value as NULL will cause phpThumb() to +// attempt to detect ImageMagick's presence with `which` +if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + // Windows: set absolute pathname + $PHPTHUMB_CONFIG['imagemagick_path'] = 'C:/Program Files/ImageMagick-6.2.5-Q16/convert.exe'; +} else { + // *nix: set absolute pathname to "convert", or leave as null if "convert" is in the path + //$PHPTHUMB_CONFIG['imagemagick_path'] = '/usr/local/bin/convert'; + $PHPTHUMB_CONFIG['imagemagick_path'] = null; +} + + +// * Default output configuration: +$PHPTHUMB_CONFIG['output_format'] = 'jpeg'; // default output format ('jpeg', 'png' or 'gif') - thumbnail will be output in this format (if available in your version of GD). This is always overridden by ?f=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxwidth'] = 0; // default maximum thumbnail width. If this is zero then default width is the width of the source image. This is always overridden by ?w=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxheight'] = 0; // default maximum thumbnail height. If this is zero then default height is the height of the source image. This is always overridden by ?h=___ GETstring parameter +$PHPTHUMB_CONFIG['output_interlace'] = true; // if true: interlaced output for GIF/PNG, progressive output for JPEG; if false: non-interlaced for GIF/PNG, baseline for JPEG. + +// * Error message configuration +$PHPTHUMB_CONFIG['error_image_width'] = 400; // default width for error images +$PHPTHUMB_CONFIG['error_image_height'] = 100; // default height for error images +$PHPTHUMB_CONFIG['error_message_image_default'] = ''; // Set this to the name of a generic error image (e.g. '/images/error.png') that you want displayed in place of any error message that may occur. This setting is overridden by the 'err' parameter, which does the same thing. +$PHPTHUMB_CONFIG['error_bgcolor'] = 'CCCCFF'; // background color of error message images +$PHPTHUMB_CONFIG['error_textcolor'] = 'FF0000'; // color of text in error messages +$PHPTHUMB_CONFIG['error_fontsize'] = 1; // size of text in error messages, from 1 (smallest) to 5 (largest) +$PHPTHUMB_CONFIG['error_die_on_error'] = true; // die with error message on any fatal error (recommended with standalone phpThumb.php) +$PHPTHUMB_CONFIG['error_silent_die_on_error'] = false; // simply die with no output of any kind on fatal errors (not recommended) +$PHPTHUMB_CONFIG['error_die_on_source_failure'] = true; // die with error message if source image cannot be processed by phpThumb() (usually because source image is corrupt in some way). If false the source image will be passed through unprocessed, if true (default) an error message will be displayed. + +// * Off-server Thumbnailing Configuration: +$PHPTHUMB_CONFIG['nohotlink_enabled'] = true; // If false will allow thumbnailing from any source domain +$PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' +$PHPTHUMB_CONFIG['nohotlink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nohotlink_text_message'] = 'Off-server thumbnailing is not allowed'; // text of error message + +// * Off-server Linking Configuration: +$PHPTHUMB_CONFIG['nooffsitelink_enabled'] = true; // If false will allow thumbnails to be linked to from any domain, if true only domains listed below in 'nooffsitelink_valid_domains' will be allowed. +$PHPTHUMB_CONFIG['nooffsitelink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' +$PHPTHUMB_CONFIG['nooffsitelink_require_refer'] = false; // If false will allow standalone calls to phpThumb(). If true then only requests with a $_SERVER['HTTP_REFERER'] value in 'nooffsitelink_valid_domains' are allowed. +$PHPTHUMB_CONFIG['nooffsitelink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nooffsitelink_text_message'] = 'Image taken from '.@$_SERVER['HTTP_HOST']; // text of error message + + +// * Border & Background default colors +$PHPTHUMB_CONFIG['border_hexcolor'] = '000000'; // Default border color - usual HTML-style hex color notation (overidden with 'bc' parameter) +$PHPTHUMB_CONFIG['background_hexcolor'] = 'FFFFFF'; // Default background color when thumbnail aspect ratio does not match fixed-dimension box - usual HTML-style hex color notation (overridden with 'bg' parameter) + +// * Watermark configuration +$PHPTHUMB_CONFIG['ttf_directory'] = dirname(__FILE__).'/fonts'; // Base directory for TTF font files +//$PHPTHUMB_CONFIG['ttf_directory'] = 'c:/windows/fonts'; + + +// * MySQL configuration +// You may want to pull data from a database rather than a physical file +// If so, modify the $PHPTHUMB_CONFIG['mysql_query'] line to suit your database structure +// Note: the data retrieved must be the actual binary data of the image, not a URL or filename +// see http://www.billy-corgan.com/blog/archive/000143.php for a brief tutorial on this section + +$PHPTHUMB_CONFIG['mysql_query'] = ''; +//$PHPTHUMB_CONFIG['mysql_query'] = 'SELECT `picture` FROM `products` WHERE (`id` = \''.mysql_escape_string(@$_GET['id']).'\')'; + +// These 4 values must be modified if $PHPTHUMB_CONFIG['mysql_query'] is not empty, but may be ignored if $PHPTHUMB_CONFIG['mysql_query'] is blank. +$PHPTHUMB_CONFIG['mysql_hostname'] = 'localhost'; +$PHPTHUMB_CONFIG['mysql_username'] = ''; +$PHPTHUMB_CONFIG['mysql_password'] = ''; +$PHPTHUMB_CONFIG['mysql_database'] = ''; + + +// * Security configuration +$PHPTHUMB_CONFIG['high_security_enabled'] = false; // if enabled, requires 'high_security_password' set to at least 5 characters, and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs +$PHPTHUMB_CONFIG['high_security_password'] = ''; // required if 'high_security_enabled' is true, must be at least 5 characters long +$PHPTHUMB_CONFIG['disable_debug'] = false; // prevent phpThumb from displaying any information about your system. If true, phpThumbDebug and error messages will be disabled +$PHPTHUMB_CONFIG['allow_src_above_docroot'] = false; // if true, allow src to be anywhere in filesystem; if false (default) only allow src within document_root +$PHPTHUMB_CONFIG['allow_src_above_phpthumb'] = true; // if true (default), allow src to be anywhere in filesystem; if false only allow src within sub-directory of phpThumb installation +$PHPTHUMB_CONFIG['allow_parameter_file'] = false; // if true, allow use of 'file' parameter; if false (default) the 'file' parameter is disabled/ignored +$PHPTHUMB_CONFIG['allow_parameter_goto'] = false; // if true, allow use of 'goto' parameter; if false (default) the 'goto' parameter is disabled/ignored + + +// * HTTP UserAgent configuration +//$PHPTHUMB_CONFIG['http_user_agent'] = ''; // PHP default: none +//$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; // Windows XP, Internet Explorer +$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; // Windows XP, Firefox + + +// * Compatability settings +$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] = false; // if true, $_SERVER[PATH_INFO] is not parsed. May be needed on some server configurations to allow normal behavior. +$PHPTHUMB_CONFIG['disable_imagecopyresampled'] = false; // if true, ImageCopyResampled is replaced with ImageCopyResampleBicubic. May be needed for buggy versions of PHP-GD. +$PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] = true; // if true, any image that can be parsed by GetImageSize() can be passed through; if false, only images that can be converted to GD by ImageCreateFrom(JPEG|GIF|PNG) functions are allowed + + +// * Speed optimizations configuration +$PHPTHUMB_CONFIG['prefer_imagemagick'] = true; // If true, use ImageMagick to resize thumbnails if possible, since it is usually faster than GD functions; if false only use ImageMagick if PHP memory limit is too low. +$PHPTHUMB_CONFIG['use_exif_thumbnail_for_speed'] = false; // If true, and EXIF thumbnail is available, and is larger or equal to output image dimensions, use EXIF thumbnail rather than actual source image for generating thumbnail. Benefit is only speed, avoiding resizing large image. + +// END USER CONFIGURATION SECTION + +/////////////////////////////////////////////////////////////////////////////// + +// START DEFAULT PARAMETERS SECTION +// If any parameters are constant across ALL images, you can set them here + +$PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE = true; // if true, any parameters in the URL will override the defaults set here; if false, any parameters set here cannot be overridden in the URL +$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = false; // if true, GETstring parameters will be ignored (except for 'src') and only below default parameters will be used; if false, both default and GETstring parameters will be used (depending on $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE). Will be auto-set true if !empty($PHPTHUMB_CONFIG['cache_default_only_suffix']) + +//$PHPTHUMB_DEFAULTS['w'] = 100; +//$PHPTHUMB_DEFAULTS['fltr'] = array('blur|10'); +//$PHPTHUMB_DEFAULTS['q'] = 90; + + +// END DEFAULT PARAMETERS SECTION + + + +/////////////////////////////////////////////////////////////////////////////// +// Function for generating hashed calls to phpThumb if 'high_security_enabled' +// example: +// require_once('phpThumb.config.php'); +// echo ''; + +function phpThumbURL($ParameterString) { + global $PHPTHUMB_CONFIG; + return 'phpThumb.php?'.$ParameterString.'&hash='.md5($ParameterString.@$PHPTHUMB_CONFIG['high_security_password']); +} + +/////////////////////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/phpThumb.php b/site/runshops/phpthumb/phpThumb.php new file mode 100644 index 0000000..e09a660 --- /dev/null +++ b/site/runshops/phpthumb/phpThumb.php @@ -0,0 +1,585 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.changelog.txt for recent changes // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +error_reporting(E_ALL); +ini_set('display_errors', '1'); +if (!@ini_get('safe_mode')) { + set_time_limit(60); // shouldn't take nearly this long in most cases, but with many filter and/or a slow server... +} +ini_set('magic_quotes_runtime', '0'); +if (@ini_get('magic_quotes_runtime')) { + die('"magic_quotes_runtime" is set in php.ini, cannot run phpThumb with this enabled'); +} +$starttime = array_sum(explode(' ', microtime())); + +// this script relies on the superglobal arrays, fake it here for old PHP versions +if (phpversion() < '4.1.0') { + $_SERVER = $HTTP_SERVER_VARS; + $_GET = $HTTP_GET_VARS; +} + +// instantiate a new phpThumb() object +ob_start(); +if (!include_once(dirname(__FILE__).'/phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.class.php').'")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +$phpThumb->DebugTimingMessage('phpThumb.php start', __FILE__, __LINE__, $starttime); + +// phpThumbDebug[0] used to be here, but may reveal too much +// info when high_security_mode should be enabled (not set yet) + +if (file_exists(dirname(__FILE__).'/phpThumb.config.php')) { + ob_start(); + if (include_once(dirname(__FILE__).'/phpThumb.config.php')) { + // great + } else { + ob_end_flush(); + $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); + } + ob_end_clean(); +} elseif (file_exists(dirname(__FILE__).'/phpThumb.config.php.default')) { + $phpThumb->ErrorImage('Please rename "phpThumb.config.php.default" to "phpThumb.config.php"'); +} else { + $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); +} + +if (!@$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] && empty($_GET) && !empty($_SERVER['PATH_INFO'])) { + $_SERVER['PHP_SELF'] = str_replace($_SERVER['PATH_INFO'], '', @$_SERVER['PHP_SELF']); + + $args = explode(';', substr($_SERVER['PATH_INFO'], 1)); + if (!empty($args)) { + $_GET['src'] = @$args[count($args) - 1]; + } + if (eregi('^([0-9]*)x?([0-9]*)$', @$args[count($args) - 2], $matches)) { + $_GET['w'] = $matches[1]; + $_GET['h'] = $matches[2]; + } + for ($i = 0; $i < count($args) - 2; $i++) { + @list($key, $value) = explode('=', @$args[$i]); + if (substr($key, -2) == '[]') { + $_GET[substr($key, 0, -2)][] = $value; + } else { + $_GET[$key] = $value; + } + } +} + +if (@$PHPTHUMB_CONFIG['high_security_enabled']) { + if (!@$_GET['hash']) { + $phpThumb->ErrorImage('ERROR: missing hash'); + } elseif (strlen($PHPTHUMB_CONFIG['high_security_password']) < 5) { + $phpThumb->ErrorImage('ERROR: strlen($PHPTHUMB_CONFIG[high_security_password]) < 5'); + } elseif ($_GET['hash'] != md5(str_replace('&hash='.$_GET['hash'], '', $_SERVER['QUERY_STRING']).$PHPTHUMB_CONFIG['high_security_password'])) { + $phpThumb->ErrorImage('ERROR: invalid hash'); + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[0]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '0') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +// returned the fixed string if the evil "magic_quotes_gpc" setting is on +if (get_magic_quotes_gpc()) { + $RequestVarsToStripSlashes = array('src', 'wmf', 'file', 'err', 'goto', 'down'); + foreach ($RequestVarsToStripSlashes as $dummy => $key) { + if (isset($_GET[$key])) { + $_GET[$key] = stripslashes($_GET[$key]); + } + } +} + +if (!@$_SERVER['PATH_INFO'] && !@$_SERVER['QUERY_STRING']) { + + echo 'phpThumb() v'.$phpThumb->phpthumb_version.'
    http://phpthumb.sourceforge.net

    ERROR: no parameters specified'; + unset($phpThumb); + exit; + +} + +if (@$_GET['src'] && isset($_GET['md5s']) && empty($_GET['md5s'])) { + if (eregi('^(f|ht)tps?://', $_GET['src'])) { + if ($rawImageData = phpthumb_functions::SafeURLread($_GET['src'], $error)) { + $md5s = md5($rawImageData); + } + } else { + $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($_GET['src']); + if (is_readable($SourceFilename)) { + $md5s = phpthumb_functions::md5_file_safe($SourceFilename); + } else { + $phpThumb->ErrorImage('ERROR: "'.$SourceFilename.'" cannot be read'); + } + } + if (@$_SERVER['HTTP_REFERER']) { + $phpThumb->ErrorImage('&md5s='.$md5s); + } else { + die('&md5s='.$md5s); + } +} + +if (!empty($PHPTHUMB_CONFIG)) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + if (!eregi('password', $key)) { + $phpThumb->DebugMessage('setParameter('.$keyname.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + } + } +} else { + $phpThumb->DebugMessage('$PHPTHUMB_CONFIG is empty', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[1]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '1') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +$parsed_url_referer = parse_url(@$_SERVER['HTTP_REFERER']); +if ($phpThumb->config_nooffsitelink_require_refer && !in_array(@$parsed_url_referer['host'], $phpThumb->config_nohotlink_valid_domains)) { + $phpThumb->ErrorImage('config_nooffsitelink_require_refer enabled and '.(@$parsed_url_referer['host'] ? '"'.$parsed_url_referer['host'].'" is not an allowed referer' : 'no HTTP_REFERER exists')); +} +$parsed_url_src = parse_url(@$_GET['src']); +if ($phpThumb->config_nohotlink_enabled && $phpThumb->config_nohotlink_erase_image && eregi('^(f|ht)tps?://', @$_GET['src']) && !in_array(@$parsed_url_src['host'], $phpThumb->config_nohotlink_valid_domains)) { + $phpThumb->ErrorImage($phpThumb->config_nohotlink_text_message); +} + +if ($phpThumb->config_mysql_query) { + if ($cid = @mysql_connect($phpThumb->config_mysql_hostname, $phpThumb->config_mysql_username, $phpThumb->config_mysql_password)) { + if (@mysql_select_db($phpThumb->config_mysql_database, $cid)) { + if ($result = @mysql_query($phpThumb->config_mysql_query, $cid)) { + if ($row = @mysql_fetch_array($result)) { + + mysql_free_result($result); + mysql_close($cid); + $phpThumb->setSourceData($row[0]); + unset($row); + + } else { + mysql_free_result($result); + mysql_close($cid); + $phpThumb->ErrorImage('no matching data in database.'); + } + } else { + mysql_close($cid); + $phpThumb->ErrorImage('Error in MySQL query: "'.mysql_error($cid).'"'); + } + } else { + mysql_close($cid); + $phpThumb->ErrorImage('cannot select MySQL database: "'.mysql_error($cid).'"'); + } + } else { + $phpThumb->ErrorImage('cannot connect to MySQL server'); + } + unset($_GET['id']); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[2]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '2') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if (@$PHPTHUMB_CONFIG['cache_default_only_suffix'] && (strpos($PHPTHUMB_CONFIG['cache_default_only_suffix'], '*') !== false)) { + $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = true; +} +$allowedGETparameters = array('src', 'new', 'w', 'h', 'wp', 'hp', 'wl', 'hl', 'ws', 'hs', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'zc', 'bc', 'bg', 'bgt', 'fltr', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'far', 'iar', 'maxb', 'down', 'phpThumbDebug', 'hash', 'md5s'); +foreach ($_GET as $key => $value) { + if (@$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS && ($key != 'src')) { + // disabled, do not set parameter + $phpThumb->DebugMessage('ignoring $_GET['.$key.'] because of $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS', __FILE__, __LINE__); + } elseif (in_array($key, $allowedGETparameters)) { + $phpThumb->DebugMessage('setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + $phpThumb->setParameter($key, $value); + } else { + $phpThumb->ErrorImage('Forbidden parameter: '.$key); + } +} + +if (!empty($PHPTHUMB_DEFAULTS) && is_array($PHPTHUMB_DEFAULTS)) { + $phpThumb->DebugMessage('setting $PHPTHUMB_DEFAULTS['.implode(';', array_keys($PHPTHUMB_DEFAULTS)).']', __FILE__, __LINE__); + foreach ($PHPTHUMB_DEFAULTS as $key => $value) { + if ($PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE || !isset($_GET[$key])) { + $phpThumb->DebugMessage('setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + $phpThumb->setParameter($key, $value); + } + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[3]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '3') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +//if (!@$_GET['phpThumbDebug'] && !$phpThumb->sourceFilename && !function_exists('ImageJPEG') && !function_exists('ImagePNG') && !function_exists('ImageGIF')) { +if (!@$_GET['phpThumbDebug'] && !is_file($phpThumb->sourceFilename) && !phpthumb_functions::gd_version()) { + if (!headers_sent()) { + // base64-encoded error image in GIF format + $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; + header('Content-Type: image/gif'); + echo base64_decode($ERROR_NOGD); + } else { + echo '*** ERROR: No PHP-GD support available ***'; + } + exit; +} + +// check to see if file can be output from source with no processing or caching +$CanPassThroughDirectly = true; +if ($phpThumb->rawImageData) { + // data from SQL, should be fine +} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because eregi("^(f|ht)tp\://", '.$phpThumb->src.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} elseif (!@is_file($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_file('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} elseif (!@is_readable($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_readable('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} +foreach ($_GET as $key => $value) { + switch ($key) { + case 'src': + // allowed + break; + + case 'w': + case 'h': + // might be OK if exactly matches original + break; + + case 'phpThumbDebug': + // handled in direct-passthru code + break; + + default: + // all other parameters will cause some processing, + // therefore cannot pass through original image unmodified + $CanPassThroughDirectly = false; + $UnAllowedGET[] = $key; + break; + } +} +if (!empty($UnAllowedGET)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because $_GET['.implode(';', array_unique($UnAllowedGET)).'] are set', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[4]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '4') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +function SendSaveAsFileHeaderIfNeeded() { + if (headers_sent()) { + return false; + } + global $phpThumb; + if (@$_GET['down']) { + $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $_GET['down']); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) { + $downloadfilename = trim($downloadfilename, '.'); + } + if (@$downloadfilename) { + $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: attachment; filename="'.$downloadfilename.'"', __FILE__, __LINE__); + header('Content-Disposition: attachment; filename="'.$downloadfilename.'"'); + return true; + } + } + $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: inline', __FILE__, __LINE__); + header('Content-Disposition: inline'); + return true; +} + +$phpThumb->DebugMessage('$CanPassThroughDirectly="'.intval($CanPassThroughDirectly).'" && $phpThumb->src="'.$phpThumb->src.'"', __FILE__, __LINE__); +while ($CanPassThroughDirectly && $phpThumb->src) { + // no parameters set, passthru + $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($phpThumb->src); + + // security and size checks + if ($phpThumb->getimagesizeinfo = @GetImageSize($SourceFilename)) { + $phpThumb->DebugMessage('Direct passthru GetImageSize() returned [w='.$phpThumb->getimagesizeinfo[0].';h='.$phpThumb->getimagesizeinfo[1].';t='.$phpThumb->getimagesizeinfo[2].']', __FILE__, __LINE__); + + if (!@$_REQUEST['w'] && !@$_REQUEST['wp'] && !@$_REQUEST['wl'] && !@$_REQUEST['ws'] && !@$_REQUEST['h'] && !@$_REQUEST['hp'] && !@$_REQUEST['hl'] && !@$_REQUEST['hs']) { + // no resizing needed + $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'")', __FILE__, __LINE__); + } elseif (($phpThumb->getimagesizeinfo[0] <= @$_REQUEST['w']) && ($phpThumb->getimagesizeinfo[1] <= @$_REQUEST['h']) && ((@$_REQUEST['w'] == $phpThumb->getimagesizeinfo[0]) || (@$_REQUEST['h'] == $phpThumb->getimagesizeinfo[1]))) { + // image fits into 'w'x'h' box, and at least one dimension matches exactly, therefore no resizing needed + $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" fits inside "'.@$_REQUEST['w'].'"x"'.@$_REQUEST['h'].'")', __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because resizing required (from "'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" to "'.@$_REQUEST['w'].'"x"'.@$_REQUEST['h'].'")', __FILE__, __LINE__); + break; + } + switch ($phpThumb->getimagesizeinfo[2]) { + case 1: // GIF + case 2: // JPG + case 3: // PNG + // great, let it through + break; + default: + // browser probably can't handle format, remangle it to JPEG/PNG/GIF + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because $phpThumb->getimagesizeinfo[2] = "'.$phpThumb->getimagesizeinfo[2].'"', __FILE__, __LINE__); + break 2; + } + + $ImageCreateFunctions = array(1=>'ImageCreateFromGIF', 2=>'ImageCreateFromJPEG', 3=>'ImageCreateFromPNG'); + $theImageCreateFunction = @$ImageCreateFunctions[$phpThumb->getimagesizeinfo[2]]; + if ($phpThumb->config_disable_onlycreateable_passthru || (function_exists($theImageCreateFunction) && ($dummyImage = @$theImageCreateFunction($SourceFilename)))) { + + // great + if (@is_resource($dummyImage)) { + unset($dummyImage); + } + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + if (@$_GET['phpThumbDebug']) { + $phpThumb->DebugTimingMessage('skipped direct $SourceFilename passthru', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have passed "'.$SourceFilename.'" through directly, but skipping due to phpThumbDebug', __FILE__, __LINE__); + break; + } + + SendSaveAsFileHeaderIfNeeded(); + header('Last-Modified: '.gmdate('D, d M Y H:i:s', @filemtime($SourceFilename)).' GMT'); + if ($contentType = phpthumb_functions::ImageTypeToMIMEtype(@$phpThumb->getimagesizeinfo[2])) { + header('Content-Type: '.$contentType); + } + @readfile($SourceFilename); + exit; + + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because ($phpThumb->config_disable_onlycreateable_passthru = "'.$phpThumb->config_disable_onlycreateable_passthru.'") and '.$theImageCreateFunction.'() failed', __FILE__, __LINE__); + break; + } + + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because GetImageSize() failed', __FILE__, __LINE__); + break; + } + break; +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[5]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '5') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +function RedirectToCachedFile() { + global $phpThumb, $PHPTHUMB_CONFIG; + + $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $phpThumb->cache_filename); + $nice_docroot = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($PHPTHUMB_CONFIG['document_root'], '/\\')); + + $parsed_url = @parse_url(@$_SERVER['HTTP_REFERER']); + + $nModified = filemtime($phpThumb->cache_filename); + + if ($phpThumb->config_nooffsitelink_enabled && @$_SERVER['HTTP_REFERER'] && !in_array(@$parsed_url['host'], $phpThumb->config_nooffsitelink_valid_domains)) { + + $phpThumb->DebugMessage('Would have used cached (image/'.$phpThumb->thumbnailFormat.') file "'.$phpThumb->cache_filename.'" (Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT), but skipping because $_SERVER[HTTP_REFERER] ('.@$_SERVER['HTTP_REFERER'].') is not in $phpThumb->config_nooffsitelink_valid_domains ('.implode(';', $phpThumb->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + + } elseif ($phpThumb->phpThumbDebug) { + + $phpThumb->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__); + $phpThumb->DebugMessage('* Would have sent headers (1): Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT', __FILE__, __LINE__); + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + $phpThumb->DebugMessage('* Would have sent headers (2): Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__); + } + if (ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { + $phpThumb->DebugMessage('* Would have sent headers (3): Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])), __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('* Would have sent data: readfile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + SendSaveAsFileHeaderIfNeeded(); + + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT'); + if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && @$_SERVER['SERVER_PROTOCOL']) { + header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); + exit; + } + + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2])); + } elseif (eregi('\.ico$', $phpThumb->cache_filename)) { + header('Content-Type: image/x-icon'); + } + if (!@$PHPTHUMB_CONFIG['cache_force_passthru'] && ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { + header('Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1]))); + } else { + @readfile($phpThumb->cache_filename); + } + exit; + + } + return true; +} + +// check to see if file already exists in cache, and output it with no processing if it does +$phpThumb->SetCacheFilename(); +if (@is_file($phpThumb->cache_filename)) { + RedirectToCachedFile(); +} else { + $phpThumb->DebugMessage('Cached file "'.$phpThumb->cache_filename.'" does not exist, processing as normal', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[6]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '6') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if ($phpThumb->rawImageData) { + + // great + +} elseif (@$_GET['new']) { + + // generate a blank image resource of the specified size/background color/opacity + if (($phpThumb->w <= 0) || ($phpThumb->h <= 0)) { + $phpThumb->ErrorImage('"w" and "h" parameters required for "new"'); + } + @list($bghexcolor, $opacity) = explode('|', $_GET['new']); + if (!phpthumb_functions::IsHexColor($bghexcolor)) { + $phpThumb->ErrorImage('BGcolor parameter for "new" is not valid'); + } + $opacity = (strlen($opacity) ? $opacity : 100); + if ($phpThumb->gdimg_source = phpthumb_functions::ImageCreateFunction($phpThumb->w, $phpThumb->h)) { + $alpha = (100 - min(100, max(0, $opacity))) * 1.27; + if ($alpha) { + $phpThumb->setParameter('is_alpha', true); + ImageAlphaBlending($phpThumb->gdimg_source, false); + phpthumb_functions::gd_ImageSaveAlpha($phpThumb->gdimg_source, true); + } + $new_background_color = phpthumb_functions::ImageHexColorAllocate($phpThumb->gdimg_source, $bghexcolor, false, $alpha); + ImageFilledRectangle($phpThumb->gdimg_source, 0, 0, $phpThumb->w, $phpThumb->h, $new_background_color); + } else { + $phpThumb->ErrorImage('failed to create "new" image ('.$phpThumb->w.'x'.$phpThumb->h.')'); + } + +} elseif (!$phpThumb->src) { + + $phpThumb->ErrorImage('Usage: '.$_SERVER['PHP_SELF'].'?src=/path/and/filename.jpg'."\n".'read Usage comments for details'); + +} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { + + if ($phpThumb->config_http_user_agent) { + ini_set('user_agent', $phpThumb->config_http_user_agent); + } + $basename = preg_quote(basename($phpThumb->src)); + $encoded = rawurlencode(basename($phpThumb->src)); + $HTTPurl = ereg_replace('(.*)'.$basename.'$', '\\1'.$encoded, $phpThumb->src); + if ($rawImageData = phpthumb_functions::SafeURLread($HTTPurl, $error)) { + $phpThumb->setSourceData($rawImageData, urlencode($phpThumb->src)); + } else { + $phpThumb->ErrorImage($error); + } + +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[7]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '7') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +$phpThumb->GenerateThumbnail(); + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[8]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '8') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if ($phpThumb->config_allow_parameter_file && $phpThumb->file) { + + $phpThumb->RenderToFile($phpThumb->ResolveFilenameToAbsolute($phpThumb->file)); + if ($phpThumb->config_allow_parameter_goto && $phpThumb->goto && eregi('^(f|ht)tps?://', $phpThumb->goto)) { + // redirect to another URL after image has been rendered to file + header('Location: '.$phpThumb->goto); + exit; + } + +} else { + + if ((file_exists($phpThumb->cache_filename) && is_writable($phpThumb->cache_filename)) || is_writable(dirname($phpThumb->cache_filename))) { + + $phpThumb->CleanUpCacheDirectory(); + if ($phpThumb->RenderToFile($phpThumb->cache_filename) && is_readable($phpThumb->cache_filename)) { + chmod($phpThumb->cache_filename, 0644); + RedirectToCachedFile(); + } else { + $phpThumb->DebugMessage('Failed: RenderToFile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + $phpThumb->DebugMessage('Cannot write to $phpThumb->cache_filename ('.$phpThumb->cache_filename.') because that directory ('.dirname($phpThumb->cache_filename).') is not writable', __FILE__, __LINE__); + + } + +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[9]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '9') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if (!$phpThumb->OutputThumbnail()) { + $phpThumb->ErrorImage('Error in OutputThumbnail():'."\n".$phpThumb->debugmessages[(count($phpThumb->debugmessages) - 1)]); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[10]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '10') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/phpthumb.bmp.php b/site/runshops/phpthumb/phpthumb.bmp.php new file mode 100644 index 0000000..4946226 --- /dev/null +++ b/site/runshops/phpthumb/phpthumb.bmp.php @@ -0,0 +1,874 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.graphic.bmp.php // +// module for analyzing BMP Image files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// +// // +// Modified for use in phpThumb() - James Heinrich 2004.07.27 // +// // +///////////////////////////////////////////////////////////////// + + +class phpthumb_bmp { + + function phpthumb_bmp() { + return true; + } + + function phpthumb_bmp2gd(&$BMPdata, $truecolor=true) { + $ThisFileInfo = array(); + if ($this->getid3_bmp($BMPdata, $ThisFileInfo, true, true)) { + $gd = $this->PlotPixelsGD($ThisFileInfo['bmp'], $truecolor); + return $gd; + } + return false; + } + + function phpthumb_bmpfile2gd($filename, $truecolor=true) { + if ($fp = @fopen($filename, 'rb')) { + $BMPdata = fread($fp, filesize($filename)); + fclose($fp); + return $this->phpthumb_bmp2gd($BMPdata, $truecolor); + } + return false; + } + + function GD2BMPstring(&$gd_image) { + $imageX = ImageSX($gd_image); + $imageY = ImageSY($gd_image); + + $BMP = ''; + for ($y = ($imageY - 1); $y >= 0; $y--) { + $thisline = ''; + for ($x = 0; $x < $imageX; $x++) { + $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); + $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']); + } + while (strlen($thisline) % 4) { + $thisline .= "\x00"; + } + $BMP .= $thisline; + } + + $bmpSize = strlen($BMP) + 14 + 40; + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + $BITMAPFILEHEADER = 'BM'; // WORD bfType; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String($bmpSize, 4); // DWORD bfSize; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved1; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved2; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 54, 4); // DWORD bfOffBits; + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + $BITMAPINFOHEADER = phpthumb_functions::LittleEndian2String( 40, 4); // DWORD biSize; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageX, 4); // LONG biWidth; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageY, 4); // LONG biHeight; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 1, 2); // WORD biPlanes; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 24, 2); // WORD biBitCount; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biCompression; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biSizeImage; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biXPelsPerMeter; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biYPelsPerMeter; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrUsed; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrImportant; + + return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP; + } + + function getid3_bmp(&$BMPdata, &$ThisFileInfo, $ExtractPalette=false, $ExtractData=false) { + + // shortcuts + $ThisFileInfo['bmp']['header']['raw'] = array(); + $thisfile_bmp = &$ThisFileInfo['bmp']; + $thisfile_bmp_header = &$thisfile_bmp['header']; + $thisfile_bmp_header_raw = &$thisfile_bmp_header['raw']; + + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + // all versions + // WORD bfType; + // DWORD bfSize; + // WORD bfReserved1; + // WORD bfReserved2; + // DWORD bfOffBits; + + $offset = 0; + $overalloffset = 0; + $BMPheader = substr($BMPdata, $overalloffset, 14 + 40); + $overalloffset += (14 + 40); + + $thisfile_bmp_header_raw['identifier'] = substr($BMPheader, $offset, 2); + $offset += 2; + + if ($thisfile_bmp_header_raw['identifier'] != 'BM') { + $ThisFileInfo['error'][] = 'Expecting "BM" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$thisfile_bmp_header_raw['identifier'].'"'; + unset($ThisFileInfo['fileformat']); + unset($ThisFileInfo['bmp']); + return false; + } + + $thisfile_bmp_header_raw['filesize'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['reserved2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['header_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + + // check if the hardcoded-to-1 "planes" is at offset 22 or 26 + $planes22 = $this->LittleEndian2Int(substr($BMPheader, 22, 2)); + $planes26 = $this->LittleEndian2Int(substr($BMPheader, 26, 2)); + if (($planes22 == 1) && ($planes26 != 1)) { + $thisfile_bmp['type_os'] = 'OS/2'; + $thisfile_bmp['type_version'] = 1; + } elseif (($planes26 == 1) && ($planes22 != 1)) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 12) { + $thisfile_bmp['type_os'] = 'OS/2'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 40) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 84) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 4; + } elseif ($thisfile_bmp_header_raw['header_size'] == 100) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 5; + } else { + $ThisFileInfo['error'][] = 'Unknown BMP subtype (or not a BMP file)'; + unset($ThisFileInfo['fileformat']); + unset($ThisFileInfo['bmp']); + return false; + } + + $ThisFileInfo['fileformat'] = 'bmp'; + $ThisFileInfo['video']['dataformat'] = 'bmp'; + $ThisFileInfo['video']['lossless'] = true; + $ThisFileInfo['video']['pixel_aspect_ratio'] = (float) 1; + + if ($thisfile_bmp['type_os'] == 'OS/2') { + + // OS/2-format BMP + // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm + + // DWORD Size; /* Size of this structure in bytes */ + // DWORD Width; /* Bitmap width in pixels */ + // DWORD Height; /* Bitmap height in pixel */ + // WORD NumPlanes; /* Number of bit planes (color depth) */ + // WORD BitsPerPixel; /* Number of bits per pixel per plane */ + + $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + + $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; + $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; + $ThisFileInfo['video']['codec'] = 'BI_RGB '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; + + if ($thisfile_bmp['type_version'] >= 2) { + // DWORD Compression; /* Bitmap compression scheme */ + // DWORD ImageDataSize; /* Size of bitmap data in bytes */ + // DWORD XResolution; /* X resolution of display device */ + // DWORD YResolution; /* Y resolution of display device */ + // DWORD ColorsUsed; /* Number of color table indices used */ + // DWORD ColorsImportant; /* Number of important color indices */ + // WORD Units; /* Type of units used to measure resolution */ + // WORD Reserved; /* Pad structure to 4-byte boundary */ + // WORD Recording; /* Recording algorithm */ + // WORD Rendering; /* Halftoning algorithm used */ + // DWORD Size1; /* Reserved for halftoning algorithm use */ + // DWORD Size2; /* Reserved for halftoning algorithm use */ + // DWORD ColorEncoding; /* Color model used in bitmap */ + // DWORD Identifier; /* Reserved for application use */ + + $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_units'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['recording'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['rendering'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['size1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['size2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['color_encoding'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['identifier'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['compression'] = $this->BMPcompressionOS2Lookup($thisfile_bmp_header_raw['compression']); + + $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + } + + } elseif ($thisfile_bmp['type_os'] == 'Windows') { + + // Windows-format BMP + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + // all versions + // DWORD biSize; + // LONG biWidth; + // LONG biHeight; + // WORD biPlanes; + // WORD biBitCount; + // DWORD biCompression; + // DWORD biSizeImage; + // LONG biXPelsPerMeter; + // LONG biYPelsPerMeter; + // DWORD biClrUsed; + // DWORD biClrImportant; + + $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['compression'] = $this->BMPcompressionWindowsLookup($thisfile_bmp_header_raw['compression']); + $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; + $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; + $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; + + if (($thisfile_bmp['type_version'] >= 4) || ($thisfile_bmp_header_raw['compression'] == 3)) { + // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen + $BMPheader .= substr($BMPdata, $overalloffset, 44); + $overalloffset += 44; + + // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp + // Win95+, WinNT4.0+ + // DWORD bV4RedMask; + // DWORD bV4GreenMask; + // DWORD bV4BlueMask; + // DWORD bV4AlphaMask; + // DWORD bV4CSType; + // CIEXYZTRIPLE bV4Endpoints; + // DWORD bV4GammaRed; + // DWORD bV4GammaGreen; + // DWORD bV4GammaBlue; + $thisfile_bmp_header_raw['red_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['green_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['blue_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['alpha_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['cs_type'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_red'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_green'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_blue'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['gamma_red'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['gamma_green'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['gamma_blue'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['ciexyz_red'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_red'])); + $thisfile_bmp_header['ciexyz_green'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_green'])); + $thisfile_bmp_header['ciexyz_blue'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_blue'])); + } + + if ($thisfile_bmp['type_version'] >= 5) { + $BMPheader .= substr($BMPdata, $overalloffset, 16); + $overalloffset += 16; + + // BITMAPV5HEADER - [16 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_7c36.asp + // Win98+, Win2000+ + // DWORD bV5Intent; + // DWORD bV5ProfileData; + // DWORD bV5ProfileSize; + // DWORD bV5Reserved; + $thisfile_bmp_header_raw['intent'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['profile_data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['profile_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['reserved3'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + } + + } else { + + $ThisFileInfo['error'][] = 'Unknown BMP format in header.'; + return false; + + } + + if ($ExtractPalette || $ExtractData) { + $PaletteEntries = 0; + if ($thisfile_bmp_header_raw['bits_per_pixel'] < 16) { + $PaletteEntries = pow(2, $thisfile_bmp_header_raw['bits_per_pixel']); + } elseif (isset($thisfile_bmp_header_raw['colors_used']) && ($thisfile_bmp_header_raw['colors_used'] > 0) && ($thisfile_bmp_header_raw['colors_used'] <= 256)) { + $PaletteEntries = $thisfile_bmp_header_raw['colors_used']; + } + if ($PaletteEntries > 0) { + $BMPpalette = substr($BMPdata, $overalloffset, 4 * $PaletteEntries); + $overalloffset += 4 * $PaletteEntries; + + $paletteoffset = 0; + for ($i = 0; $i < $PaletteEntries; $i++) { + // RGBQUAD - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_5f8y.asp + // BYTE rgbBlue; + // BYTE rgbGreen; + // BYTE rgbRed; + // BYTE rgbReserved; + $blue = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + $green = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + $red = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + if (($thisfile_bmp['type_os'] == 'OS/2') && ($thisfile_bmp['type_version'] == 1)) { + // no padding byte + } else { + $paletteoffset++; // padding byte + } + $thisfile_bmp['palette'][$i] = (($red << 16) | ($green << 8) | ($blue)); + } + } + } + + if ($ExtractData) { + $RowByteLength = ceil(($thisfile_bmp_header_raw['width'] * ($thisfile_bmp_header_raw['bits_per_pixel'] / 8)) / 4) * 4; // round up to nearest DWORD boundry + + $BMPpixelData = substr($BMPdata, $thisfile_bmp_header_raw['data_offset'], $thisfile_bmp_header_raw['height'] * $RowByteLength); + $overalloffset = $thisfile_bmp_header_raw['data_offset'] + ($thisfile_bmp_header_raw['height'] * $RowByteLength); + + $pixeldataoffset = 0; + switch (@$thisfile_bmp_header_raw['compression']) { + + case 0: // BI_RGB + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 1: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { + $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); + for ($i = 7; $i >= 0; $i--) { + $paletteindex = ($paletteindexbyte & (0x01 << $i)) >> $i; + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $col++; + } + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 4: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { + $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); + for ($i = 1; $i >= 0; $i--) { + $paletteindex = ($paletteindexbyte & (0x0F << (4 * $i))) >> (4 * $i); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $col++; + } + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 8: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $paletteindex = ord($BMPpixelData{$pixeldataoffset++}); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 24: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); + $pixeldataoffset += 3; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 32: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+3}) << 24) | (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); + $pixeldataoffset += 4; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 16: + // ? + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + case 1: // BI_RLE8 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 8: + $pixelcounter = 0; + while ($pixeldataoffset < strlen($BMPpixelData)) { + $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + if ($firstbyte == 0) { + + // escaped/absolute mode - the first byte of the pair can be set to zero to + // indicate an escape character that denotes the end of a line, the end of + // a bitmap, or a delta, depending on the value of the second byte. + switch ($secondbyte) { + case 0: + // end of line + // no need for special processing, just ignore + break; + + case 1: + // end of bitmap + $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case + break; + + case 2: + // delta - The 2 bytes following the escape contain unsigned values + // indicating the horizontal and vertical offsets of the next pixel + // from the current position. + $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; + $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; + $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; + break; + + default: + // In absolute mode, the first byte is zero and the second byte is a + // value in the range 03H through FFH. The second byte represents the + // number of bytes that follow, each of which contains the color index + // of a single pixel. Each run must be aligned on a word boundary. + for ($i = 0; $i < $secondbyte; $i++) { + $paletteindex = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $pixelcounter++; + } + while (($pixeldataoffset % 2) != 0) { + // Each run must be aligned on a word boundary. + $pixeldataoffset++; + } + break; + } + + } else { + + // encoded mode - the first byte specifies the number of consecutive pixels + // to be drawn using the color index contained in the second byte. + for ($i = 0; $i < $firstbyte; $i++) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$secondbyte]; + $pixelcounter++; + } + + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + + case 2: // BI_RLE4 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 4: + $pixelcounter = 0; + while ($pixeldataoffset < strlen($BMPpixelData)) { + $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + if ($firstbyte == 0) { + + // escaped/absolute mode - the first byte of the pair can be set to zero to + // indicate an escape character that denotes the end of a line, the end of + // a bitmap, or a delta, depending on the value of the second byte. + switch ($secondbyte) { + case 0: + // end of line + // no need for special processing, just ignore + break; + + case 1: + // end of bitmap + $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case + break; + + case 2: + // delta - The 2 bytes following the escape contain unsigned values + // indicating the horizontal and vertical offsets of the next pixel + // from the current position. + $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; + $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; + $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; + break; + + default: + // In absolute mode, the first byte is zero. The second byte contains the number + // of color indexes that follow. Subsequent bytes contain color indexes in their + // high- and low-order 4 bits, one color index for each pixel. In absolute mode, + // each run must be aligned on a word boundary. + unset($paletteindexes); + for ($i = 0; $i < ceil($secondbyte / 2); $i++) { + $paletteindexbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $paletteindexes[] = ($paletteindexbyte & 0xF0) >> 4; + $paletteindexes[] = ($paletteindexbyte & 0x0F); + } + while (($pixeldataoffset % 2) != 0) { + // Each run must be aligned on a word boundary. + $pixeldataoffset++; + } + + foreach ($paletteindexes as $dummy => $paletteindex) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $pixelcounter++; + } + break; + } + + } else { + + // encoded mode - the first byte of the pair contains the number of pixels to be + // drawn using the color indexes in the second byte. The second byte contains two + // color indexes, one in its high-order 4 bits and one in its low-order 4 bits. + // The first of the pixels is drawn using the color specified by the high-order + // 4 bits, the second is drawn using the color in the low-order 4 bits, the third + // is drawn using the color in the high-order 4 bits, and so on, until all the + // pixels specified by the first byte have been drawn. + $paletteindexes[0] = ($secondbyte & 0xF0) >> 4; + $paletteindexes[1] = ($secondbyte & 0x0F); + for ($i = 0; $i < $firstbyte; $i++) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindexes[($i % 2)]]; + $pixelcounter++; + } + + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + case 3: // BI_BITFIELDS + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 16: + case 32: + $redshift = 0; + $greenshift = 0; + $blueshift = 0; + if (!$thisfile_bmp_header_raw['red_mask'] || !$thisfile_bmp_header_raw['green_mask'] || !$thisfile_bmp_header_raw['blue_mask']) { + $ThisFileInfo['error'][] = 'missing $thisfile_bmp_header_raw[(red|green|blue)_mask]'; + return false; + } + while ((($thisfile_bmp_header_raw['red_mask'] >> $redshift) & 0x01) == 0) { + $redshift++; + } + while ((($thisfile_bmp_header_raw['green_mask'] >> $greenshift) & 0x01) == 0) { + $greenshift++; + } + while ((($thisfile_bmp_header_raw['blue_mask'] >> $blueshift) & 0x01) == 0) { + $blueshift++; + } + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $pixelvalue = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset, $thisfile_bmp_header_raw['bits_per_pixel'] / 8)); + $pixeldataoffset += $thisfile_bmp_header_raw['bits_per_pixel'] / 8; + + $red = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['red_mask']) >> $redshift) / ($thisfile_bmp_header_raw['red_mask'] >> $redshift)) * 255)); + $green = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['green_mask']) >> $greenshift) / ($thisfile_bmp_header_raw['green_mask'] >> $greenshift)) * 255)); + $blue = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['blue_mask']) >> $blueshift) / ($thisfile_bmp_header_raw['blue_mask'] >> $blueshift)) * 255)); + $thisfile_bmp['data'][$row][$col] = (($red << 16) | ($green << 8) | ($blue)); + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + default: // unhandled compression type + $ThisFileInfo['error'][] = 'Unknown/unhandled compression type value ('.$thisfile_bmp_header_raw['compression'].') - cannot decompress pixel data'; + break; + } + } + + return true; + } + + function IntColor2RGB($color) { + $red = ($color & 0x00FF0000) >> 16; + $green = ($color & 0x0000FF00) >> 8; + $blue = ($color & 0x000000FF); + return array($red, $green, $blue); + } + + function PlotPixelsGD(&$BMPdata, $truecolor=true) { + $imagewidth = $BMPdata['header']['raw']['width']; + $imageheight = $BMPdata['header']['raw']['height']; + + if ($truecolor) { + + $gd = @ImageCreateTrueColor($imagewidth, $imageheight); + + } else { + + $gd = @ImageCreate($imagewidth, $imageheight); + if (!empty($BMPdata['palette'])) { + // create GD palette from BMP palette + foreach ($BMPdata['palette'] as $dummy => $color) { + list($r, $g, $b) = $this->IntColor2RGB($color); + ImageColorAllocate($gd, $r, $g, $b); + } + } else { + // create 216-color websafe palette + for ($r = 0x00; $r <= 0xFF; $r += 0x33) { + for ($g = 0x00; $g <= 0xFF; $g += 0x33) { + for ($b = 0x00; $b <= 0xFF; $b += 0x33) { + ImageColorAllocate($gd, $r, $g, $b); + } + } + } + } + + } + if (!is_resource($gd)) { + return false; + } + + foreach ($BMPdata['data'] as $row => $colarray) { + @set_time_limit(30); + foreach ($colarray as $col => $color) { + list($red, $green, $blue) = $this->IntColor2RGB($color); + if ($truecolor) { + $pixelcolor = ImageColorAllocate($gd, $red, $green, $blue); + } else { + $pixelcolor = ImageColorClosest($gd, $red, $green, $blue); + } + ImageSetPixel($gd, $col, $row, $pixelcolor); + } + } + return $gd; + } + + function PlotBMP(&$BMPinfo) { + $starttime = time(); + if (!isset($BMPinfo['bmp']['data']) || !is_array($BMPinfo['bmp']['data'])) { + echo 'ERROR: no pixel data
    '; + return false; + } + set_time_limit(intval(round($BMPinfo['resolution_x'] * $BMPinfo['resolution_y'] / 10000))); + $im = $this->PlotPixelsGD($BMPinfo['bmp']); + if (headers_sent()) { + echo 'plotted '.($BMPinfo['resolution_x'] * $BMPinfo['resolution_y']).' pixels in '.(time() - $starttime).' seconds
    '; + ImageDestroy($im); + exit; + } else { + header('Content-Type: image/png'); + ImagePNG($im); + ImageDestroy($im); + return true; + } + return false; + } + + function BMPcompressionWindowsLookup($compressionid) { + static $BMPcompressionWindowsLookup = array( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'BI_BITFIELDS', + 4 => 'BI_JPEG', + 5 => 'BI_PNG' + ); + return (isset($BMPcompressionWindowsLookup[$compressionid]) ? $BMPcompressionWindowsLookup[$compressionid] : 'invalid'); + } + + function BMPcompressionOS2Lookup($compressionid) { + static $BMPcompressionOS2Lookup = array( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'Huffman 1D', + 4 => 'BI_RLE24', + ); + return (isset($BMPcompressionOS2Lookup[$compressionid]) ? $BMPcompressionOS2Lookup[$compressionid] : 'invalid'); + } + + + // from getid3.lib.php + + function trunc($floatnumber) { + // truncates a floating-point number at the decimal point + // returns int (if possible, otherwise float) + if ($floatnumber >= 1) { + $truncatednumber = floor($floatnumber); + } elseif ($floatnumber <= -1) { + $truncatednumber = ceil($floatnumber); + } else { + $truncatednumber = 0; + } + if ($truncatednumber <= 1073741824) { // 2^30 + $truncatednumber = (int) $truncatednumber; + } + return $truncatednumber; + } + + function LittleEndian2Int($byteword) { + $intvalue = 0; + $byteword = strrev($byteword); + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i)); + } + return $intvalue; + } + + function BigEndian2Int($byteword) { + return $this->LittleEndian2Int(strrev($byteword)); + } + + function BigEndian2Bin($byteword) { + $binvalue = ''; + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT); + } + return $binvalue; + } + + function FixedPoint2_30($rawdata) { + $binarystring = $this->BigEndian2Bin($rawdata); + return $this->Bin2Dec(substr($binarystring, 0, 2)) + (float) ($this->Bin2Dec(substr($binarystring, 2, 30)) / 1073741824); + } + + function Bin2Dec($binstring, $signed=false) { + $signmult = 1; + if ($signed) { + if ($binstring{0} == '1') { + $signmult = -1; + } + $binstring = substr($binstring, 1); + } + $decvalue = 0; + for ($i = 0; $i < strlen($binstring); $i++) { + $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i); + } + return $this->CastAsInt($decvalue * $signmult); + } + + function CastAsInt($floatnum) { + // convert to float if not already + $floatnum = (float) $floatnum; + + // convert a float to type int, only if possible + if ($this->trunc($floatnum) == $floatnum) { + // it's not floating point + if ($floatnum <= 1073741824) { // 2^30 + // it's within int range + $floatnum = (int) $floatnum; + } + } + return $floatnum; + } + +} + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/phpthumb.class.php b/site/runshops/phpthumb/phpthumb.class.php new file mode 100644 index 0000000..14865fd --- /dev/null +++ b/site/runshops/phpthumb/phpthumb.class.php @@ -0,0 +1,3170 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'")'); +} +ob_end_clean(); + +class phpthumb { + + // public: + // START PARAMETERS (for object mode and phpThumb.php) + // See phpthumb.readme.txt for descriptions of what each of these values are + var $src = null; // SouRCe filename + var $new = null; // NEW image (phpThumb.php only) + var $w = null; // Width + var $h = null; // Height + var $wp = null; // Width (Portrait Images Only) + var $hp = null; // Height (Portrait Images Only) + var $wl = null; // Width (Landscape Images Only) + var $hl = null; // Height (Landscape Images Only) + var $ws = null; // Width (Square Images Only) + var $hs = null; // Height (Square Images Only) + var $f = null; // Format + var $q = 75; // jpeg output Quality + var $sx = null; // Source crop top-left X position + var $sy = null; // Source crop top-left Y position + var $sw = null; // Source crop Width + var $sh = null; // Source crop Height + var $zc = null; // Zoom Crop + var $bc = null; // Border Color + var $bg = null; // BackGround color + var $fltr = array(); // FiLTeRs + var $goto = null; // GO TO url after processing + var $err = null; // default ERRor image filename + var $xto = null; // extract eXif Thumbnail Only + var $ra = null; // Rotate by Angle + var $ar = null; // Auto Rotate + var $aoe = null; // Allow Output Enlargement + var $far = null; // Fixed Aspect Ratio + var $iar = null; // Ignore Aspect Ratio + var $maxb = null; // MAXimum Bytes + var $down = null; // DOWNload thumbnail filename + var $md5s = null; // MD5 hash of Source image + var $file = null; // >>deprecated, do not use<< + + var $phpThumbDebug = null; + // END PARAMETERS + + + // public: + // START CONFIGURATION OPTIONS (for object mode only) + // See phpThumb.config.php for descriptions of what each of these settings do + + // * Directory Configuration + var $config_cache_directory = null; + var $config_cache_disable_warning = true; + var $config_cache_source_enabled = false; + var $config_cache_source_directory = null; + var $config_temp_directory = null; + var $config_document_root = null; + + // * Default output configuration: + var $config_output_format = 'jpeg'; + var $config_output_maxwidth = 0; + var $config_output_maxheight = 0; + var $config_output_interlace = true; + + // * Error message configuration + var $config_error_image_width = 400; + var $config_error_image_height = 100; + var $config_error_message_image_default = ''; + var $config_error_bgcolor = 'CCCCFF'; + var $config_error_textcolor = 'FF0000'; + var $config_error_fontsize = 1; + var $config_error_die_on_error = true; + var $config_error_silent_die_on_error = false; + var $config_error_die_on_source_failure = true; + + // * Anti-Hotlink Configuration: + var $config_nohotlink_enabled = true; + var $config_nohotlink_valid_domains = array(); + var $config_nohotlink_erase_image = true; + var $config_nohotlink_text_message = 'Off-server thumbnailing is not allowed'; + // * Off-server Linking Configuration: + var $config_nooffsitelink_enabled = false; + var $config_nooffsitelink_valid_domains = array(); + var $config_nooffsitelink_require_refer = false; + var $config_nooffsitelink_erase_image = true; + var $config_nooffsitelink_text_message = 'Off-server linking is not allowed'; + + // * Border & Background default colors + var $config_border_hexcolor = '000000'; + var $config_background_hexcolor = 'FFFFFF'; + + // * TrueType Fonts + var $config_ttf_directory = '.'; + + var $config_max_source_pixels = null; + var $config_use_exif_thumbnail_for_speed = false; + + var $config_imagemagick_path = null; + var $config_prefer_imagemagick = true; + + var $config_cache_maxage = null; + var $config_cache_maxsize = null; + var $config_cache_maxfiles = null; + var $config_cache_source_filemtime_ignore_local = false; + var $config_cache_source_filemtime_ignore_remote = true; + var $config_cache_default_only_suffix = false; + var $config_cache_force_passthru = true; + var $config_cache_prefix = ''; // default value set in the constructor below + + // * MySQL + var $config_mysql_query = null; + var $config_mysql_hostname = null; + var $config_mysql_username = null; + var $config_mysql_password = null; + var $config_mysql_database = null; + + // * Security + var $config_high_security_enabled = false; + var $config_config_high_security_password = null; + var $config_disable_debug = false; + var $config_allow_src_above_docroot = false; + var $config_allow_src_above_phpthumb = true; + var $config_allow_parameter_file = false; + var $config_allow_parameter_goto = false; + + // * Compatability + var $config_disable_pathinfo_parsing = false; + var $config_disable_imagecopyresampled = false; + var $config_disable_onlycreateable_passthru = false; + + var $config_http_user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; + + // END CONFIGURATION OPTIONS + + + // public: error messages (read-only) + var $debugmessages = array(); + var $debugtiming = array(); + var $fatalerror = null; + + + // private: (should not be modified directly) + var $thumbnailQuality = 75; + var $thumbnailFormat = null; + + var $sourceFilename = null; + var $rawImageData = null; + var $IMresizedData = null; + + var $useRawIMoutput = false; + + var $gdimg_output = null; + var $gdimg_source = null; + + var $getimagesizeinfo = null; + + var $source_width = null; + var $source_height = null; + + var $thumbnailCropX = null; + var $thumbnailCropY = null; + var $thumbnailCropW = null; + var $thumbnailCropH = null; + + var $exif_thumbnail_width = null; + var $exif_thumbnail_height = null; + var $exif_thumbnail_type = null; + var $exif_thumbnail_data = null; + + var $thumbnail_width = null; + var $thumbnail_height = null; + var $thumbnail_image_width = null; + var $thumbnail_image_height = null; + + var $cache_filename = null; + + var $AlphaCapableFormats = array('png', 'ico', 'gif'); + var $is_alpha = false; + + var $iswindows = null; + + var $phpthumb_version = '1.7.0-200602150817'; + + ////////////////////////////////////////////////////////////////////// + + // public: constructor + function phpThumb() { + $this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__); + $this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__); + $this->config_max_source_pixels = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); // 20% of memory_limit + + //if (phpthumb_functions::gd_version() < 1) { + // die('No GD support detected'); + //} + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + $this->iswindows = true; + } else { + $this->iswindows = false; + } + if (@$_SERVER['DOCUMENT_ROOT']) { + $this->config_document_root = $_SERVER['DOCUMENT_ROOT']; + } + $this->config_cache_prefix = 'phpThumb_cache_'.@$_SERVER['SERVER_NAME']; + } + + // public: + function setSourceFilename($sourceFilename) { + $this->rawImageData = null; + $this->sourceFilename = $sourceFilename; + $this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->sourceFilename to "'.$this->sourceFilename.'"', __FILE__, __LINE__); + return true; + } + + // public: + function setSourceData($rawImageData, $sourceFilename='') { + $this->sourceFilename = null; + $this->rawImageData = $rawImageData; + $this->DebugMessage('setSourceData() setting $this->rawImageData ('.strlen($this->rawImageData).' bytes)', __FILE__, __LINE__); + if ($this->config_cache_source_enabled) { + $sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData)); + if (!is_dir($this->config_cache_source_directory)) { + $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory'); + } elseif (!is_writable($this->config_cache_source_directory)) { + $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable'); + } + $this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).'"', __FILE__, __LINE__); + if ($fp = @fopen($this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename), 'wb')) { + fwrite($fp, $rawImageData); + fclose($fp); + } elseif (!$this->phpThumbDebug) { + $this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).')'); + } + } + return true; + } + + // public: + function setSourceImageResource($gdimg) { + $this->gdimg_source = $gdimg; + return true; + } + + // public: + function setParameter($param, $value) { + switch ($param) { + case 'src': + $this->setSourceFilename($this->ResolveFilenameToAbsolute($value)); + break; + + default: + $this->$param = $value; + break; + } + $this->$param = $value; + return true; + } + + // public: + function getParameter($param) { + //if (property_exists('phpThumb', $param)) { + return $this->$param; + //} + //$this->DebugMessage('setParameter() attempting to set non-existant parameter "'.$param.'"', __FILE__, __LINE__); + //return false; + } + + + // public: + function GenerateThumbnail() { + + $this->setOutputFormat(); + $this->ResolveSource(); + $this->SetCacheFilename(); + $this->ExtractEXIFgetImageSize(); + if ($this->useRawIMoutput) { + $this->DebugMessage('Skipping rest of GenerateThumbnail() because $this->useRawIMoutput', __FILE__, __LINE__); + return true; + } + if (!$this->SourceImageToGD()) { + $this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__); + return false; + } + $this->Rotate(); + $this->CreateGDoutput(); + + switch ($this->far) { + case 'L': + case 'TL': + case 'BL': + $destination_offset_x = 0; + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + break; + case 'R': + case 'TR': + case 'BR': + $destination_offset_x = round($this->thumbnail_width - $this->thumbnail_image_width); + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + break; + case 'T': + case 'TL': + case 'TR': + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = 0; + break; + case 'B': + case 'BL': + case 'BR': + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = round($this->thumbnail_height - $this->thumbnail_image_height); + break; + case 'C': + default: + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + } + + // copy/resize image to appropriate dimensions + $this->DebugMessage('ImageResizeFunction($o, $s, '.$destination_offset_x.', '.$destination_offset_y.', '.$this->thumbnailCropX.', '.$this->thumbnailCropY.', '.$this->thumbnail_image_width.', '.$this->thumbnail_image_height.', '.$this->thumbnailCropW.', '.$this->thumbnailCropH.')', __FILE__, __LINE__); + $this->ImageResizeFunction( + $this->gdimg_output, + $this->gdimg_source, + $destination_offset_x, + $destination_offset_y, + $this->thumbnailCropX, + $this->thumbnailCropY, + $this->thumbnail_image_width, + $this->thumbnail_image_height, + $this->thumbnailCropW, + $this->thumbnailCropH + ); + + $this->DebugMessage('memory_get_usage() after copy-resize = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); + ImageDestroy($this->gdimg_source); + $this->DebugMessage('memory_get_usage() after ImageDestroy = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); + + $this->AntiOffsiteLinking(); + $this->ApplyFilters(); + $this->AlphaChannelFlatten(); + $this->MaxFileSize(); + + $this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__); + return true; + } + + + // public: + function RenderToFile($filename) { + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { + $this->DebugMessage('RenderToFile('.$filename.') failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); + return false; + } + if (!$this->thumbnailFormat) { + $this->DebugMessage('RenderToFile() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__); + return false; + } + // render thumbnail to this file only, do not cache, do not output to browser + //$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename); + $renderfilename = $filename; + if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) { + $renderfilename = $this->ResolveFilenameToAbsolute($renderfilename); + } + if (!is_writable(dirname($renderfilename))) { + $this->DebugMessage('RenderToFile() failed because "'.dirname($renderfilename).'/" is not writable', __FILE__, __LINE__); + return false; + } + if (is_file($renderfilename) && !is_writable($renderfilename)) { + $this->DebugMessage('RenderToFile() failed because "'.$renderfilename.'" is not writable', __FILE__, __LINE__); + return false; + } + + if ($this->useRawIMoutput) { + + $this->DebugMessage('RenderToFile copying $this->IMresizedData ('.strlen($this->IMresizedData).' bytes) to "'.$renderfilename.'"', __FILE__, __LINE__); + return file_put_contents($renderfilename, $this->IMresizedData); + + } else { + + $this->DebugMessage('RenderToFile('.$filename.') attempting Image'.strtoupper(@$this->thumbnailFormat).'($this->gdimg_output, '.$renderfilename.')', __FILE__, __LINE__); + ob_start(); + switch ($this->thumbnailFormat) { + case 'jpeg': + $ImageOutFunction = 'image'.$this->thumbnailFormat; + $ImageOutFunction($this->gdimg_output, $renderfilename, $this->thumbnailQuality); + break; + + case 'png': + case 'gif': + $ImageOutFunction = 'image'.$this->thumbnailFormat; + $ImageOutFunction($this->gdimg_output, $renderfilename); + break; + + case 'bmp': + $ImageOutFunction = '"builtin BMP output"'; + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $phpthumb_bmp = new phpthumb_bmp(); + $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); + unset($phpthumb_bmp); + if (!$bmp_data) { + $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + if (!file_put_contents($renderfilename, $bmp_data)) { + $this->DebugMessage('file_put_contents('.$renderfilename.', ['.strlen($bmp_data).' bytes]) failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + break; + + case 'ico': + $ImageOutFunction = '"builtin ICO output"'; + if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $phpthumb_ico = new phpthumb_ico(); + $arrayOfOutputImages = array($this->gdimg_output); + $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); + unset($phpthumb_ico); + if (!$ico_data) { + $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + if (!file_put_contents($renderfilename, $ico_data)) { + $this->DebugMessage('file_put_contents('.$renderfilename.', ['.strlen($ico_data).' bytes]) failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + break; + + default: + $this->DebugMessage('RenderToFile failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $errormessage = strip_tags(ob_get_contents()); + ob_end_clean(); + if ($errormessage) { + $this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] failed with message "'.$errormessage.'"', __FILE__, __LINE__); + return false; + } elseif (!file_exists($renderfilename)) { + $this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__); + } + + } + return true; + } + + + // public: + function OutputThumbnail() { + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { + $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); + return false; + } + if (headers_sent()) { + return $this->ErrorImage('OutputThumbnail() failed - headers already sent'); + exit; + } + + if ($this->down) { + $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $this->down); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) { + $downloadfilename = trim($downloadfilename, '.'); + } + if ($downloadfilename != $this->down) { + $this->DebugMessage('renaming output file for "down" from "'.$this->down.'" to "'.$downloadfilename.'"', __FILE__, __LINE__); + } + if ($downloadfilename) { + header('Content-Disposition: attachment; filename="'.$downloadfilename.'"'); + } else { + $this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__); + } + } + + if ($this->useRawIMoutput) { + + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $this->IMresizedData; + + } else { + + $this->DebugMessage('ImageInterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__); + ImageInterlace($this->gdimg_output, intval($this->config_output_interlace)); + switch ($this->thumbnailFormat) { + case 'jpeg': + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + $ImageOutFunction = 'image'.$this->thumbnailFormat; + @$ImageOutFunction($this->gdimg_output, '', $this->thumbnailQuality); + break; + + case 'png': + case 'gif': + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + $ImageOutFunction = 'image'.$this->thumbnailFormat; + @$ImageOutFunction($this->gdimg_output); + break; + + case 'bmp': + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); + return false; + } + $phpthumb_bmp = new phpthumb_bmp(); + if (is_object($phpthumb_bmp)) { + $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); + unset($phpthumb_bmp); + if (!$bmp_data) { + $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); + return false; + } + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $bmp_data; + } else { + $this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__); + return false; + } + break; + + case 'ico': + if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); + return false; + } + $phpthumb_ico = new phpthumb_ico(); + if (is_object($phpthumb_ico)) { + $arrayOfOutputImages = array($this->gdimg_output); + $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); + unset($phpthumb_ico); + if (!$ico_data) { + $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); + return false; + } + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $ico_data; + } else { + $this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__); + return false; + } + break; + + default: + $this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); + return false; + break; + } + + } + return true; + } + + + // public: + function CleanUpCacheDirectory() { + if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) { + $CacheDirOldFilesAge = array(); + $CacheDirOldFilesSize = array(); + if ($dirhandle = opendir($this->config_cache_directory)) { + while ($oldcachefile = readdir($dirhandle)) { + if (eregi('^phpThumb_cache_', $oldcachefile)) { + $CacheDirOldFilesAge[$oldcachefile] = fileatime($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + if ($CacheDirOldFilesAge[$oldcachefile] == 0) { + $CacheDirOldFilesAge[$oldcachefile] = filemtime($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + } + + $CacheDirOldFilesSize[$oldcachefile] = filesize($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile); + } + } + } + asort($CacheDirOldFilesAge); + + if ($this->config_cache_maxfiles > 0) { + $TotalCachedFiles = count($CacheDirOldFilesAge); + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($TotalCachedFiles > $this->config_cache_maxfiles) { + $TotalCachedFiles--; + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // there are few enough files to keep the rest + break; + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + if ($this->config_cache_maxage > 0) { + $mindate = time() - $this->config_cache_maxage; + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($filedate > 0) { + if ($filedate < $mindate) { + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // the rest of the files are new enough to keep + break; + } + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + if ($this->config_cache_maxsize > 0) { + $TotalCachedFileSize = array_sum($CacheDirOldFilesSize); + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { + if ($TotalCachedFileSize > $this->config_cache_maxsize) { + $TotalCachedFileSize -= $CacheDirOldFilesSize[$oldcachefile]; + if (@unlink($this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile)) { + $DeletedKeys[] = $oldcachefile; + } + } else { + // the total filesizes are small enough to keep the rest of the files + break; + } + } + foreach ($DeletedKeys as $dummy => $oldcachefile) { + unset($CacheDirOldFilesAge[$oldcachefile]); + unset($CacheDirOldFilesSize[$oldcachefile]); + } + } + + } + return true; + } + + ////////////////////////////////////////////////////////////////////// + + function ResolveSource() { + if (is_resource($this->gdimg_source)) { + $this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__); + return true; + } + if ($this->rawImageData) { + $this->sourceFilename = null; + $this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set', __FILE__, __LINE__); + return true; + } + if ($this->sourceFilename) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename); + $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'"', __FILE__, __LINE__); + } else { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); + $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'" from $this->src ('.$this->src.')', __FILE__, __LINE__); + } + if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) { + // Windows \\share\filename.ext + } elseif (eregi('^(f|ht)tps?://', $this->sourceFilename)) { + // URL + if ($this->config_http_user_agent) { + ini_set('user_agent', $this->config_http_user_agent); + } + } elseif (!file_exists($this->sourceFilename)) { + return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist'); + } elseif (!is_file($this->sourceFilename)) { + return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file'); + } + return true; + } + + function setOutputFormat() { + static $alreadyCalled = false; + if ($this->thumbnailFormat && $alreadyCalled) { + return true; + } + $alreadyCalled = true; + + $AvailableImageOutputFormats = array(); + $AvailableImageOutputFormats[] = 'text'; + if (is_readable(dirname(__FILE__).'/phpthumb.ico.php')) { + $AvailableImageOutputFormats[] = 'ico'; + } + if (is_readable(dirname(__FILE__).'/phpthumb.bmp.php')) { + $AvailableImageOutputFormats[] = 'bmp'; + } + + $this->thumbnailFormat = 'ico'; + + // Set default output format based on what image types are available + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_WBMP) { + $this->thumbnailFormat = 'wbmp'; + $AvailableImageOutputFormats[] = 'wbmp'; + } + if ($imagetypes & IMG_GIF) { + $this->thumbnailFormat = 'gif'; + $AvailableImageOutputFormats[] = 'gif'; + } + if ($imagetypes & IMG_PNG) { + $this->thumbnailFormat = 'png'; + $AvailableImageOutputFormats[] = 'png'; + } + if ($imagetypes & IMG_JPG) { + $this->thumbnailFormat = 'jpeg'; + $AvailableImageOutputFormats[] = 'jpeg'; + } + } else { + //return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?'); + $this->DebugMessage('ImageTypes() does not exist - GD support might not be enabled?', __FILE__, __LINE__); + } + if ($this->ImageMagickVersion()) { + $IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico'); + $this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats ('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); + foreach ($IMformats as $key => $format) { + $AvailableImageOutputFormats[] = $format; + } + } + $AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats); + $this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); + + if (strtolower($this->config_output_format) == 'jpg') { + $this->config_output_format = 'jpeg'; + } + if (strtolower($this->f) == 'jpg') { + $this->f = 'jpeg'; + } + if (in_array(strtolower($this->config_output_format), $AvailableImageOutputFormats)) { + // set output format to config default if that format is available + $this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__); + $this->thumbnailFormat = strtolower($this->config_output_format); + } elseif ($this->config_output_format) { + $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->config_output_format ('.strtolower($this->config_output_format).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); + } + if ($this->f && (in_array(strtolower($this->f), $AvailableImageOutputFormats))) { + // override output format if $this->f is set and that format is available + $this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__); + $this->thumbnailFormat = strtolower($this->f); + } elseif ($this->f) { + $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->f ('.strtolower($this->f).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); + } + + // for JPEG images, quality 1 (worst) to 99 (best) + // quality < 25 is nasty, with not much size savings - not recommended + // problems with 100 - invalid JPEG? + $this->thumbnailQuality = max(1, min(99, ($this->q ? $this->q : 75))); + $this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__); + + return true; + } + + function setCacheDirectory() { + // resolve cache directory to absolute pathname + $this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__); + if (substr($this->config_cache_directory, 0, 1) == '.') { + if (eregi('^(f|ht)tps?://', $this->src)) { + if (!$this->config_cache_disable_warning) { + $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); + } + } elseif ($this->src) { + // resolve relative cache directory to source image + $this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory; + } else { + // $this->new is probably set + } + } + if (substr($this->config_cache_directory, -1) == '/') { + $this->config_cache_directory = substr($this->config_cache_directory, 0, -1); + } + if ($this->iswindows) { + $this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory); + } + if ($this->config_cache_directory) { + $real_cache_path = realpath($this->config_cache_directory); + if (!$real_cache_path) { + $this->DebugMessage('realpath($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__); + if (!is_dir($this->config_cache_directory)) { + $this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__); + } + } + if ($real_cache_path) { + $this->DebugMessage('setting config_cache_directory to realpath('.$this->config_cache_directory.') = "'.$real_cache_path.'"', __FILE__, __LINE__); + $this->config_cache_directory = $real_cache_path; + } + } + if (!is_dir($this->config_cache_directory)) { + if (!$this->config_cache_disable_warning) { + $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); + } + $this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__); + $this->config_cache_directory = null; + } elseif (!is_writable($this->config_cache_directory)) { + $this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__); + } + return true; + } + + + function ResolveFilenameToAbsolute($filename) { + if (eregi('^(f|ht)tps?://', $filename)) { + + // URL + //$AbsoluteFilename = $filename; + return $filename; + + } elseif ($this->iswindows && ($filename{1} == ':')) { + + // absolute pathname (Windows) + $AbsoluteFilename = $filename; + + } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) { + + // absolute pathname (Windows) + $AbsoluteFilename = $filename; + + } elseif ($filename{0} == '/') { + + if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) { + + // absolute filename (*nix) + $AbsoluteFilename = $filename; + + } elseif ($filename{1} == '~') { + + // /~user/path + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) { + $AbsoluteFilename = $ApacheLookupURIarray['filename']; + } else { + $AbsoluteFilename = realpath($filename); + if (@is_readable($AbsoluteFilename)) { + $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__); + } else { + return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image'); + } + } + + } else { + + // relative filename (any OS) + if (ereg('^'.preg_quote($this->config_document_root), $filename)) { + $AbsoluteFilename = $filename; + $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); + } else { + $AbsoluteFilename = $this->config_document_root.$filename; + $this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); + } + + } + + } else { + + // relative to current directory (any OS) + $AbsoluteFilename = $this->config_document_root.dirname(@$_SERVER['PHP_SELF']).DIRECTORY_SEPARATOR.$filename; + //if (!file_exists($AbsoluteFilename) && file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) { + // $AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename)); + //} + + if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') { + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { + $AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename; + } else { + $AbsoluteFilename = realpath('.').DIRECTORY_SEPARATOR.$filename; + if (@is_readable($AbsoluteFilename)) { + $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__); + } else { + return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image'); + } + } + } + + } + if (is_link($AbsoluteFilename)) { + $this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__); + $AbsoluteFilename = readlink($AbsoluteFilename); + } + if (realpath($AbsoluteFilename)) { + $AbsoluteFilename = realpath($AbsoluteFilename); + } + if ($this->iswindows) { + $AbsoluteFilename = eregi_replace('^'.preg_quote(realpath($this->config_document_root)), realpath($this->config_document_root), $AbsoluteFilename); + $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename); + } + if (!$this->config_allow_src_above_docroot && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))), $AbsoluteFilename)) { + $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.realpath($this->config_document_root).'") to null', __FILE__, __LINE__); + return false; + } + if (!$this->config_allow_src_above_phpthumb && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))), $AbsoluteFilename)) { + $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__); + return false; + } + return $AbsoluteFilename; + } + + function ImageMagickWhichConvert() { + static $WhichConvert = null; + if (is_null($WhichConvert)) { + if ($this->iswindows) { + $WhichConvert = false; + } else { + $WhichConvert = trim(phpthumb_functions::SafeExec('which convert')); + } + } + return $WhichConvert; + } + + function ImageMagickCommandlineBase() { + static $commandline = null; + if (is_null($commandline)) { + $commandline = $this->config_imagemagick_path; + $commandline = (!is_null($commandline) ? $commandline : ''); + + $which_convert = $this->ImageMagickWhichConvert(); + $IMversion = $this->ImageMagickVersion(); + + if ($this->config_imagemagick_path && ($this->config_imagemagick_path != realpath($this->config_imagemagick_path))) { + if (@is_executable(realpath($this->config_imagemagick_path))) { + $this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to realpath($this->config_imagemagick_path) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); + $this->config_imagemagick_path = realpath($this->config_imagemagick_path); + } else { + $this->DebugMessage('Leaving $this->config_imagemagick_path as ('.$this->config_imagemagick_path.') because !is_execuatable(realpath($this->config_imagemagick_path)) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); + } + } + $this->DebugMessage(' file_exists('.$this->config_imagemagick_path.') = '.intval( @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__); + $this->DebugMessage('is_executable('.$this->config_imagemagick_path.') = '.intval(@is_executable($this->config_imagemagick_path)), __FILE__, __LINE__); + if (@file_exists($this->config_imagemagick_path)) { + + $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__); + if ($this->iswindows) { + $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.substr(dirname($this->config_imagemagick_path), 2).'" && '.basename($this->config_imagemagick_path); + } else { + $commandline = '"'.$this->config_imagemagick_path.'"'; + } + + } elseif ($which_convert && ($which_convert{0} == '/') && @file_exists($which_convert)) { + + // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't + // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin" + // so only do this if the value returned exists as a file + $this->DebugMessage('using ImageMagick path from `which convert` ('.$which_convert.')', __FILE__, __LINE__); + $commandline = 'convert'; + + } elseif ($IMversion) { + + $this->DebugMessage('setting ImageMagick path to $this->config_imagemagick_path ('.$this->config_imagemagick_path.') ['.$IMversion.']', __FILE__, __LINE__); + $commandline = $this->config_imagemagick_path; + + } else { + + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path ('.$this->config_imagemagick_path.'), and `which convert` returned ('.$which_convert.')', __FILE__, __LINE__); + $commandline = ''; + + } + } + return $commandline; + } + + function ImageMagickVersion() { + static $versionstring = null; + if (is_null($versionstring)) { + $commandline = $this->ImageMagickCommandlineBase(); + $commandline = (!is_null($commandline) ? $commandline : ''); + + if ($commandline) { + $commandline .= ' -version'; + $versionstring = phpthumb_functions::SafeExec($commandline); + if (eregi('^Version: (.*) http', $versionstring, $matches)) { + $versionstring = $matches[1]; + } else { + $versionstring = false; + $this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring.')', __FILE__, __LINE__); + } + } + } + return $versionstring; + } + + function ImageMagickThumbnailToGD() { + // http://www.imagemagick.org/script/command-line-options.php + + $this->useRawIMoutput = true; + if (phpthumb_functions::gd_version()) { + //$UnAllowedParameters = array('sx', 'sy', 'sw', 'sh', 'xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); + $UnAllowedParameters = array('xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); + foreach ($UnAllowedParameters as $dummy => $parameter) { + if ($this->$parameter) { + $this->DebugMessage('$this->useRawIMoutput=false because "'.$parameter.'" is set', __FILE__, __LINE__); + $this->useRawIMoutput = false; + break; + } + } + } + $outputFormat = $this->thumbnailFormat; + if (phpthumb_functions::gd_version()) { + if ($this->useRawIMoutput) { + switch ($this->thumbnailFormat) { + case 'gif': + $ImageCreateFunction = 'ImageCreateFromGIF'; + $this->is_alpha = true; + break; + case 'png': + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + break; + case 'jpg': + case 'jpeg': + $ImageCreateFunction = 'ImageCreateFromJPEG'; + break; + default: + $outputFormat = 'png'; + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + $this->useRawIMoutput = false; + break; + } + if (!function_exists(@$ImageCreateFunction)) { + // ImageMagickThumbnailToGD() depends on ImageCreateFromPNG/ImageCreateFromGIF + //$this->DebugMessage('ImageMagickThumbnailToGD() aborting because '.@$ImageCreateFunction.'() is not available', __FILE__, __LINE__); + $this->useRawIMoutput = true; + //return false; + } + } else { + $outputFormat = 'png'; + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + $this->useRawIMoutput = false; + } + } + + // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html + if (!$this->sourceFilename) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } + if (ini_get('safe_mode')) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } + + $commandline = $this->ImageMagickCommandlineBase(); + if ($commandline) { + if ($IMtempfilename = $this->phpThumb_tempnam()) { + + if (!eregi('('.implode('|', $this->AlphaCapableFormats).')', $outputFormat)) { + // not a transparency-capable format + $commandline .= ' -background "#'.($this->bg ? $this->bg : 'FFFFFF').'"'; + $commandline .= ' -flatten'; + } + $IMtempfilename = realpath($IMtempfilename); + if ($getimagesize = GetImageSize($this->sourceFilename)) { + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') returned [w='.$getimagesize[0].';h='.$getimagesize[1].';f='.$getimagesize[2].']', __FILE__, __LINE__); + $this->source_width = $getimagesize[0]; + $this->source_height = $getimagesize[1]; + $this->DebugMessage('source dimensions set to '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__); + $this->SetOrientationDependantWidthHeight(); + + $commandline .= ' -coalesce'; // may be needed for animated GIFs + if ($this->source_width || $this->source_height) { + if ($this->zc) { + + $side = min($this->source_width, $this->source_height, max($this->w, $this->wp, $this->wl, $this->ws, $this->h, $this->hp, $this->hl, $this->hs)); + if ($getimagesize[0] > $getimagesize[1]) { + $commandline .= ' -thumbnail x'.$side; + } else { + $commandline .= ' -thumbnail '.$side.'x'; + } + $commandline .= ' -gravity center'; + $commandline .= ' -crop '.$side.'x'.$side.'+0+0'; + $commandline .= ' +repage'; + + } elseif ($this->sw || $this->sh || $this->sx || $this->sy) { + + $commandline .= ' -crop '.($this->sw ? $this->sw : $this->source_width).'x'.($this->sh ? $this->sh : $this->source_height).'+'.$this->sx.'+'.$this->sy; + // this is broken for aoe=1, but unsure how to fix. Send advice to info@silisoftware.com + + } else { + + $this->w = (($this->aoe && $this->w) ? max($this->w, $getimagesize[0]) : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : '')); + $this->h = (($this->aoe && $this->h) ? max($this->h, $getimagesize[1]) : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : '')); + if ($this->w || $this->h) { + $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; + if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { + $commandline .= '!'; + } + } + } + } + + } else { + + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') failed', __FILE__, __LINE__); + $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; + if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { + $commandline .= '!'; + } + + } + foreach ($this->fltr as $filterkey => $filtercommand) { + @list($command, $parameter) = explode('|', $filtercommand, 2); + switch ($command) { + case 'brit': + $commandline .= ' -modulate '.(100 + $parameter).',100,100'; + unset($this->fltr[$filterkey]); + break; + + case 'cont': + $contDiv10 = round($parameter / 10); + if ($contDiv10 > 0) { + for ($i = 0; $i < $contDiv10; $i++) { + $commandline .= ' -contrast'; // increase contrast by 10% + } + } elseif ($contDiv10 < 0) { + for ($i = $contDiv10; $i < 0; $i++) { + $commandline .= ' +contrast'; // decrease contrast by 10% + } + } else { + // do nothing + } + unset($this->fltr[$filterkey]); + break; + + case 'ds': + if ($parameter == 100) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + } else { + $commandline .= ' -modulate 100,'.(100 - $parameter).',100'; + } + unset($this->fltr[$filterkey]); + break; + + case 'sat': + if ($parameter == -100) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + } else { + $commandline .= ' -modulate 100,'.(100 + $parameter).',100'; + } + unset($this->fltr[$filterkey]); + break; + + case 'gray': + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + //$commandline .= ' -colorspace GRAY'; + unset($this->fltr[$filterkey]); + break; + + case 'clr': + @list($amount, $color) = explode('|', $parameter); + $commandline .= ' -fill #'.$color.' -colorize '.$amount; + break; + + case 'sep': + @list($amount, $color) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + if (!$color) { + $commandline .= ' -sepia-tone '.$amount.'%'; + unset($this->fltr[$filterkey]); + } + break; + + case 'gam': + $commandline .= ' -gamma '.$parameter; + unset($this->fltr[$filterkey]); + break; + + case 'neg': + $commandline .= ' -negate'; + unset($this->fltr[$filterkey]); + break; + + case 'th': + $commandline .= ' -threshold '.round($parameter / 2.55).'% -dither -monochrome'; + unset($this->fltr[$filterkey]); + break; + + case 'rcd': + @list($colors, $dither) = explode('|', $parameter); + $colors = ($colors ? (int) $colors : 256); + $dither = ((strlen($dither) > 0) ? (bool) $dither : true); + $commandline .= ' -colors '.max($colors, 8); // ImageMagick will otherwise fail with "cannot quantize to fewer than 8 colors" + $commandline .= ($dither ? ' -dither' : ' +dither'); + unset($this->fltr[$filterkey]); + break; + + case 'flip': + if (strpos(strtolower($parameter), 'x') !== false) { + $commandline .= ' -flop'; + } + if (strpos(strtolower($parameter), 'y') !== false) { + $commandline .= ' -flip'; + } + unset($this->fltr[$filterkey]); + break; + + case 'edge': + $parameter = ($parameter ? $parameter : 2); + $commandline .= ' -edge '.($parameter ? $parameter : 1); + unset($this->fltr[$filterkey]); + break; + + case 'emb': + $parameter = ($parameter ? $parameter : 2); + $commandline .= ' -emboss '.$parameter; + if ($parameter < 2) { + $commandline .= ' -negate'; // ImageMagick negates the image for some reason with '-emboss 1'; + } + unset($this->fltr[$filterkey]); + break; + + case 'lvl': + @list($band, $min, $max) = explode('|', $parameter); + $band = ($band ? $band : '*'); + $min = ((strlen($min) > 0) ? $min : '-1'); + $max = ((strlen($max) > 0) ? $max : '-1'); + if ($band == '*') { + if (($min == -1) && ($max == -1)) { + $commandline .= ' -normalize'; + unset($this->fltr[$filterkey]); + } elseif (($min == -1) || ($max == -1)) { + // + } else { + $commandline .= ' -level '.$min.'%,'.$max.'%'; + unset($this->fltr[$filterkey]); + } + } + break; + + case 'blur': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + $commandline .= ' -blur '.$radius; + unset($this->fltr[$filterkey]); + break; + + case 'gblr': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + $commandline .= ' -gaussian '.$radius; + unset($this->fltr[$filterkey]); + break; + + case 'usm': + @list($amount, $radius, $threshold) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + $radius = ($radius ? $radius : 0.5); + $threshold = (strlen($threshold) ? $threshold : 3); + $commandline .= ' -unsharp '.number_format(($radius * 2) - 1, 2).'x1+'.number_format($amount / 100, 2).'+'.number_format($threshold / 100, 2); + unset($this->fltr[$filterkey]); + break; + + case 'sblr': + break; + + case 'mean': + break; + + case 'smth': + break; + + case 'bvl': + break; + + case 'wmi': + break; + + case 'wmt': + break; + + case 'over': + break; + + case 'wb': + break; + + case 'hist': + break; + + case 'fram': + break; + + case 'drop': + break; + + case 'mask': + break; + + case 'elip': + break; + + case 'ric': + break; + + case 'bord': + break; + + } + if (!isset($this->fltr[$filterkey])) { + $this->DebugMessage('Processed $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); + } else { + $this->DebugMessage('Skipping $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); + } + } + $this->DebugMessage('Remaining $this->fltr after ImageMagick: ('.$this->phpThumbDebugVarDump($this->fltr).')', __FILE__, __LINE__); + + if (eregi('jpe?g', $outputFormat) && $this->q) { + $commandline .= ' -quality '.$this->thumbnailQuality; + if ($this->config_output_interlace) { + // causes weird things with animated GIF... leave for JPEG only + $commandline .= ' -interlace line '; // Use Line or Plane to create an interlaced PNG or GIF or progressive JPEG image + } + } + $commandline .= ' "'.str_replace('/', DIRECTORY_SEPARATOR, $this->sourceFilename).(($outputFormat == 'gif') ? '' : '[0]').'"'; // [0] means first frame of (GIF) animation, can be ignored + $commandline .= ' '.$outputFormat.':"'.$IMtempfilename.'"'; + $commandline .= ' 2>&1'; + $this->DebugMessage('ImageMagick called as ('.$commandline.')', __FILE__, __LINE__); + $IMresult = phpthumb_functions::SafeExec($commandline); +//var_Dump($commandline); +//var_dump($ImageCreateFunction); +//exit; + clearstatcache(); + if (!file_exists($IMtempfilename) || !filesize($IMtempfilename)) { + + $this->DebugMessage('ImageMagick failed with message ('.$IMresult.')', __FILE__, __LINE__); + + } else { + + $this->IMresizedData = file_get_contents($IMtempfilename); + if (function_exists(@$ImageCreateFunction) && ($this->gdimg_source = @$ImageCreateFunction($IMtempfilename))) { +//header('Content-Type: image/png'); +//phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_source, true); +//ImagePNG($this->gdimg_source); +//exit; + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $this->DebugMessage('ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() succeeded, $this->gdimg_source is now ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); + $this->DebugMessage('ImageMagickThumbnailToGD() returning $IMresizedData ('.strlen($this->IMresizedData).' bytes)', __FILE__, __LINE__); + } else { + $this->useRawIMoutput = true; + $this->DebugMessage('$this->useRawIMoutput set to TRUE because '.@$ImageCreateFunction.'('.$IMtempfilename.') failed', __FILE__, __LINE__); + } + @unlink($IMtempfilename); + return true; + + } + unlink($IMtempfilename); + + } else { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpThumb_tempnam() failed', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__); + } + $this->useRawIMoutput = false; + return false; + } + + + function Rotate() { + if ($this->ra || $this->ar) { + if (!function_exists('ImageRotate')) { + $this->DebugMessage('!function_exists(ImageRotate)', __FILE__, __LINE__); + return false; + } + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); + return false; + } + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + + $rotate_angle = 0; + if ($this->ra) { + + $rotate_angle = floatval($this->ra); + + } else { + + if ($this->ar == 'x') { + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=')) { + if ($this->sourceFilename) { + if (function_exists('exif_read_data')) { + if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) { + // http://sylvana.net/jpegcrop/exif_orientation.html + switch (@$exif_data['Orientation']) { + case 1: + $rotate_angle = 0; + break; + case 3: + $rotate_angle = 180; + break; + case 6: + $rotate_angle = 270; + break; + case 8: + $rotate_angle = 90; + break; + + default: + $this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "'.@$exif_data['Orientation'].'"', __FILE__, __LINE__); + return false; + break; + } + $this->DebugMessage('EXIF auto-rotate set to '.$rotate_angle.' degrees ($exif_data[Orientation] = "'.@$exif_data['Orientation'].'")', __FILE__, __LINE__); + } else { + $this->DebugMessage('failed: exif_read_data('.$this->sourceFilename.')', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 ('.phpversion().')', __FILE__, __LINE__); + return false; + } + } elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) { + $rotate_angle = 270; + } elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) { + $rotate_angle = 90; + } elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) { + $rotate_angle = 90; + } elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) { + $rotate_angle = 270; + } + + } + while ($rotate_angle < 0) { + $rotate_angle += 360; + } + $rotate_angle = $rotate_angle % 360; + if ($rotate_angle != 0) { + + if ($rotate_angle % 90) { + $this->is_alpha = true; + } + + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_source, $this->config_background_hexcolor); + + //if ((phpthumb_functions::gd_version() >= 2) && in_array($this->thumbnailFormat, $this->AlphaCapableFormats) && !$this->bg && ($rotate_angle % 90)) { + if ((phpthumb_functions::gd_version() >= 2) && !$this->bg && ($rotate_angle % 90)) { + + $this->DebugMessage('Using alpha rotate', __FILE__, __LINE__); + if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_source), ImageSY($this->gdimg_source))) { + + for ($i = 0; $i <= 255; $i++) { + $color_mask[$i] = ImageColorAllocate($gdimg_rotate_mask, $i, $i, $i); + } + ImageFilledRectangle($gdimg_rotate_mask, 0, 0, ImageSX($gdimg_rotate_mask), ImageSY($gdimg_rotate_mask), $color_mask[255]); + $imageX = ImageSX($this->gdimg_source); + $imageY = ImageSY($this->gdimg_source); + for ($x = 0; $x < $imageX; $x++) { + for ($y = 0; $y < $imageY; $y++) { + $pixelcolor = phpthumb_functions::GetPixelColor($this->gdimg_source, $x, $y); + ImageSetPixel($gdimg_rotate_mask, $x, $y, $color_mask[255 - round($pixelcolor['alpha'] * 255 / 127)]); + } + } + $gdimg_rotate_mask = ImageRotate($gdimg_rotate_mask, $rotate_angle, $color_mask[0]); + $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color); + + ImageAlphaBlending($this->gdimg_source, false); + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_source, true); + $this->is_alpha = true; + $phpThumbFilters = new phpthumb_filters(); + $phpThumbFilters->phpThumbObject = $this; + $phpThumbFilters->ApplyMask($gdimg_rotate_mask, $this->gdimg_source); + + ImageDestroy($gdimg_rotate_mask); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + + } else { + + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + } elseif ($this->bg) { + $this->DebugMessage('Using non-alpha rotate because $this->bg is "'.$this->bg.'"', __FILE__, __LINE__); + } elseif ($this->bg) { + $this->DebugMessage('Using non-alpha rotate because ($rotate_angle % 90) = "'.($rotate_angle % 90).'"', __FILE__, __LINE__); + } else { + $this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); + } + + if (ImageColorTransparent($this->gdimg_source) >= 0) { + // ImageRotate() forgets all about an image's transparency and sets the transparent color to black + // To compensate, flood-fill the transparent color of the source image with the specified background color first + // then rotate and the colors should match + + if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($this->gdimg_source)) { + // convert paletted image to true-color before rotating to prevent nasty aliasing artifacts + + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $gdimg_newsrc = phpthumb_functions::ImageCreateFunction($this->source_width, $this->source_height); + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor); + ImageFilledRectangle($gdimg_newsrc, 0, 0, $this->source_width, $this->source_height, phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor)); + ImageCopy($gdimg_newsrc, $this->gdimg_source, 0, 0, 0, 0, $this->source_width, $this->source_height); + ImageDestroy($this->gdimg_source); + unset($this->gdimg_source); + $this->gdimg_source = $gdimg_newsrc; + unset($gdimg_newsrc); + + } else { + + ImageColorSet( + $this->gdimg_source, + ImageColorTransparent($this->gdimg_source), + hexdec(substr($this->config_background_hexcolor, 0, 2)), + hexdec(substr($this->config_background_hexcolor, 2, 2)), + hexdec(substr($this->config_background_hexcolor, 4, 2))); + + ImageColorTransparent($this->gdimg_source, -1); + + } + } + + $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + } + } + } + return true; + } + + + function FixedAspectRatio() { + // optional fixed-dimension images (regardless of aspect ratio) + + if (!$this->far) { + // do nothing + return true; + } + + if (!$this->w || !$this->h) { + return false; + } + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->is_alpha = true; + if ($this->thumbnail_image_width >= $this->thumbnail_width) { + + if ($this->w) { + $aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width; + $this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio); + if (!$this->h) { + $this->thumbnail_height = $this->thumbnail_image_height; + } + } elseif ($this->thumbnail_image_height < $this->thumbnail_height) { + $this->thumbnail_image_height = $this->thumbnail_height; + $this->thumbnail_image_width = round($this->thumbnail_image_height / $aspectratio); + } + + } else { + + if ($this->h) { + $aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height; + $this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio); + } elseif ($this->thumbnail_image_width < $this->thumbnail_width) { + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = round($this->thumbnail_image_width / $aspectratio); + } + + } + return true; + } + + + function AntiOffsiteLinking() { + // Optional anti-offsite hijacking of the thumbnail script + $allow = true; + if ($allow && $this->config_nooffsitelink_enabled && (@$_SERVER['HTTP_REFERER'] || $this->config_nooffsitelink_require_refer)) { + $this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "'.@$_SERVER['HTTP_REFERER'].'"', __FILE__, __LINE__); + $parsed_url = parse_url(@$_SERVER['HTTP_REFERER']); + if (!in_array(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) { + $allow = false; + $erase = $this->config_nooffsitelink_erase_image; + $message = $this->config_nooffsitelink_text_message; + $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + } else { + $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + } + } + + if ($allow && $this->config_nohotlink_enabled && eregi('^(f|ht)tps?://', $this->src)) { + $parsed_url = parse_url($this->src); + if (!in_array(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) { + // This domain is not allowed + $allow = false; + $erase = $this->config_nohotlink_erase_image; + $message = $this->config_nohotlink_text_message; + $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is NOT in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); + } else { + $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); + } + } + + if ($allow) { + $this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__); + return true; + } + + if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_error_bgcolor.'" for $this->config_error_bgcolor'); + } + if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_error_textcolor.'" for $this->config_error_textcolor'); + } + if ($erase) { + + return $this->ErrorImage($message, $this->thumbnail_width, $this->thumbnail_height, $this->config_error_bgcolor, $this->config_error_textcolor, $this->config_error_fontsize); + + } else { + + $nohotlink_text_array = explode("\n", wordwrap($message, floor($this->thumbnail_width / ImageFontWidth($this->config_error_fontsize)), "\n")); + $nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor); + + $topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * ImageFontHeight($this->config_error_fontsize))) / 2); + + $rowcounter = 0; + $this->DebugMessage('AntiOffsiteLinking() writing '.count($nohotlink_text_array).' lines of text "'.$message.'" (in #'.$this->config_error_textcolor.') on top of image', __FILE__, __LINE__); + foreach ($nohotlink_text_array as $dummy => $textline) { + $leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * ImageFontWidth($this->config_error_fontsize))) / 2)); + ImageString($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * ImageFontHeight($this->config_error_fontsize)), $textline, $nohotlink_text_color); + } + + } + return true; + } + + + function AlphaChannelFlatten() { + if (!$this->is_alpha) { + // image doesn't have alpha transparency, no need to flatten + $this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__); + return false; + } + switch ($this->thumbnailFormat) { + case 'png': + case 'ico': + // image has alpha transparency, but output as PNG or ICO which can handle it + $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'")', __FILE__, __LINE__); + return false; + break; + + case 'gif': + // image has alpha transparency, but output as GIF which can handle only single-color transparency + $CurrentImageColorTransparent = ImageColorTransparent($this->gdimg_output); + if ($CurrentImageColorTransparent == -1) { + // no transparent color defined + + if (phpthumb_functions::gd_version() < 2.0) { + $this->DebugMessage('AlphaChannelFlatten() failed because GD version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + + if ($img_alpha_mixdown_dither = @ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { + + for ($i = 0; $i <= 255; $i++) { + $dither_color[$i] = ImageColorAllocate($img_alpha_mixdown_dither, $i, $i, $i); + } + + // scan through current truecolor image copy alpha channel to temp image as grayscale + for ($x = 0; $x < $this->thumbnail_width; $x++) { + for ($y = 0; $y < $this->thumbnail_height; $y++) { + $PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y); + ImageSetPixel($img_alpha_mixdown_dither, $x, $y, $dither_color[($PixelColor['alpha'] * 2)]); + } + } + + // dither alpha channel grayscale version down to 2 colors + ImageTrueColorToPalette($img_alpha_mixdown_dither, true, 2); + + // reduce color palette to 256-1 colors (leave one palette position for transparent color) + ImageTrueColorToPalette($this->gdimg_output, true, 255); + + // allocate a new color for transparent color index + $TransparentColor = ImageColorAllocate($this->gdimg_output, 1, 254, 253); + ImageColorTransparent($this->gdimg_output, $TransparentColor); + + // scan through alpha channel image and note pixels with >50% transparency + $TransparentPixels = array(); + for ($x = 0; $x < $this->thumbnail_width; $x++) { + for ($y = 0; $y < $this->thumbnail_height; $y++) { + $AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y); + if ($AlphaChannelPixel['red'] > 127) { + ImageSetPixel($this->gdimg_output, $x, $y, $TransparentColor); + } + } + } + ImageDestroy($img_alpha_mixdown_dither); + + $this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__); + return true; + + } else { + $this->DebugMessage('AlphaChannelFlatten() failed ImageCreate('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); + return false; + } + + } else { + // a single transparent color already defined, leave as-is + $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'") and ImageColorTransparent returned "'.$CurrentImageColorTransparent.'"', __FILE__, __LINE__); + return true; + } + break; + } + $this->DebugMessage('continuing AlphaChannelFlatten() for output format "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); + + // image has alpha transparency, and is being output in a format that doesn't support it -- flatten + if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) { + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); + ImageFilledRectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); + ImageCopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); + + ImageAlphaBlending($this->gdimg_output, true); + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_output, false); + ImageColorTransparent($this->gdimg_output, -1); + ImageCopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); + + ImageDestroy($gdimg_flatten_temp); + return true; + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + return false; + } + + + function ApplyFilters() { + if ($this->fltr && is_array($this->fltr)) { + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); + return false; + } + $phpthumbFilters = new phpthumb_filters(); + $phpthumbFilters->phpThumbObject = $this; + foreach ($this->fltr as $dummy => $filtercommand) { + @list($command, $parameter) = explode('|', $filtercommand, 2); + $this->DebugMessage('Attempting to process filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__); + switch ($command) { + case 'brit': + $phpthumbFilters->Brightness($this->gdimg_output, $parameter); + break; + + case 'cont': + $phpthumbFilters->Contrast($this->gdimg_output, $parameter); + break; + + case 'ds': + $phpthumbFilters->Desaturate($this->gdimg_output, $parameter, ''); + break; + + case 'sat': + $phpthumbFilters->Saturation($this->gdimg_output, $parameter, ''); + break; + + case 'gray': + $phpthumbFilters->Grayscale($this->gdimg_output); + break; + + case 'clr': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Colorize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($amount, $color) = explode('|', $parameter); + $phpthumbFilters->Colorize($this->gdimg_output, $amount, $color); + break; + + case 'sep': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Sepia() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($amount, $color) = explode('|', $parameter); + $phpthumbFilters->Sepia($this->gdimg_output, $amount, $color); + break; + + case 'gam': + $phpthumbFilters->Gamma($this->gdimg_output, $parameter); + break; + + case 'neg': + $phpthumbFilters->Negative($this->gdimg_output); + break; + + case 'th': + $phpthumbFilters->Threshold($this->gdimg_output, $parameter); + break; + + case 'rcd': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping ReduceColorDepth() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($colors, $dither) = explode('|', $parameter); + $colors = ($colors ? (int) $colors : 256); + $dither = ((strlen($dither) > 0) ? (bool) $dither : true); + $phpthumbFilters->ReduceColorDepth($this->gdimg_output, $colors, $dither); + break; + + case 'flip': + $phpthumbFilters->Flip($this->gdimg_output, (strpos(strtolower($parameter), 'x') !== false), (strpos(strtolower($parameter), 'y') !== false)); + break; + + case 'edge': + $phpthumbFilters->EdgeDetect($this->gdimg_output); + break; + + case 'emb': + $phpthumbFilters->Emboss($this->gdimg_output); + break; + + case 'bvl': + @list($width, $color1, $color2) = explode('|', $parameter); + $phpthumbFilters->Bevel($this->gdimg_output, $width, $color1, $color2); + break; + + case 'lvl': + @list($band, $min, $max) = explode('|', $parameter); + $band = ($band ? $band : '*'); + $min = ((strlen($min) > 0) ? $min : '-1'); + $max = ((strlen($max) > 0) ? $max : '-1'); + $phpthumbFilters->HistogramStretch($this->gdimg_output, $band, $min, $max); + break; + + case 'wb': + $phpthumbFilters->WhiteBalance($this->gdimg_output, $parameter); + break; + + case 'hist': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping HistogramOverlay() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($bands, $colors, $width, $height, $alignment, $opacity, $margin) = explode('|', $parameter); + $bands = ($bands ? $bands : '*'); + $colors = ($colors ? $colors : ''); + $width = ($width ? $width : 0.25); + $height = ($height ? $height : 0.25); + $alignment = ($alignment ? $alignment : 'BR'); + $opacity = ($opacity ? $opacity : 50); + $margin = ($margin ? $margin : 5); + $phpthumbFilters->HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin); + break; + + case 'fram': + @list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter); + $phpthumbFilters->Frame($this->gdimg_output, $frame_width, $edge_width, $color_frame, $color1, $color2); + break; + + case 'drop': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping DropShadow() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $this->is_alpha = true; + @list($distance, $width, $color, $angle, $fade) = explode('|', $parameter); + $phpthumbFilters->DropShadow($this->gdimg_output, $distance, $width, $color, $angle, $fade); + break; + + case 'mask': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Mask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $mask_filename = $this->ResolveFilenameToAbsolute($parameter); + if (@is_readable($mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) { + $MaskImageData = fread($fp_mask, filesize($mask_filename)); + fclose($fp_mask); + if ($gdimg_mask = $this->ImageCreateFromStringReplacement($MaskImageData)) { + $this->is_alpha = true; + $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output); + ImageDestroy($gdimg_mask); + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$mask_filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('Cannot open mask file "'.$mask_filename.'"', __FILE__, __LINE__); + } + break; + + case 'elip': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Elipse() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $this->is_alpha = true; + $phpthumbFilters->Elipse($this->gdimg_output); + break; + + case 'ric': + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping RoundedImageCorners() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + @list($radius_x, $radius_y) = explode('|', $parameter); + if (($radius_x < 1) || ($radius_y < 1)) { + $this->DebugMessage('Skipping RoundedImageCorners('.$radius_x.', '.$radius_y.') because x/y radius is less than 1', __FILE__, __LINE__); + break; + } + $this->is_alpha = true; + $phpthumbFilters->RoundedImageCorners($this->gdimg_output, $radius_x, $radius_y); + break; + + case 'bord': + @list($border_width, $radius_x, $radius_y, $hexcolor_border) = explode('|', $parameter); + $this->is_alpha = true; + $phpthumbFilters->ImageBorder($this->gdimg_output, $border_width, $radius_x, $radius_y, $hexcolor_border); + break; + + case 'over': + @list($filename, $underlay, $margin, $opacity) = explode('|', $parameter); + $underlay = (bool) ($underlay ? $underlay : false); + $margin = ((strlen($margin) > 0) ? $margin : ($underlay ? 0.1 : 0.0)); + $opacity = ((strlen($opacity) > 0) ? $opacity : 100); + if (($margin > 0) && ($margin < 1)) { + $margin = min(0.499, $margin); + } elseif (($margin > -1) && ($margin < 0)) { + $margin = max(-0.499, $margin); + } + + $filename = $this->ResolveFilenameToAbsolute($filename); + if (@is_readable($filename) && ($fp_watermark = @fopen($filename, 'rb'))) { + $WatermarkImageData = fread($fp_watermark, filesize($filename)); + fclose($fp_watermark); + if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) { + if ($margin < 1) { + $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * (ImageSX($this->gdimg_output) * $margin))); + $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * (ImageSY($this->gdimg_output) * $margin))); + } else { + $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * $margin)); + $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * $margin)); + } + + if ($underlay) { + + if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { + ImageAlphaBlending($img_watermark_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark_resized, true); + $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); + if ($img_source_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { + ImageAlphaBlending($img_source_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_source_resized, true); + $this->ImageResizeFunction($img_source_resized, $this->gdimg_output, 0, 0, 0, 0, ImageSX($img_source_resized), ImageSY($img_source_resized), ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + $phpthumbFilters->WatermarkOverlay($img_watermark_resized, $img_source_resized, 'C', $opacity, $margin); + ImageCopy($this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); + } + ImageDestroy($img_watermark_resized); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); + } + + } else { // overlay + + if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { + ImageAlphaBlending($img_watermark_resized, false); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark_resized, true); + $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark_resized, 'C', $opacity, $margin); + ImageDestroy($img_watermark_resized); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); + } + + } + ImageDestroy($img_watermark); + + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('Cannot open overlay file "'.$filename.'"', __FILE__, __LINE__); + } + break; + + case 'wmi': + @list($filename, $alignment, $opacity, $margin) = explode('|', $parameter); + $alignment = ($alignment ? $alignment : 'BR'); + $opacity = (strlen($opacity) ? $opacity : 50); + $margin = (strlen($margin) ? $margin : 5); + + $filename = $this->ResolveFilenameToAbsolute($filename); + if (@is_readable($filename)) { + if ($img_watermark = $this->ImageCreateFromFilename($filename, $rawImageData)) { + // great + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark, $alignment, $opacity, $margin); + ImageDestroy($img_watermark); + } else { + $this->DebugMessage('ImageCreateFromFilename() failed for "'.$filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('!is_readable('.$filename.')', __FILE__, __LINE__); + } + break; + + case 'wmt': + @list($text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend) = explode('|', $parameter); + $text = ($text ? $text : ''); + $size = ($size ? $size : 3); + $alignment = ($alignment ? $alignment : 'BR'); + $hex_color = ($hex_color ? $hex_color : '000000'); + $ttffont = ($ttffont ? $ttffont : ''); + $opacity = (strlen($opacity) ? $opacity : 50); + $margin = (strlen($margin) ? $margin : 5); + $angle = (strlen($angle) ? $angle : 0); + $bg_color = ($bg_color ? $bg_color : false); + $bg_opacity = ($bg_opacity ? $bg_opacity : 0); + $fillextend = ($fillextend ? $fillextend : ''); + + if (basename($ttffont) == $ttffont) { + $ttffont = realpath($this->config_ttf_directory.DIRECTORY_SEPARATOR.$ttffont); + } else { + $ttffont = $this->ResolveFilenameToAbsolute($ttffont); + } + $phpthumbFilters->WatermarkText($this->gdimg_output, $text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend); + break; + + case 'blur': + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Blur() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $phpthumbFilters->Blur($this->gdimg_output, $radius); + break; + + case 'gblr': + $phpthumbFilters->BlurGaussian($this->gdimg_output); + break; + + case 'sblr': + $phpthumbFilters->BlurSelective($this->gdimg_output); + break; + + case 'mean': + $phpthumbFilters->MeanRemoval($this->gdimg_output); + break; + + case 'smth': + $phpthumbFilters->Smooth($this->gdimg_output, $parameter); + break; + + case 'usm': + @list($amount, $radius, $threshold) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + $radius = ($radius ? $radius : 0.5); + $threshold = (strlen($threshold) ? $threshold : 3); + if (phpthumb_functions::gd_version() >= 2.0) { + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.unsharp.php')) { + $include_error = ob_get_contents(); + if ($include_error) { + $this->DebugMessage('include_once("'.dirname(__FILE__).'/phpthumb.unsharp.php") generated message: "'.$include_error.'"', __FILE__, __LINE__); + } + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.unsharp.php" which is required for unsharp masking', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ob_end_clean(); + phpUnsharpMask::applyUnsharpMask($this->gdimg_output, $amount, $radius, $threshold); + } else { + $this->DebugMessage('Skipping unsharp mask because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + break; + } + } + } + return true; + } + + + function MaxFileSize() { + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping MaxFileSize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + if ($this->maxb > 0) { + switch ($this->thumbnailFormat) { + case 'png': + case 'gif': + $imgRenderFunction = 'image'.$this->thumbnailFormat; + + ob_start(); + $imgRenderFunction($this->gdimg_output); + $imgdata = ob_get_contents(); + ob_end_clean(); + + if (strlen($imgdata) > $this->maxb) { + for ($i = 8; $i >= 1; $i--) { + $tempIMG = ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + ImageCopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + ImageTrueColorToPalette($tempIMG, true, pow(2, $i)); + ob_start(); + $imgRenderFunction($tempIMG); + $imgdata = ob_get_contents(); + ob_end_clean(); + + if (strlen($imgdata) <= $this->maxb) { + ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); + break; + } + } + } + if (strlen($imgdata) > $this->maxb) { + ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); + return false; + } + break; + + case 'jpeg': + ob_start(); + ImageJPEG($this->gdimg_output); + $imgdata = ob_get_contents(); + ob_end_clean(); + + $OriginalJPEGquality = $this->thumbnailQuality; + if (strlen($imgdata) > $this->maxb) { + for ($i = 3; $i < 20; $i++) { + $q = round(100 * (1 - log10($i / 2))); + ob_start(); + ImageJPEG($this->gdimg_output, '', $q); + $imgdata = ob_get_contents(); + ob_end_clean(); + + $this->thumbnailQuality = $q; + if (strlen($imgdata) <= $this->maxb) { + break; + } + } + } + if (strlen($imgdata) > $this->maxb) { + return false; + } + break; + + default: + return false; + break; + } + } + return true; + } + + + function CalculateThumbnailDimensions() { + $this->thumbnailCropX = ($this->sx ? (($this->sx >= 1) ? $this->sx : round($this->sx * $this->source_width)) : 0); + $this->thumbnailCropY = ($this->sy ? (($this->sy >= 1) ? $this->sy : round($this->sy * $this->source_height)) : 0); + $this->thumbnailCropW = ($this->sw ? (($this->sw >= 1) ? $this->sw : round($this->sw * $this->source_width)) : $this->source_width); + $this->thumbnailCropH = ($this->sh ? (($this->sh >= 1) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height); + + // limit source area to original image area + $this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width - $this->thumbnailCropX)); + $this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY)); + + $this->DebugMessage('CalculateThumbnailDimensions() [x,y,w,h] initially set to ['.$this->thumbnailCropX.','.$this->thumbnailCropY.','.$this->thumbnailCropW.','.$this->thumbnailCropH.']', __FILE__, __LINE__); + + + if ($this->zc && $this->w && $this->h) { + // Zoom Crop + // retain proportional resizing we did above, but crop off larger dimension so smaller + // dimension fully fits available space + + $scaling_X = $this->source_width / $this->w; + $scaling_Y = $this->source_height / $this->h; + if ($scaling_X > $scaling_Y) { + // some of the width will need to be cropped + $allowable_width = $this->source_width / $scaling_X * $scaling_Y; + $this->thumbnailCropW = round($allowable_width); + $this->thumbnailCropX = round(($this->source_width - $allowable_width) / 2); + + } elseif ($scaling_Y > $scaling_X) { + // some of the height will need to be cropped + $allowable_height = $this->source_height / $scaling_Y * $scaling_X; + $this->thumbnailCropH = round($allowable_height); + $this->thumbnailCropY = round(($this->source_height - $allowable_height) / 2); + + } else { + // image fits perfectly, no cropping needed + } + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = $this->thumbnail_height; + + } elseif ($this->iar && $this->w && $this->h) { + + // Ignore Aspect Ratio + // stretch image to fit exactly 'w' x 'h' + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = $this->thumbnail_height; + + } else { + + $original_aspect_ratio = $this->thumbnailCropW / $this->thumbnailCropH; + if ($this->aoe) { + $maxwidth = max($this->w, $this->thumbnailCropW); + $maxheight = max($this->h, $this->thumbnailCropH); + $maxwidth = max($maxwidth, $maxheight * $original_aspect_ratio); + $maxheight = max($maxheight, $maxwidth / $original_aspect_ratio); + } else { + $maxwidth = phpthumb_functions::nonempty_min($this->w, $this->thumbnailCropW, $this->config_output_maxwidth); + $maxheight = phpthumb_functions::nonempty_min($this->h, $this->thumbnailCropH, $this->config_output_maxheight); + $maxwidth = min($maxwidth, $maxheight * $original_aspect_ratio); + $maxheight = min($maxheight, $maxwidth / $original_aspect_ratio); + } + + $this->thumbnail_image_width = $maxwidth; + $this->thumbnail_image_height = $maxheight; + $this->thumbnail_width = $maxwidth; + $this->thumbnail_height = $maxheight; + + $this->FixedAspectRatio(); + } + + $this->thumbnail_width = max(1, floor($this->thumbnail_width)); + $this->thumbnail_height = max(1, floor($this->thumbnail_height)); + return true; + } + + + function CreateGDoutput() { + + $this->CalculateThumbnailDimensions(); + + // Create the GD image (either true-color or 256-color, depending on GD version) + $this->gdimg_output = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height); + + // Images that have transparency must have the background filled with the configured 'bg' color + // otherwise the transparent color will appear as black + phpthumb_functions::gd_ImageSaveAlpha($this->gdimg_output, true); + if ($this->is_alpha && phpthumb_functions::gd_version() >= 2) { + + ImageAlphaBlending($this->gdimg_output, false); + $output_full_alpha = phpthumb_functions::ImageColorAllocateAlphaSafe($this->gdimg_output, 255, 255, 255, 127); + ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha); + + } else { + + $current_transparent_color = ImageColorTransparent($this->gdimg_source); + if ($this->bg || (@$current_transparent_color >= 0)) { + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); + ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); + + } + + } + return true; + } + + function SetOrientationDependantWidthHeight() { + $this->DebugMessage('SetOrientationDependantWidthHeight() starting with "'.$this->source_width.'"x"'.$this->source_height.'"', __FILE__, __LINE__); + if ($this->source_height > $this->source_width) { + // portrait + $this->w = phpthumb_functions::OneOfThese($this->wp, $this->w, $this->ws, $this->wl); + $this->h = phpthumb_functions::OneOfThese($this->hp, $this->h, $this->hs, $this->hl); + } elseif ($this->source_height < $this->source_width) { + // landscape + $this->w = phpthumb_functions::OneOfThese($this->wl, $this->w, $this->ws, $this->wp); + $this->h = phpthumb_functions::OneOfThese($this->hl, $this->h, $this->hs, $this->hp); + } else { + // square + $this->w = phpthumb_functions::OneOfThese($this->ws, $this->w, $this->wl, $this->wp); + $this->h = phpthumb_functions::OneOfThese($this->hs, $this->h, $this->hl, $this->hp); + } + //$this->w = round($this->w ? $this->w : (($this->h && $this->source_height) ? $this->h * $this->source_width / $this->source_height : $this->w)); + //$this->h = round($this->h ? $this->h : (($this->w && $this->source_width) ? $this->w * $this->source_height / $this->source_width : $this->h)); + $this->DebugMessage('SetOrientationDependantWidthHeight() setting w="'.intval($this->w).'", h="'.intval($this->h).'"', __FILE__, __LINE__); + return true; + } + + function ExtractEXIFgetImageSize() { + $this->DebugMessage('starting ExtractEXIFgetImageSize()', __FILE__, __LINE__); + + if (is_resource($this->gdimg_source)) { + + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + $this->SetOrientationDependantWidthHeight(); + + } elseif ($this->rawImageData && !$this->sourceFilename) { + + $this->DebugMessage('bypassing EXIF and GetImageSize sections because $this->rawImageData is set and $this->sourceFilename is not set', __FILE__, __LINE__); + + } + + if (is_null($this->getimagesizeinfo)) { + $this->getimagesizeinfo = @GetImageSize($this->sourceFilename); + } + + if (!empty($this->getimagesizeinfo)) { + // great + $this->getimagesizeinfo['filesize'] = @filesize($this->sourceFilename); + } elseif (!$this->rawImageData) { + $this->DebugMessage('GetImageSize("'.$this->sourceFilename.'") failed', __FILE__, __LINE__); + } + + if ($this->config_prefer_imagemagick) { + if ($this->ImageMagickThumbnailToGD()) { + return true; + } + $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); + } + + $this->source_width = $this->getimagesizeinfo[0]; + $this->source_height = $this->getimagesizeinfo[1]; + + $this->SetOrientationDependantWidthHeight(); + + if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == 2)) { + // Extract EXIF info from JPEGs + + $this->exif_thumbnail_width = ''; + $this->exif_thumbnail_height = ''; + $this->exif_thumbnail_type = ''; + + // The parameters width, height and imagetype are available since PHP v4.3.0 + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + + $this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type); + + } else { + + // older versions of exif_thumbnail output an error message but NOT return false on failure + ob_start(); + $this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename); + $exit_thumbnail_error = ob_get_contents(); + ob_end_clean(); + if (!$exit_thumbnail_error && $this->exif_thumbnail_data) { + + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + $this->exif_thumbnail_width = ImageSX($gdimg_exif_temp); + $this->exif_thumbnail_height = ImageSY($gdimg_exif_temp); + $this->exif_thumbnail_type = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned + unset($gdimg_exif_temp); + } else { + return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in '.__FILE__.' on line '.__LINE__); + } + + } + + } + + } elseif (!function_exists('exif_thumbnail')) { + + $this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__); + return false; + + } + + $this->DebugMessage('EXIF thumbnail extraction: (size='.strlen($this->exif_thumbnail_data).'; type="'.$this->exif_thumbnail_type.'"; '.intval($this->exif_thumbnail_width).'x'.intval($this->exif_thumbnail_height).')', __FILE__, __LINE__); + + // see if EXIF thumbnail can be used directly with no processing + if ($this->config_use_exif_thumbnail_for_speed && $this->exif_thumbnail_data) { + while (true) { + if (!$this->xto) { + $source_ar = $this->source_width / $this->source_height; + $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; + if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { + $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); + break; + } + if ($this->w && ($this->w != $this->exif_thumbnail_width)) { + $this->DebugMessage('not using EXIF thumbnail because $this->w != $this->exif_thumbnail_width ('.$this->w.' != '.$this->exif_thumbnail_width.')', __FILE__, __LINE__); + break; + } + if ($this->h && ($this->h != $this->exif_thumbnail_height)) { + $this->DebugMessage('not using EXIF thumbnail because $this->h != $this->exif_thumbnail_height ('.$this->h.' != '.$this->exif_thumbnail_height.')', __FILE__, __LINE__); + break; + } + $CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'far', 'bg', 'bc', 'fltr', 'phpThumbDebug'); + foreach ($CannotBeSetParameters as $dummy => $parameter) { + if ($this->$parameter) { + break 2; + } + } + } + + $this->DebugMessage('setting $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data)', __FILE__, __LINE__); + $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + return true; + } + } + + if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) { + + // Source image is larger than would fit in available PHP memory. + // If ImageMagick is installed, use it to generate the thumbnail. + // Else, if an EXIF thumbnail is available, use that as the source image. + // Otherwise, no choice but to fail with an error message + $this->DebugMessage('image is '.$this->source_width.'x'.$this->source_height.' and therefore contains more pixels ('.($this->source_width * $this->source_height).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); + if (!$this->config_prefer_imagemagick && $this->ImageMagickThumbnailToGD()) { + // excellent, we have a thumbnailed source image + return true; + } + + } + return true; + } + + + function SetCacheFilename() { + if (!is_null($this->cache_filename)) { + $this->DebugMessage('$this->cache_filename already set, skipping SetCacheFilename()', __FILE__, __LINE__); + return true; + } + $this->setOutputFormat(); + $this->setCacheDirectory(); + if (!$this->config_cache_directory) { + $this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__); + return false; + } + + if (!$this->sourceFilename && !$this->rawImageData && $this->src) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); + } + + if ($this->config_cache_default_only_suffix && $this->sourceFilename) { + // simplified cache filenames: + // only use default parameters in phpThumb.config.php + // substitute source filename into * in $this->config_cache_default_only_suffix + // (eg: '*_thumb' becomes 'picture_thumb.jpg') + if (strpos($this->config_cache_default_only_suffix, '*') === false) { + $this->DebugMessage('aborting simplified caching filename because no * in "'.$this->config_cache_default_only_suffix.'"', __FILE__, __LINE__); + } else { + preg_match('/(.+)(\.[a-z0-9]+)?$/iU', basename($this->sourceFilename), $matches); + $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.str_replace('*', $matches[1], $this->config_cache_default_only_suffix).'.'.strtolower($this->thumbnailFormat); + return true; + } + } + + $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.$this->config_cache_prefix; + if ($this->new) { + $this->cache_filename .= '_new'.strtolower(md5($this->new)); + } elseif ($this->md5s) { + // source image MD5 hash provided + $this->DebugMessage('SetCacheFilename() _raw set from $this->md5s = "'.$this->md5s.'"', __FILE__, __LINE__); + $this->cache_filename .= '_raw'.$this->md5s; + } elseif (!$this->src && $this->rawImageData) { + $this->DebugMessage('SetCacheFilename() _raw set from md5($this->rawImageData) = "'.md5($this->rawImageData).'"', __FILE__, __LINE__); + $this->cache_filename .= '_raw'.strtolower(md5($this->rawImageData)); + } else { + $this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "'.$this->sourceFilename.'" = "'.md5($this->sourceFilename).'"', __FILE__, __LINE__); + $this->cache_filename .= '_src'.strtolower(md5($this->sourceFilename)); + } + if (@$_SERVER['HTTP_REFERER'] && $this->config_nooffsitelink_enabled) { + $parsed_url1 = @parse_url(@$_SERVER['HTTP_REFERER']); + $parsed_url2 = @parse_url('http://'.@$_SERVER['HTTP_HOST']); + if (@$parsed_url1['host'] && @$parsed_url2['host'] && ($parsed_url1['host'] != $parsed_url2['host'])) { + // include "_offsite" only if nooffsitelink_enabled and if referrer doesn't match the domain of the current server + $this->cache_filename .= '_offsite'; + } + } + + $ParametersString = ''; + if ($this->fltr && is_array($this->fltr)) { + $ParametersString .= '_fltr'.implode('_fltr', $this->fltr); + } + $FilenameParameters1 = array('ar', 'bg', 'bc', 'far'); + foreach ($FilenameParameters1 as $dummy => $key) { + if ($this->$key) { + $ParametersString .= '_'.$key.$this->$key; + } + } + $FilenameParameters2 = array('h', 'w', 'wl', 'wp', 'ws', 'hp', 'hs', 'sx', 'sy', 'sw', 'sh', 'xto', 'ra', 'iar', 'aoe', 'maxb'); + foreach ($FilenameParameters2 as $dummy => $key) { + if ($this->$key) { + $ParametersString .= '_'.$key.intval($this->$key); + } + } + if ($this->thumbnailFormat == 'jpeg') { + // only JPEG output has variable quality option + $ParametersString .= '_q'.intval($this->thumbnailQuality); + } + $this->DebugMessage('SetCacheFilename() _par set from md5('.$ParametersString.')', __FILE__, __LINE__); + $this->cache_filename .= '_par'.strtolower(md5($ParametersString)); + + if ($this->md5s) { + // source image MD5 hash provided + // do not source image modification date -- + // cached image will be used even if file was modified or removed + } elseif (!$this->config_cache_source_filemtime_ignore_remote && eregi('^(f|ht)tps?://', $this->src)) { + $this->cache_filename .= '_dat'.intval(phpthumb_functions::filedate_remote($this->src)); + } elseif (!$this->config_cache_source_filemtime_ignore_local && $this->src && !$this->rawImageData) { + $this->cache_filename .= '_dat'.intval(@filemtime($this->sourceFilename)); + } + + $this->cache_filename .= '.'.strtolower($this->thumbnailFormat); + + return true; + } + + + function ImageCreateFromFilename($filename, &$rawimagedata) { + // try to create GD image source directly via GD, if possible, + // rather than buffering to memory and creating with ImageCreateFromString + $ImageCreateWasAttempted = false; + $gd_image = false; + + $this->DebugMessage('starting ImageCreateFromFilename('.$filename.', ['.strlen($rawimagedata).' bytes])', __FILE__, __LINE__); + + if ($filename && ($getimagesizeinfo = @GetImageSize($filename))) { + if (($this->config_max_source_pixels > 0) && (($getimagesizeinfo[0] * $getimagesizeinfo[1]) > $this->config_max_source_pixels)) { + $ImageCreateFromFunction = array( + 1 => 'ImageCreateFromGIF', + 2 => 'ImageCreateFromJPEG', + 3 => 'ImageCreateFromPNG', + 15 => 'ImageCreateFromWBMP', + ); + $this->DebugMessage('ImageCreateFromFilename found ($getimagesizeinfo[2]=='.@$getimagesizeinfo[2].')', __FILE__, __LINE__); + switch (@$getimagesizeinfo[2]) { + case 1: // GIF + case 2: // JPEG + case 3: // PNG + case 15: // WBMP + $ImageCreateFromFunctionName = $ImageCreateFromFunction[$getimagesizeinfo[2]]; + if (function_exists($ImageCreateFromFunctionName)) { + $this->DebugMessage('Calling '.$ImageCreateFromFunctionName.'('.$filename.')', __FILE__, __LINE__); + $ImageCreateWasAttempted = true; + $gd_image = @$ImageCreateFromFunctionName($filename); + } else { + $this->DebugMessage('NOT calling '.$ImageCreateFromFunctionName.'('.$filename.') because !function_exists('.$ImageCreateFromFunctionName.')', __FILE__, __LINE__); + } + break; + + case 4: // SWF + case 5: // PSD + case 6: // BMP + case 7: // TIFF (LE) + case 8: // TIFF (BE) + case 9: // JPC + case 10: // JP2 + case 11: // JPX + case 12: // JB2 + case 13: // SWC + case 14: // IFF + case 16: // XBM + $this->DebugMessage('No built-in image creation function for image type "'.@$getimagesizeinfo[2].'" ($getimagesizeinfo[2])', __FILE__, __LINE__); + break; + + default: + $this->DebugMessage('Unknown value for $getimagesizeinfo[2]: "'.@$getimagesizeinfo[2].'"', __FILE__, __LINE__); + break; + } + } else { + $this->DebugMessage('image is '.$getimagesizeinfo[0].'x'.$getimagesizeinfo[1].' and therefore contains more pixels ('.($getimagesizeinfo[0] * $getimagesizeinfo[1]).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('empty $filename or GetImageSize('.$filename.') failed', __FILE__, __LINE__); + } + + if (!$gd_image) { + // cannot create from filename, attempt to create source image with ImageCreateFromString, if possible + if ($ImageCreateWasAttempted) { + $this->DebugMessage(@$ImageCreateFromFunctionName.'() was attempted but FAILED', __FILE__, __LINE__); + } + if (!$rawimagedata) { + $this->DebugMessage('Populating $rawimagedata', __FILE__, __LINE__); + if ($fp = @fopen($filename, 'rb')) { + + $rawimagedata = ''; + $filesize = filesize($filename); + $blocksize = 32768; + $blockreads = ceil($filesize / $blocksize); + for ($i = 0; $i < $blockreads; $i++) { + $rawimagedata .= fread($fp, $blocksize); + } + fclose($fp); + + } else { + $this->DebugMessage('cannot fopen('.$filename.')', __FILE__, __LINE__); + } + } + if ($rawimagedata) { + $this->DebugMessage('attempting ImageCreateFromStringReplacement($rawimagedata ('.strlen($rawimagedata).' bytes), true)', __FILE__, __LINE__); + $gd_image = $this->ImageCreateFromStringReplacement($rawimagedata, true); + } + } + return $gd_image; + } + + function SourceImageToGD() { + if (is_resource($this->gdimg_source)) { + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $this->DebugMessage('skipping SourceImageToGD() because $this->gdimg_source is already a resource ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); + return true; + } + $this->DebugMessage('starting SourceImageToGD()', __FILE__, __LINE__); + while (true) { + if (!$this->config_use_exif_thumbnail_for_speed) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__); + break; + } + if (!$this->exif_thumbnail_data) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty', __FILE__, __LINE__); + break; + } + if (($this->thumbnailCropX != 0) || ($this->thumbnailCropY != 0)) { + $this->DebugMessage('Not using EXIF thumbnail data because source cropping is enabled ('.$this->thumbnailCropX.','.$this->thumbnailCropY.')', __FILE__, __LINE__); + break; + } + if (($this->w > $this->exif_thumbnail_width) || ($this->h > $this->exif_thumbnail_height)) { + $this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small ('.$this->exif_thumbnail_width.'x'.$this->exif_thumbnail_height.' vs '.$this->w.'x'.$this->h.')', __FILE__, __LINE__); + break; + } + $source_ar = $this->source_width / $this->source_height; + $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; + if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { + $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); + } + + // EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image + $this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__); + + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + + $this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__); + $this->gdimg_source = $gdimg_exif_temp; + $this->source_width = $this->exif_thumbnail_width; + $this->source_height = $this->exif_thumbnail_height; + $this->thumbnailCropW = $this->source_width; + $this->thumbnailCropH = $this->source_height; + return true; + + } else { + $this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__); + } + + break; + } + if (!$this->gdimg_source) { + + if ($this->md5s && ($this->md5s != phpthumb_functions::md5_file_safe($this->sourceFilename))) { + return $this->ErrorImage('$this->md5s != md5($rawimagedata)'."\n".'"'.$this->md5s.'" != '."\n".'"'.phpthumb_functions::md5_file_safe($this->sourceFilename).'"'); + } + switch (@$this->getimagesizeinfo[2]) { + case 1: + case 3: + // GIF or PNG input file may have transparency + $this->is_alpha = true; + break; + } + + $this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename, $this->rawImageData); + + if ($this->md5s && ($this->md5s != md5($this->rawImageData))) { + return $this->ErrorImage('$this->md5s != md5($this->rawImageData)'."\n".'"'.$this->md5s.'" != '."\n".'"'.md5($this->rawImageData).'"'); + } + + if (!$this->gdimg_source) { + $this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__); + + if ($this->ImageMagickThumbnailToGD()) { + + // excellent, we have a thumbnailed source image + $this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__); + + } else { + + $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); + + $imageHeader = ''; + $gd_info = gd_info(); + $GDreadSupport = false; + switch (substr($this->rawImageData, 0, 3)) { + case 'GIF': + $imageHeader = 'Content-Type: image/gif'; + $GDreadSupport = (bool) @$gd_info['GIF Read Support']; + break; + case "\xFF\xD8\xFF": + $imageHeader = 'Content-Type: image/jpeg'; + $GDreadSupport = (bool) @$gd_info['JPG Support']; + break; + case "\x89".'PN': + $imageHeader = 'Content-Type: image/png'; + $GDreadSupport = (bool) @$gd_info['PNG Support']; + break; + } + if ($imageHeader) { + // cannot create image for whatever reason (maybe ImageCreateFromJPEG et al are not available?) + // and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit + if ($this->config_error_die_on_source_failure) { + $this->ErrorImage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), cannot generate thumbnail'); + } else { + //$this->DebugMessage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), outputing raw image', __FILE__, __LINE__); + //if (!$this->phpThumbDebug) { + // header($imageHeader); + // echo $this->rawImageData; + // exit; + //} + return false; + } + } + + switch (substr($this->rawImageData, 0, 2)) { + case 'BM': + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + ob_end_clean(); + return $this->ErrorImage('include_once('.dirname(__FILE__).'/phpthumb.bmp.php) failed'); + } + ob_end_clean(); + $phpthumb_bmp = new phpthumb_bmp(); + if ($this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, (phpthumb_functions::gd_version() >= 2.0))) { + $this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__); + break; + } + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on BMP source conversion' : 'phpthumb_bmp2gd() failed'); + break; + } + + + switch (substr($this->rawImageData, 0, 4)) { + case 'II'."\x2A\x00": + case 'MM'."\x00\x2A": + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on TIFF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support TIFF source images without it'); + break; + + case "\xD7\xCD\xC6\x9A": + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); + break; + } + + if (!$this->gdimg_source) { + return $this->ErrorImage('Unknown image type identified by "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()'); + } + + } + } + } + if (!$this->gdimg_source) { + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + $this->DebugMessage('All other attempts failed, but successfully using EXIF thumbnail as source image', __FILE__, __LINE__); + $this->gdimg_source = $gdimg_exif_temp; + // override allow-enlarging setting if EXIF thumbnail is the only source available + // otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size + $this->aoe = true; + return true; + } + return false; + } + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + return true; + } + + + function phpThumbDebugVarDump($var) { + if (is_null($var)) { + return 'NULL'; + } elseif (is_bool($var)) { + return ($var ? 'TRUE' : 'FALSE'); + } elseif (is_string($var)) { + return 'string('.strlen($var).')'.str_repeat(' ', max(0, 3 - strlen(strlen($var)))).' "'.$var.'"'; + } elseif (is_int($var)) { + return 'integer '.$var; + } elseif (is_float($var)) { + return 'float '.$var; + } elseif (is_array($var)) { + ob_start(); + var_dump($var); + $vardumpoutput = ob_get_contents(); + ob_end_clean(); + return strtr($vardumpoutput, "\n\r\t", ' '); + } + return gettype($var); + } + + function phpThumbDebug() { + if ($this->config_disable_debug) { + return $this->ErrorImage('phpThumbDebug disabled'); + } + + $FunctionsExistance = array('exif_thumbnail', 'gd_info', 'image_type_to_mime_type', 'ImageCopyResampled', 'ImageCopyResized', 'ImageCreate', 'ImageCreateFromString', 'ImageCreateTrueColor', 'ImageIsTrueColor', 'ImageRotate', 'ImageTypes', 'version_compare', 'ImageCreateFromGIF', 'ImageCreateFromJPEG', 'ImageCreateFromPNG', 'ImageCreateFromWBMP', 'ImageCreateFromXBM', 'ImageCreateFromXPM', 'ImageCreateFromString', 'ImageCreateFromGD', 'ImageCreateFromGD2', 'ImageCreateFromGD2Part', 'ImageJPEG', 'ImageGIF', 'ImagePNG', 'ImageWBMP'); + $ParameterNames = array('src', 'new', 'w', 'h', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'far', 'bg', 'bc', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'iar', 'maxb'); + $ConfigVariableNames = array('document_root', 'temp_directory', 'output_format', 'output_maxwidth', 'output_maxheight', 'error_message_image_default', 'error_bgcolor', 'error_textcolor', 'error_fontsize', 'error_die_on_error', 'error_silent_die_on_error', 'error_die_on_source_failure', 'nohotlink_enabled', 'nohotlink_valid_domains', 'nohotlink_erase_image', 'nohotlink_text_message', 'nooffsitelink_enabled', 'nooffsitelink_valid_domains', 'nooffsitelink_require_refer', 'nooffsitelink_erase_image', 'nooffsitelink_text_message', 'high_security_enabled', 'allow_src_above_docroot', 'allow_src_above_phpthumb', 'allow_parameter_file', 'allow_parameter_goto', 'max_source_pixels', 'use_exif_thumbnail_for_speed', 'border_hexcolor', 'background_hexcolor', 'ttf_directory', 'disable_pathinfo_parsing', 'disable_imagecopyresampled'); + $OtherVariableNames = array('phpThumbDebug', 'thumbnailQuality', 'thumbnailFormat', 'gdimg_output', 'gdimg_source', 'sourceFilename', 'source_width', 'source_height', 'thumbnailCropX', 'thumbnailCropY', 'thumbnailCropW', 'thumbnailCropH', 'exif_thumbnail_width', 'exif_thumbnail_height', 'exif_thumbnail_type', 'thumbnail_width', 'thumbnail_height', 'thumbnail_image_width', 'thumbnail_image_height'); + + $DebugOutput = array(); + $DebugOutput[] = 'phpThumb() version = '.$this->phpthumb_version; + $DebugOutput[] = 'phpversion() = '.@phpversion(); + $DebugOutput[] = 'PHP_OS = '.PHP_OS; + $DebugOutput[] = '__FILE__ = '.__FILE__; + $DebugOutput[] = 'realpath(.) = '.@realpath('.'); + $DebugOutput[] = '$_SERVER[PHP_SELF] = '.@$_SERVER['PHP_SELF']; + $DebugOutput[] = '$_SERVER[HTTP_REFERER] = '.@$_SERVER['HTTP_REFERER']; + $DebugOutput[] = '$_SERVER[QUERY_STRING] = '.@$_SERVER['QUERY_STRING']; + $DebugOutput[] = '$_SERVER[PATH_INFO] = '.@$_SERVER['PATH_INFO']; + $DebugOutput[] = '$_SERVER[DOCUMENT_ROOT] = '.@$_SERVER['DOCUMENT_ROOT']; + $DebugOutput[] = 'getenv(DOCUMENT_ROOT) = '.@getenv('DOCUMENT_ROOT'); + $DebugOutput[] = ''; + + $DebugOutput[] = 'get_magic_quotes_gpc() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_gpc()); + $DebugOutput[] = 'get_magic_quotes_runtime() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_runtime()); + $DebugOutput[] = 'error_reporting() = '.$this->phpThumbDebugVarDump(error_reporting()); + $DebugOutput[] = 'ini_get(error_reporting) = '.$this->phpThumbDebugVarDump(@ini_get('error_reporting')); + $DebugOutput[] = 'ini_get(display_errors) = '.$this->phpThumbDebugVarDump(@ini_get('display_errors')); + $DebugOutput[] = 'ini_get(allow_url_fopen) = '.$this->phpThumbDebugVarDump(@ini_get('allow_url_fopen')); + $DebugOutput[] = 'ini_get(disable_functions) = '.$this->phpThumbDebugVarDump(@ini_get('disable_functions')); + $DebugOutput[] = 'ini_get(safe_mode) = '.$this->phpThumbDebugVarDump(@ini_get('safe_mode')); + $DebugOutput[] = 'ini_get(open_basedir) = '.$this->phpThumbDebugVarDump(@ini_get('open_basedir')); + $DebugOutput[] = 'ini_get(memory_limit) = '.$this->phpThumbDebugVarDump(@ini_get('memory_limit')); + $DebugOutput[] = 'ini_get(max_execution_time) = '.$this->phpThumbDebugVarDump(@ini_get('max_execution_time')); + $DebugOutput[] = 'get_cfg_var(memory_limit) = '.$this->phpThumbDebugVarDump(@get_cfg_var('memory_limit')); + $DebugOutput[] = 'memory_get_usage() = '.(function_exists('memory_get_usage') ? $this->phpThumbDebugVarDump(@memory_get_usage()) : 'n/a'); + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->config_prefer_imagemagick = '.$this->phpThumbDebugVarDump($this->config_prefer_imagemagick); + $DebugOutput[] = '$this->config_imagemagick_path = '.$this->phpThumbDebugVarDump($this->config_imagemagick_path); + $DebugOutput[] = '$this->ImageMagickWhichConvert() = '.$this->ImageMagickWhichConvert(); + $IMpathUsed = ($this->config_imagemagick_path ? $this->config_imagemagick_path : $this->ImageMagickWhichConvert()); + $DebugOutput[] = '[actual ImageMagick path used] = '.$this->phpThumbDebugVarDump($IMpathUsed); + $DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(@file_exists($IMpathUsed)); + $DebugOutput[] = 'ImageMagickVersion() = '.$this->ImageMagickVersion(); + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->config_cache_directory = '.$this->phpThumbDebugVarDump($this->config_cache_directory); + $DebugOutput[] = '$this->config_cache_disable_warning = '.$this->phpThumbDebugVarDump($this->config_cache_disable_warning); + $DebugOutput[] = '$this->config_cache_maxage = '.$this->phpThumbDebugVarDump($this->config_cache_maxage); + $DebugOutput[] = '$this->config_cache_maxsize = '.$this->phpThumbDebugVarDump($this->config_cache_maxsize); + $DebugOutput[] = '$this->config_cache_maxfiles = '.$this->phpThumbDebugVarDump($this->config_cache_maxfiles); + $DebugOutput[] = '$this->config_cache_force_passthru = '.$this->phpThumbDebugVarDump($this->config_cache_force_passthru); + $DebugOutput[] = '$this->cache_filename = '.$this->phpThumbDebugVarDump($this->cache_filename); + $DebugOutput[] = 'is_readable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(is_readable($this->config_cache_directory)); + $DebugOutput[] = 'is_writable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(is_writable($this->config_cache_directory)); + $DebugOutput[] = 'is_readable($this->cache_filename) = '.$this->phpThumbDebugVarDump(is_readable($this->cache_filename)); + $DebugOutput[] = 'is_writable($this->cache_filename) = '.(file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(is_writable($this->cache_filename)) : 'n/a'); + $DebugOutput[] = ''; + + foreach ($ConfigVariableNames as $dummy => $varname) { + $varname = 'config_'.$varname; + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 37, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + foreach ($OtherVariableNames as $dummy => $varname) { + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 27, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = 'strlen($this->rawImageData) = '.strlen(@$this->rawImageData); + $DebugOutput[] = 'strlen($this->exif_thumbnail_data) = '.strlen(@$this->exif_thumbnail_data); + $DebugOutput[] = ''; + + foreach ($ParameterNames as $dummy => $varname) { + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 4, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + foreach ($FunctionsExistance as $dummy => $functionname) { + $DebugOutput[] = 'builtin_function_exists('.$functionname.')'.str_repeat(' ', 23 - strlen($functionname)).' = '.$this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname)); + } + $DebugOutput[] = ''; + + $gd_info = gd_info(); + foreach ($gd_info as $key => $value) { + $DebugOutput[] = 'gd_info.'.str_pad($key, 34, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + $exif_info = phpthumb_functions::exif_info(); + foreach ($exif_info as $key => $value) { + $DebugOutput[] = 'exif_info.'.str_pad($key, 26, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { + foreach ($ApacheLookupURIarray as $key => $value) { + $DebugOutput[] = 'ApacheLookupURIarray.'.str_pad($key, 15, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + } else { + $DebugOutput[] = 'ApacheLookupURIarray() -- FAILED'; + } + $DebugOutput[] = ''; + + if (isset($_GET) && is_array($_GET)) { + foreach ($_GET as $key => $value) { + $DebugOutput[] = '$_GET['.$key.']'.str_repeat(' ', 30 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); + } + } + if (isset($_POST) && is_array($_POST)) { + foreach ($_POST as $key => $value) { + $DebugOutput[] = '$_POST['.$key.']'.str_repeat(' ', 29 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); + } + } + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->debugmessages:'; + foreach ($this->debugmessages as $dummy => $errorstring) { + $DebugOutput[] = ' * '.$errorstring; + } + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->debugtiming:'; + foreach ($this->debugtiming as $timestamp => $timingstring) { + $DebugOutput[] = ' * '.$timestamp.' '.$timingstring; + } + $DebugOutput[] = ' * Total processing time: '.number_format(max(array_keys($this->debugtiming)) - min(array_keys($this->debugtiming)), 6); + + return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500, true); + } + + function ErrorImage($text, $width=0, $height=0, $forcedisplay=false) { + $width = ($width ? $width : $this->config_error_image_width); + $height = ($height ? $height : $this->config_error_image_height); + + $text = 'phpThumb() v'.$this->phpthumb_version."\n\n".$text; + if ($this->config_disable_debug) { + $text = 'Error messages disabled'; + } + + $this->DebugMessage($text, __FILE__, __LINE__); + if ($this->phpThumbDebug && !$forcedisplay) { + return false; + } + if (!$this->config_error_die_on_error && !$forcedisplay) { + $this->fatalerror = $text; + return false; + } + if ($this->config_error_silent_die_on_error) { + exit; + } + if ($this->err || $this->config_error_message_image_default) { + // Show generic custom error image instead of error message + // for use on production sites where you don't want debug messages + if ($this->err == 'showerror') { + // fall through and actually show error message even if default error image is set + } else { + header('Location: '.($this->err ? $this->err : $this->config_error_message_image_default)); + exit; + } + } + if (!$this->thumbnailFormat || (phpthumb_functions::gd_version() < 1)) { + $this->thumbnailFormat = 'text'; + } + if (@$this->thumbnailFormat == 'text') { + // bypass all GD functions and output text error message + die('
    '.$text.'
    '); + } + + $FontWidth = ImageFontWidth($this->config_error_fontsize); + $FontHeight = ImageFontHeight($this->config_error_fontsize); + + $LinesOfText = explode("\n", @wordwrap($text, floor($width / $FontWidth), "\n", true)); + $height = max($height, count($LinesOfText) * $FontHeight); + + $headers_file = ''; + $headers_line = ''; + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=') && headers_sent($headers_file, $headers_line)) { + + echo "\n".'**Headers already sent in file "'.$headers_file.'" on line "'.$headers_line.'", dumping error message as text:**
    '."\n\n".$text."\n".'
    '; + + } elseif (headers_sent()) { + + echo "\n".'**Headers already sent, dumping error message as text:**
    '."\n\n".$text."\n".'
    '; + + } elseif ($gdimg_error = ImageCreate($width, $height)) { + + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor, true); + $text_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true); + ImageFilledRectangle($gdimg_error, 0, 0, $width, $height, $background_color); + $lineYoffset = 0; + foreach ($LinesOfText as $dummy => $line) { + ImageString($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color); + $lineYoffset += $FontHeight; + } + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_PNG) { + header('Content-Type: image/png'); + ImagePNG($gdimg_error); + } elseif ($imagetypes & IMG_GIF) { + header('Content-Type: image/gif'); + ImageGIF($gdimg_error); + } elseif ($imagetypes & IMG_JPG) { + header('Content-Type: image/jpeg'); + ImageJPEG($gdimg_error); + } elseif ($imagetypes & IMG_WBMP) { + header('Content-Type: image/wbmp'); + ImageWBMP($gdimg_error); + } + } + ImageDestroy($gdimg_error); + + } + if (!headers_sent()) { + echo "\n".'**Failed to send graphical error image, dumping error message as text:**
    '."\n\n".$text; + } + exit; + return true; + } + + function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors=false) { + // there are serious bugs in the non-bundled versions of GD which may cause + // PHP to segfault when calling ImageCreateFromString() - avoid if at all possible + // when not using a bundled version of GD2 + if (phpthumb_functions::gd_is_bundled()) { + return @ImageCreateFromString($RawImageData); + } + if (ini_get('safe_mode')) { + $this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__); + return false; + } + + switch (substr($RawImageData, 0, 3)) { + case 'GIF': + $ICFSreplacementFunctionName = 'ImageCreateFromGIF'; + break; + case "\xFF\xD8\xFF": + $ICFSreplacementFunctionName = 'ImageCreateFromJPEG'; + break; + case "\x89".'PN': + $ICFSreplacementFunctionName = 'ImageCreateFromPNG'; + break; + default: + $this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "'.phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)).'"', __FILE__, __LINE__); + return false; + break; + } + if ($tempnam = $this->phpThumb_tempnam()) { + if ($fp_tempnam = @fopen($tempnam, 'wb')) { + fwrite($fp_tempnam, $RawImageData); + fclose($fp_tempnam); + if (($ICFSreplacementFunctionName == 'ImageCreateFromGIF') && !function_exists($ICFSreplacementFunctionName)) { + + // Need to create from GIF file, but ImageCreateFromGIF does not exist + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.gif.php')) { + $ErrorMessage = 'Failed to include required file "'.dirname(__FILE__).'/phpthumb.gif.php" in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + ob_end_clean(); + // gif_loadFileToGDimageResource() cannot read from raw data, write to file first + if ($tempfilename = $this->phpThumb_tempnam()) { + if ($fp_tempfile = @fopen($tempfilename, 'wb')) { + fwrite($fp_tempfile, $RawImageData); + fclose($fp_tempfile); + $gdimg_source = gif_loadFileToGDimageResource($tempfilename); + unlink($tempfilename); + return $gdimg_source; + break; + } else { + $ErrorMessage = 'Failed to open tempfile in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + } else { + $ErrorMessage = 'Failed to open generate tempfile name in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + + } elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam))) { + + // great + unlink($tempnam); + return $gdimg_source; + + } else { // GD functions not available + + if (!headers_sent()) { + // base64-encoded error image in GIF format + $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; + header('Content-Type: image/gif'); + echo base64_decode($ERROR_NOGD); + } else { + echo '*** ERROR: No PHP-GD support available ***'; + } + exit; + + } + } else { + $ErrorMessage = 'Failed to fopen('.$tempnam.', "wb") in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + @unlink($tempnam); + } else { + $ErrorMessage = 'Failed to generate phpThumb_tempnam() in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; + } + if ($DieOnErrors && $ErrorMessage) { + return $this->ErrorImage($ErrorMessage); + } + return false; + } + + function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) { + if (phpthumb_functions::gd_version() >= 2.0) { + if ($this->config_disable_imagecopyresampled) { + return phpthumb_functions::ImageCopyResampleBicubic($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + return ImageCopyResampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + return ImageCopyResized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + + function phpThumb_tempnam() { + if (!$this->config_temp_directory) { + $this->config_temp_directory = (getenv('TMPDIR') ? getenv('TMPDIR') : getenv('TMP')); + } + $tempnam = realpath(tempnam($this->config_temp_directory, 'pThumb')); + $this->DebugMessage('phpThumb_tempnam() returning "'.$tempnam.'"', __FILE__, __LINE__); + return $tempnam; + } + + function DebugMessage($message, $file='', $line='') { + $this->debugmessages[] = $message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); + return true; + } + + function DebugTimingMessage($message, $file='', $line='', $timestamp=0) { + if (!$timestamp) { + $timestamp = array_sum(explode(' ', microtime())); + } + $this->debugtiming[number_format($timestamp, 6, '.', '')] = ': '.$message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); + return true; + } + +} + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/phpthumb.filters.php b/site/runshops/phpthumb/phpthumb.filters.php new file mode 100644 index 0000000..ac058cb --- /dev/null +++ b/site/runshops/phpthumb/phpthumb.filters.php @@ -0,0 +1,1235 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.filters.php - image processing filter functions // +// /// +////////////////////////////////////////////////////////////// + +class phpthumb_filters { + + var $phpThumbObject = null; + + function phpthumb_filters() { + return true; + } + + function ApplyMask(&$gdimg_mask, &$gdimg_image) { + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping ApplyMask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=')) { + + $this->DebugMessage('Using alpha ApplyMask() technique', __FILE__, __LINE__); + if ($gdimg_mask_resized = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { + + ImageCopyResampled($gdimg_mask_resized, $gdimg_mask, 0, 0, 0, 0, ImageSX($gdimg_image), ImageSY($gdimg_image), ImageSX($gdimg_mask), ImageSY($gdimg_mask)); + if ($gdimg_mask_blendtemp = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { + + $color_background = ImageColorAllocate($gdimg_mask_blendtemp, 0, 0, 0); + ImageFilledRectangle($gdimg_mask_blendtemp, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp), $color_background); + ImageAlphaBlending($gdimg_mask_blendtemp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_mask_blendtemp, true); + for ($x = 0; $x < ImageSX($gdimg_image); $x++) { + for ($y = 0; $y < ImageSY($gdimg_image); $y++) { + //$RealPixel = phpthumb_functions::GetPixelColor($gdimg_mask_blendtemp, $x, $y); + $RealPixel = phpthumb_functions::GetPixelColor($gdimg_image, $x, $y); + $MaskPixel = phpthumb_functions::GrayscalePixel(phpthumb_functions::GetPixelColor($gdimg_mask_resized, $x, $y)); + $MaskAlpha = 127 - (floor($MaskPixel['red'] / 2) * (1 - ($RealPixel['alpha'] / 127))); + $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_mask_blendtemp, $RealPixel['red'], $RealPixel['green'], $RealPixel['blue'], $MaskAlpha); + ImageSetPixel($gdimg_mask_blendtemp, $x, $y, $newcolor); + } + } + ImageAlphaBlending($gdimg_image, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_image, true); + ImageCopy($gdimg_image, $gdimg_mask_blendtemp, 0, 0, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp)); + ImageDestroy($gdimg_mask_blendtemp); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + ImageDestroy($gdimg_mask_resized); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + + } else { + // alpha merging requires PHP v4.3.2+ + $this->DebugMessage('Skipping ApplyMask() technique because PHP is v"'.phpversion().'"', __FILE__, __LINE__); + } + return true; + } + + + function Bevel(&$gdimg, $width, $hexcolor1, $hexcolor2) { + $width = ($width ? $width : 5); + $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); + $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); + + ImageAlphaBlending($gdimg, true); + for ($i = 0; $i < $width; $i++) { + $alpha = round(($i / $width) * 127); + $color1[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1, false, $alpha); + $color2[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2, false, $alpha); + + ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1[$i]); // left + ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1[$i]); // top + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2[$i]); // right + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2[$i]); // bottom + } + return true; + } + + + function Blur(&$gdimg, $radius=0.5) { + // Taken from Torstein Hønsi's phpUnsharpMask (see phpthumb.unsharp.php) + + $radius = round(max(0, min($radius, 50)) * 2); + if (!$radius) { + return false; + } + + $w = ImageSX($gdimg); + $h = ImageSY($gdimg); + if ($imgBlur = ImageCreateTrueColor($w, $h)) { + // Gaussian blur matrix: + // 1 2 1 + // 2 4 2 + // 1 2 1 + + // Move copies of the image around one pixel at the time and merge them with weight + // according to the matrix. The same matrix is simply repeated for higher radii. + for ($i = 0; $i < $radius; $i++) { + ImageCopy ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1); // up left + ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w, $h, 50.00000); // down right + ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left + ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w, $h - 1, 25.00000); // up right + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left + ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w, $h, 25.00000); // right + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w, $h - 1, 20.00000); // up + ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w, $h, 16.666667); // down + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w, $h, 50.000000); // center + ImageCopy ($gdimg, $imgBlur, 0, 0, 0, 0, $w, $h); + } + return true; + } + return false; + } + + + function BlurGaussian(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)', __FILE__, __LINE__); + // fall through and try it the hard way + } + $this->DebugMessage('FAILED: phpthumb_filters::BlurGaussian($gdimg) [using phpthumb_filters::Blur() instead]', __FILE__, __LINE__); + return phpthumb_filters::Blur($gdimg, 0.5); + } + + + function BlurSelective(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::BlurSelective($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Brightness(&$gdimg, $amount=0) { + if ($amount == 0) { + return true; + } + $amount = max(-255, min(255, $amount)); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + + $scaling = (255 - abs($amount)) / 255; + $baseamount = (($amount > 0) ? $amount : 0); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + foreach ($OriginalPixel as $key => $value) { + $NewPixel[$key] = round($baseamount + ($OriginalPixel[$key] * $scaling)); + } + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Contrast(&$gdimg, $amount=0) { + if ($amount == 0) { + return true; + } + $amount = max(-255, min(255, $amount)); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_CONTRAST, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_CONTRAST, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + + if ($amount > 0) { + $scaling = 1 + ($amount / 255); + } else { + $scaling = (255 - abs($amount)) / 255; + } + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + foreach ($OriginalPixel as $key => $value) { + $NewPixel[$key] = min(255, max(0, round($OriginalPixel[$key] * $scaling))); + } + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + } + + + function Colorize(&$gdimg, $amount, $targetColor) { + $amount = (is_numeric($amount) ? $amount : 25); + $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'gray'); + + if ($amount == 0) { + return true; + } + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if ($targetColor == 'gray') { + $targetColor = '808080'; + } + $r = substr($targetColor, 0, 2); + $g = substr($targetColor, 2, 2); + $b = substr($targetColor, 4, 2); + if (ImageFilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + + // overridden below for grayscale + if ($targetColor != 'gray') { + $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); + $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); + $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); + } + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + if ($targetColor == 'gray') { + $TargetPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + } + foreach ($TargetPixel as $key => $value) { + $NewPixel[$key] = round(max(0, min(255, ($OriginalPixel[$key] * ((100 - $amount) / 100)) + ($TargetPixel[$key] * ($amount / 100))))); + } + //$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Desaturate(&$gdimg, $amount, $color='') { + if ($amount == 0) { + return true; + } + return phpthumb_filters::Colorize($gdimg, $amount, (phpthumb_functions::IsHexColor($color) ? $color : 'gray')); + } + + + function DropShadow(&$gdimg, $distance, $width, $hexcolor, $angle, $fade) { + if (phpthumb_functions::gd_version() < 2) { + return false; + } + $distance = ($distance ? $distance : 10); + $width = ($width ? $width : 10); + $hexcolor = ($hexcolor ? $hexcolor : '000000'); + $angle = ($angle ? $angle : 225); + $fade = ($fade ? $fade : 1); + + $width_shadow = cos(deg2rad($angle)) * ($distance + $width); + $height_shadow = sin(deg2rad($angle)) * ($distance + $width); + + $scaling = min(ImageSX($gdimg) / (ImageSX($gdimg) + abs($width_shadow)), ImageSY($gdimg) / (ImageSY($gdimg) + abs($height_shadow))); + + for ($i = 0; $i < $width; $i++) { + $WidthAlpha[$i] = (abs(($width / 2) - $i) / $width) * $fade; + $Offset['x'] = cos(deg2rad($angle)) * ($distance + $i); + $Offset['y'] = sin(deg2rad($angle)) * ($distance + $i); + } + + $tempImageWidth = ImageSX($gdimg) + abs($Offset['x']); + $tempImageHeight = ImageSY($gdimg) + abs($Offset['y']); + + if ($gdimg_dropshadow_temp = phpthumb_functions::ImageCreateFunction($tempImageWidth, $tempImageHeight)) { + + ImageAlphaBlending($gdimg_dropshadow_temp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_dropshadow_temp, true); + $transparent1 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, 0, 0, 0, 127); + ImageFill($gdimg_dropshadow_temp, 0, 0, $transparent1); + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $PixelMap[$x][$y] = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + } + } + for ($x = 0; $x < $tempImageWidth; $x++) { + for ($y = 0; $y < $tempImageHeight; $y++) { + //for ($i = 0; $i < $width; $i++) { + for ($i = 0; $i < 1; $i++) { + if (!isset($PixelMap[$x][$y]['alpha']) || ($PixelMap[$x][$y]['alpha'] > 0)) { + if (isset($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']) && ($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha'] < 127)) { + $thisColor = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor, false, $PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']); + ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); + } + } + } + } + } + + ImageAlphaBlending($gdimg_dropshadow_temp, true); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + if ($PixelMap[$x][$y]['alpha'] < 127) { + $thisColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, $PixelMap[$x][$y]['red'], $PixelMap[$x][$y]['green'], $PixelMap[$x][$y]['blue'], $PixelMap[$x][$y]['alpha']); + ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); + } + } + } + + phpthumb_functions::gd_ImageSaveAlpha($gdimg, true); + ImageAlphaBlending($gdimg, false); + //$this->is_alpha = true; + $transparent2 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0, 0, 0, 127); + ImageFilledRectangle($gdimg, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $transparent2); + ImageCopyResampled($gdimg, $gdimg_dropshadow_temp, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg_dropshadow_temp), ImageSY($gdimg_dropshadow_temp)); + + ImageDestroy($gdimg_dropshadow_temp); + } + return true; + } + + + function EdgeDetect(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::EdgeDetect($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Elipse($gdimg) { + if (phpthumb_functions::gd_version() < 2) { + return false; + } + // generate mask at twice desired resolution and downsample afterwards for easy antialiasing + if ($gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg) * 2, ImageSY($gdimg) * 2)) { + if ($gdimg_elipsemask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + + $color_transparent = ImageColorAllocate($gdimg_elipsemask_double, 255, 255, 255); + ImageFilledEllipse($gdimg_elipsemask_double, ImageSX($gdimg), ImageSY($gdimg), (ImageSX($gdimg) - 1) * 2, (ImageSY($gdimg) - 1) * 2, $color_transparent); + ImageCopyResampled($gdimg_elipsemask, $gdimg_elipsemask_double, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg) * 2, ImageSY($gdimg) * 2); + + phpthumb_filters::ApplyMask($gdimg_elipsemask, $gdimg); + ImageDestroy($gdimg_elipsemask); + return true; + + } else { + $this->DebugMessage('$gdimg_elipsemask = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); + } + ImageDestroy($gdimg_elipsemask_double); + } else { + $this->DebugMessage('$gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); + } + return false; + } + + + function Emboss(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_EMBOSS)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EMBOSS)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::Emboss($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Flip(&$gdimg, $x=false, $y=false) { + if (!$x && !$y) { + return false; + } + if ($tempImage = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + if ($x) { + ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + ImageCopy($gdimg, $tempImage, ImageSX($gdimg) - 1 - $x, 0, $x, 0, 1, ImageSY($gdimg)); + } + } + if ($y) { + ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); + for ($y = 0; $y < ImageSY($gdimg); $y++) { + ImageCopy($gdimg, $tempImage, 0, ImageSY($gdimg) - 1 - $y, 0, $y, ImageSX($gdimg), 1); + } + } + ImageDestroy($tempImage); + } + return true; + } + + + function Frame(&$gdimg, $frame_width, $edge_width, $hexcolor_frame, $hexcolor1, $hexcolor2) { + $frame_width = ($frame_width ? $frame_width : 5); + $edge_width = ($edge_width ? $edge_width : 1); + $hexcolor_frame = ($hexcolor_frame ? $hexcolor_frame : 'CCCCCC'); + $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); + $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); + + $color_frame = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor_frame); + $color1 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1); + $color2 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2); + for ($i = 0; $i < $edge_width; $i++) { + // outer bevel + ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1); // left + ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1); // top + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2); // right + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2); // bottom + } + for ($i = 0; $i < $frame_width; $i++) { + // actual frame + ImageRectangle($gdimg, $edge_width + $i, $edge_width + $i, ImageSX($gdimg) - $edge_width - $i, ImageSY($gdimg) - $edge_width - $i, $color_frame); + } + for ($i = 0; $i < $edge_width; $i++) { + // inner bevel + ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color2); // left + ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color2); // top + ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color1); // right + ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color1); // bottom + } + return true; + } + + + function Gamma(&$gdimg, $amount) { + if (number_format($amount, 4) == '1.0000') { + return true; + } + return ImageGammaCorrect($gdimg, 1.0, $amount); + } + + + function Grayscale(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + return phpthumb_filters::Colorize($gdimg, 100, 'gray'); + } + + + function HistogramAnalysis(&$gdimg, $calculateGray=false) { + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + @$Analysis['red'][$OriginalPixel['red']]++; + @$Analysis['green'][$OriginalPixel['green']]++; + @$Analysis['blue'][$OriginalPixel['blue']]++; + @$Analysis['alpha'][$OriginalPixel['alpha']]++; + if ($calculateGray) { + $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + @$Analysis['gray'][$GrayPixel['red']]++; + } + } + } + $keys = array('red', 'green', 'blue', 'alpha'); + if ($calculateGray) { + $keys[] = 'gray'; + } + foreach ($keys as $dummy => $key) { + ksort($Analysis[$key]); + } + return $Analysis; + } + + + function HistogramStretch(&$gdimg, $band='*', $min=-1, $max=-1) { + // equivalent of "Auto Contrast" in Adobe Photoshop + + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); + $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); + if (!isset($keys[$band])) { + return false; + } + $key = $keys[$band]; + + // If the absolute brightest and darkest pixels are used then one random + // pixel in the image could throw off the whole system. Instead, count up/down + // from the limit and allow 0.1% of brightest/darkest pixels to be clipped to min/max + $clip_threshold = ImageSX($gdimg) * ImageSX($gdimg) * 0.001; + if ($min >= 0) { + $range_min = min($min, 255); + } else { + $countsum = 0; + for ($i = 0; $i <= 255; $i++) { + $countsum += @$Analysis[$key][$i]; + if ($countsum >= $clip_threshold) { + $range_min = $i - 1; + break; + } + } + $range_min = max($range_min, 0); + } + if ($max >= 0) { + $range_max = max($max, 255); + } else { + $countsum = 0; + $threshold = ImageSX($gdimg) * ImageSX($gdimg) * 0.001; // 0.1% of brightest and darkest pixels can be clipped + for ($i = 255; $i >= 0; $i--) { + $countsum += @$Analysis[$key][$i]; + if ($countsum >= $clip_threshold) { + $range_max = $i + 1; + break; + } + } + $range_max = min($range_max, 255); + } + $range_scale = (($range_max == $range_min) ? 1 : (255 / ($range_max - $range_min))); + if (($range_min == 0) && ($range_max == 255)) { + // no adjustment neccesary - don't waste CPU time! + return true; + } + + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + if ($band == '*') { + $new['red'] = min(255, max(0, ($OriginalPixel['red'] - $range_min) * $range_scale)); + $new['green'] = min(255, max(0, ($OriginalPixel['green'] - $range_min) * $range_scale)); + $new['blue'] = min(255, max(0, ($OriginalPixel['blue'] - $range_min) * $range_scale)); + $new['alpha'] = min(255, max(0, ($OriginalPixel['alpha'] - $range_min) * $range_scale)); + } else { + $new = $OriginalPixel; + $new[$key] = min(255, max(0, ($OriginalPixel[$key] - $range_min) * $range_scale)); + } + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $new['red'], $new['green'], $new['blue'], $new['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + + return true; + } + + + function HistogramOverlay(&$gdimg, $bands='*', $colors='', $width=0.25, $height=0.25, $alignment='BR', $opacity=50, $margin=5) { + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); + + $histW = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); + $histH = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); + if ($gdHist = ImageCreateTrueColor($histW, $histH)) { + $color_back = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHist, 0, 0, 0, 127); + ImageFilledRectangle($gdHist, 0, 0, $histW, $histH, $color_back); + ImageAlphaBlending($gdHist, false); + phpthumb_functions::gd_ImageSaveAlpha($gdHist, true); + + if ($gdHistTemp = ImageCreateTrueColor(256, 100)) { + $color_back_temp = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHistTemp, 255, 0, 255, 127); + ImageAlphaBlending($gdHistTemp, false); + phpthumb_functions::gd_ImageSaveAlpha($gdHistTemp, true); + ImageFilledRectangle($gdHistTemp, 0, 0, ImageSX($gdHistTemp), ImageSY($gdHistTemp), $color_back_temp); + + $DefaultColors = array('r'=>'FF0000', 'g'=>'00FF00', 'b'=>'0000FF', 'a'=>'999999', '*'=>'FFFFFF'); + $Colors = explode(';', $colors); + $BandsToGraph = array_unique(preg_split('//', $bands)); + $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); + foreach ($BandsToGraph as $key => $band) { + if (!isset($keys[$band])) { + continue; + } + $PeakValue = max($Analysis[$keys[$band]]); + $thisColor = phpthumb_functions::ImageHexColorAllocate($gdHistTemp, phpthumb_functions::IsHexColor(@$Colors[$key]) ? $Colors[$key] : $DefaultColors[$band]); + $tempHeight = ImageSY($gdHistTemp); + for ($x = 0; $x <= 255; $x++) { + ImageLine($gdHistTemp, $x, $tempHeight - 1, $x, $tempHeight - 1 - round(@$Analysis[$keys[$band]][$x] / $PeakValue * $tempHeight), $thisColor); + } + ImageLine($gdHistTemp, 0, $tempHeight - 1, 255, $tempHeight - 1, $thisColor); + ImageLine($gdHistTemp, 0, $tempHeight - 2, 255, $tempHeight - 2, $thisColor); + } + ImageCopyResampled($gdHist, $gdHistTemp, 0, 0, 0, 0, ImageSX($gdHist), ImageSY($gdHist), ImageSX($gdHistTemp), ImageSY($gdHistTemp)); + ImageDestroy($gdHistTemp); + } else { + return false; + } + + phpthumb_filters::WatermarkOverlay($gdimg, $gdHist, $alignment, $opacity, $margin); + ImageDestroy($gdHist); + return true; + } + return false; + } + + + function ImageBorder(&$gdimg, $border_width, $radius_x, $radius_y, $hexcolor_border) { + $border_width = ($border_width ? $border_width : 1); + $radius_x = ($radius_x ? $radius_x : 0); + $radius_y = ($radius_y ? $radius_y : 0); + + $output_width = ImageSX($gdimg); + $output_height = ImageSY($gdimg); + + list($new_width, $new_height) = phpthumb_functions::ProportionalResize($output_width, $output_height, $output_width - max($border_width * 2, $radius_x), $output_height - max($border_width * 2, $radius_y)); + $offset_x = ($radius_x ? $output_width - $new_width - $radius_x : 0); + $offset_y = ($radius_y ? $output_height - $new_height - $radius_y : 0); + + if ($gd_border_canvas = phpthumb_functions::ImageCreateFunction($output_width, $output_height)) { + + phpthumb_functions::gd_ImageSaveAlpha($gd_border_canvas, true); + ImageAlphaBlending($gd_border_canvas, false); + $color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gd_border_canvas, 255, 255, 255, 127); + ImageFilledRectangle($gd_border_canvas, 0, 0, $output_width, $output_height, $color_background); + + $color_border = phpthumb_functions::ImageHexColorAllocate($gd_border_canvas, (phpthumb_functions::IsHexColor($hexcolor_border) ? $hexcolor_border : '000000')); + + for ($i = 0; $i < $border_width; $i++) { + ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $i, $output_width - $radius_x - ceil($offset_x / 2), $i, $color_border); // top + ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $output_height - 1 - $i, $output_width - $radius_x - ceil($offset_x / 2), $output_height - 1 - $i, $color_border); // bottom + ImageLine($gd_border_canvas, floor($offset_x / 2) + $i, $radius_y, floor($offset_x / 2) + $i, $output_height - $radius_y, $color_border); // left + ImageLine($gd_border_canvas, $output_width - 1 - $i - ceil($offset_x / 2), $radius_y, $output_width - 1 - $i - ceil($offset_x / 2), $output_height - $radius_y, $color_border); // right + } + + if ($radius_x && $radius_y) { + + // PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results + // Solution: Draw multiple 1px arcs side-by-side. + + // Problem: parallel arcs give strange/ugly antialiasing problems + // Solution: draw non-parallel arcs, from one side of the line thickness at the start angle + // to the opposite edge of the line thickness at the terminating angle + for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { + ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left + ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right + ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right + ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left + } + if ($border_width > 1) { + for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { + ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left + ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right + ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right + ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left + } + } + + } + $this->phpThumbObject->ImageResizeFunction($gd_border_canvas, $gdimg, floor(($output_width - $new_width) / 2), round(($output_height - $new_height) / 2), 0, 0, $new_width, $new_height, $output_width, $output_height); + + ImageDestroy($gdimg); + $gdimg = phpthumb_functions::ImageCreateFunction($output_width, $output_height); + phpthumb_functions::gd_ImageSaveAlpha($gdimg, true); + ImageAlphaBlending($gdimg, false); + $gdimg_color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 255, 255, 255, 127); + ImageFilledRectangle($gdimg, 0, 0, $output_width, $output_height, $gdimg_color_background); + + ImageCopy($gdimg, $gd_border_canvas, 0, 0, 0, 0, $output_width, $output_height); + //$gdimg = $gd_border_canvas; + ImageDestroy($gd_border_canvas); + return true; + + + } else { + $this->DebugMessage('FAILED: $gd_border_canvas = phpthumb_functions::ImageCreateFunction('.$output_width.', '.$output_height.')', __FILE__, __LINE__); + } + return false; + } + + + function MeanRemoval(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::MeanRemoval($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Negative(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_NEGATE)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_NEGATE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, (~$currentPixel['red'] & 0xFF), (~$currentPixel['green'] & 0xFF), (~$currentPixel['blue'] & 0xFF), $currentPixel['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function RoundedImageCorners(&$gdimg, $radius_x, $radius_y) { + // generate mask at twice desired resolution and downsample afterwards for easy antialiasing + // mask is generated as a white double-size elipse on a triple-size black background and copy-paste-resampled + // onto a correct-size mask image as 4 corners due to errors when the entire mask is resampled at once (gray edges) + if ($gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction($radius_x * 6, $radius_y * 6)) { + if ($gdimg_cornermask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + + $color_transparent = ImageColorAllocate($gdimg_cornermask_triple, 255, 255, 255); + ImageFilledEllipse($gdimg_cornermask_triple, $radius_x * 3, $radius_y * 3, $radius_x * 4, $radius_y * 4, $color_transparent); + + ImageFilledRectangle($gdimg_cornermask, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $color_transparent); + + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, 0, $radius_x, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, ImageSY($gdimg) - $radius_y, $radius_x, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, ImageSY($gdimg) - $radius_y, $radius_x * 3, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, 0, $radius_x * 3, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + + phpthumb_filters::ApplyMask($gdimg_cornermask, $gdimg); + ImageDestroy($gdimg_cornermask); + $this->DebugMessage('RoundedImageCorners('.$radius_x.', '.$radius_y.') succeeded', __FILE__, __LINE__); + return true; + + } else { + $this->DebugMessage('FAILED: $gdimg_cornermask = phpthumb_functions::ImageCreateFunction('.ImageSX($gdimg).', '.ImageSY($gdimg).')', __FILE__, __LINE__); + } + ImageDestroy($gdimg_cornermask_triple); + + } else { + $this->DebugMessage('FAILED: $gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction('.($radius_x * 6).', '.($radius_y * 6).')', __FILE__, __LINE__); + } + return false; + } + + + function Saturation(&$gdimg, $amount, $color='') { + if ($amount == 0) { + return true; + } elseif ($amount > 0) { + $amount = 0 - $amount; + } else { + $amount = abs($amount); + } + return phpthumb_filters::Desaturate($gdimg, $amount, $color); + } + + + function Sepia(&$gdimg, $amount, $targetColor) { + $amount = (is_numeric($amount) ? max(0, min(100, $amount)) : 50); + $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'A28065'); + + if ($amount == 0) { + return true; + } + + $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); + $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); + $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); + + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + + // http://www.gimpguru.org/Tutorials/SepiaToning/ + // "In the traditional sepia toning process, the tinting occurs most in + // the mid-tones: the lighter and darker areas appear to be closer to B&W." + $SepiaAmount = ((128 - abs($GrayPixel['red'] - 128)) / 128) * ($amount / 100); + + foreach ($TargetPixel as $key => $value) { + $NewPixel[$key] = round(max(0, min(255, $GrayPixel[$key] * (1 - $SepiaAmount) + ($TargetPixel[$key] * $SepiaAmount)))); + } + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Smooth(&$gdimg, $amount=6) { + $amount = min(25, max(0, $amount)); + if ($amount == 0) { + return true; + } + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_SMOOTH, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SMOOTH, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, '.$amount.') [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Threshold(&$gdimg, $cutoff) { + $cutoff = min(255, max(0, ($cutoff ? $cutoff : 128))); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $grayPixel = phpthumb_functions::GrayscalePixel($currentPixel); + if ($grayPixel['red'] < $cutoff) { + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0x00, 0x00, 0x00, $currentPixel['alpha']); + } else { + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0xFF, 0xFF, 0xFF, $currentPixel['alpha']); + } + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function ImageTrueColorToPalette2(&$image, $dither, $ncolors) { + // http://www.php.net/manual/en/function.imagetruecolortopalette.php + // zmorris at zsculpt dot com (17-Aug-2004 06:58) + $width = ImageSX($image); + $height = ImageSY($image); + $image_copy = ImageCreateTrueColor($width, $height); + //ImageCopyMerge($image_copy, $image, 0, 0, 0, 0, $width, $height, 100); + ImageCopy($image_copy, $image, 0, 0, 0, 0, $width, $height); + ImageTrueColorToPalette($image, $dither, $ncolors); + ImageColorMatch($image_copy, $image); + ImageDestroy($image_copy); + return true; + } + + function ReduceColorDepth(&$gdimg, $colors=256, $dither=true) { + $colors = max(min($colors, 256), 2); + // ImageTrueColorToPalette usually makes ugly colors, the replacement is a bit better + //ImageTrueColorToPalette($gdimg, $dither, $colors); + phpthumb_filters::ImageTrueColorToPalette2($gdimg, $dither, $colors); + return true; + } + + + function WhiteBalance(&$gdimg, $targetColor='') { + if (phpthumb_functions::IsHexColor($targetColor)) { + $targetPixel = array( + 'red' => hexdec(substr($targetColor, 0, 2)), + 'green' => hexdec(substr($targetColor, 2, 2)), + 'blue' => hexdec(substr($targetColor, 4, 2)) + ); + } else { + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, false); + $targetPixel = array( + 'red' => max(array_keys($Analysis['red'])), + 'green' => max(array_keys($Analysis['green'])), + 'blue' => max(array_keys($Analysis['blue'])) + ); + } + $grayValue = phpthumb_functions::GrayscaleValue($targetPixel['red'], $targetPixel['green'], $targetPixel['blue']); + $scaleR = $grayValue / $targetPixel['red']; + $scaleG = $grayValue / $targetPixel['green']; + $scaleB = $grayValue / $targetPixel['blue']; + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe( + $gdimg, + max(0, min(255, round($currentPixel['red'] * $scaleR))), + max(0, min(255, round($currentPixel['green'] * $scaleG))), + max(0, min(255, round($currentPixel['blue'] * $scaleB))), + $currentPixel['alpha'] + ); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function WatermarkText(&$gdimg, $text, $size, $alignment, $hex_color='000000', $ttffont='', $opacity=100, $margin=5, $angle=0, $bg_color=false, $bg_opacity=0, $fillextend='') { + // text watermark requested + if (!$text) { + return false; + } + ImageAlphaBlending($gdimg, true); + + $metaTextArray = array( + '^Fb' => $this->phpThumbObject->getimagesizeinfo['filesize'], + '^Fk' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1024), + '^Fm' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1048576), + '^X' => $this->phpThumbObject->getimagesizeinfo[0], + '^Y' => $this->phpThumbObject->getimagesizeinfo[1], + '^x' => ImageSX($gdimg), + '^y' => ImageSY($gdimg), + '^^' => '^', + ); + $text = strtr($text, $metaTextArray); + + $text = str_replace("\r\n", "\n", $text); + $text = str_replace("\r", "\n", $text); + $textlines = explode("\n", $text); + + if (@is_readable($ttffont) && is_file($ttffont)) { + + $opacity = 100 - intval(max(min($opacity, 100), 0)); + + $this->DebugMessage('Using TTF font "'.$ttffont.'"', __FILE__, __LINE__); + + $TTFbox = ImageTTFbBox($size, $angle, $ttffont, $text); + + $min_x = min($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); + $max_x = max($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); + //$text_width = round($max_x - $min_x + ($size * 0.5)); + $text_width = round($max_x - $min_x); + + $min_y = min($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); + $max_y = max($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); + //$text_height = round($max_y - $min_y + ($size * 0.5)); + $text_height = round($max_y - $min_y); + + $TTFboxChar = ImageTTFbBox($size, $angle, $ttffont, 'jH'); + $char_min_y = min($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); + $char_max_y = max($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); + $char_height = round($char_max_y - $char_min_y); + + switch ($alignment) { + case 'T': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = $char_height + $margin; + break; + + case 'B': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + + case 'L': + $text_origin_x = $margin; + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'R': + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'C': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'TL': + $text_origin_x = $margin; + $text_origin_y = $char_height + $margin; + break; + + case 'TR': + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = $char_height + $margin; + break; + + case 'BL': + $text_origin_x = $margin; + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + + case 'BR': + default: + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + } + $letter_color_text = phpthumb_functions::ImageHexColorAllocate($gdimg, $hex_color, false, $opacity * 1.27); + + if ($alignment == '*') { + + $text_origin_y = $char_height + $margin; + while (($text_origin_y - $text_height) < ImageSY($gdimg)) { + $text_origin_x = $margin; + while ($text_origin_x < ImageSX($gdimg)) { + ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); + $text_origin_x += ($text_width + $margin); + } + $text_origin_y += ($text_height + $margin); + } + + } else { + + //ImageRectangle($gdimg, $text_origin_x + $min_x, $text_origin_y + $TTFbox[1], $text_origin_x + $min_x + $text_width, $text_origin_y + $TTFbox[1] - $text_height, $letter_color_text); + if (phpthumb_functions::IsHexColor($bg_color)) { + $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); + $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, $bg_color, false, $text_background_alpha); + } else { + $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, 'FFFFFF', false, 127); + } + $x1 = $text_origin_x + $min_x; + $y1 = $text_origin_y + $TTFbox[1]; + $x2 = $text_origin_x + $min_x + $text_width; + $y2 = $text_origin_y + $TTFbox[1] - $text_height; + $x_TL = eregi('x', $fillextend) ? 0 : min($x1, $x2); + $y_TL = eregi('y', $fillextend) ? 0 : min($y1, $y2); + $x_BR = eregi('x', $fillextend) ? ImageSX($gdimg) : max($x1, $x2); + $y_BR = eregi('y', $fillextend) ? ImageSY($gdimg) : max($y1, $y2); + //while ($y_BR > ImageSY($gdimg)) { + // $y_TL--; + // $y_BR--; + // $text_origin_y--; + //} + ImageFilledRectangle($gdimg, $x_TL, $y_TL, $x_BR, $y_BR, $text_color_background); + ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); + + } + return true; + + } else { + + $size = min(5, max(1, $size)); + $this->DebugMessage('Using built-in font (size='.$size.') for text watermark'.($ttffont ? ' because $ttffont !is_readable('.$ttffont.')' : ''), __FILE__, __LINE__); + + $text_width = 0; + $text_height = 0; + foreach ($textlines as $dummy => $line) { + $text_width = max($text_width, ImageFontWidth($size) * strlen($line)); + $text_height += ImageFontHeight($size); + } + if ($img_watermark = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { + ImageAlphaBlending($img_watermark, false); + if (phpthumb_functions::IsHexColor($bg_color)) { + $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); + $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, $bg_color, false, $text_background_alpha); + } else { + $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, 'FFFFFF', false, 127); + } + ImageFilledRectangle($img_watermark, 0, 0, ImageSX($img_watermark), ImageSY($img_watermark), $text_color_background); + + if ($angle && function_exists('ImageRotate')) { + // using $img_watermark_mask is pointless if ImageRotate function isn't available + if ($img_watermark_mask = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { + $mask_color_background = ImageColorAllocate($img_watermark_mask, 0, 0, 0); + ImageAlphaBlending($img_watermark_mask, false); + ImageFilledRectangle($img_watermark_mask, 0, 0, ImageSX($img_watermark_mask), ImageSY($img_watermark_mask), $mask_color_background); + $mask_color_watermark = ImageColorAllocate($img_watermark_mask, 255, 255, 255); + } + } + + $text_color_watermark = phpthumb_functions::ImageHexColorAllocate($img_watermark, $hex_color); + foreach ($textlines as $key => $line) { + switch ($alignment) { + case 'C': + case 'T': + case 'B': + $x_offset = round(($text_width - (ImageFontWidth($size) * strlen($line))) / 2); + break; + + case 'L': + case 'TL': + case 'BL': + $x_offset = 0; + break; + + case 'R': + case 'TR': + case 'BR': + default: + $x_offset = $text_width - (ImageFontWidth($size) * strlen($line)); + break; + } + ImageString($img_watermark, $size, $x_offset, $key * ImageFontHeight($size), $line, $text_color_watermark); + if ($angle && $img_watermark_mask) { + ImageString($img_watermark_mask, $size, $x_offset, $key * ImageFontHeight($size), $text, $mask_color_watermark); + } + } + if ($angle && $img_watermark_mask) { + $img_watermark = ImageRotate($img_watermark, $angle, $text_color_background); + $img_watermark_mask = ImageRotate($img_watermark_mask, $angle, $mask_color_background); + phpthumb_filters::ApplyMask($img_watermark_mask, $img_watermark); + } + phpthumb_filters::WatermarkOverlay($gdimg, $img_watermark, $alignment, $opacity, $margin); + ImageDestroy($img_watermark); + return true; + } + + } + return false; + } + + + function WatermarkOverlay(&$gdimg_dest, &$img_watermark, $alignment='*', $opacity=50, $margin=5) { + if (is_resource($gdimg_dest) && is_resource($img_watermark)) { + $watermark_source_x = 0; + $watermark_source_y = 0; + $img_source_width = ImageSX($gdimg_dest); + $img_source_height = ImageSY($gdimg_dest); + $watermark_source_width = ImageSX($img_watermark); + $watermark_source_height = ImageSY($img_watermark); + $watermark_opacity_percent = max(0, min(100, $opacity)); + if ($margin < 1) { + $watermark_margin_percent = 1 - $margin; + } else { + $watermark_margin_percent = (100 - max(0, min(100, $margin))) / 100; + } + $watermark_margin_x = round((1 - $watermark_margin_percent) * $img_source_width); + $watermark_margin_y = round((1 - $watermark_margin_percent) * $img_source_height); + switch ($alignment) { + case '*': + if ($gdimg_tiledwatermark = phpthumb_functions::ImageCreateFunction($img_source_width, $img_source_height)) { + + ImageAlphaBlending($gdimg_tiledwatermark, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_tiledwatermark, true); + $text_color_transparent = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_tiledwatermark, 255, 0, 255, 127); + ImageFill($gdimg_tiledwatermark, 0, 0, $text_color_transparent); + + // set the tiled image transparent color to whatever the untiled image transparency index is +// ImageColorTransparent($gdimg_tiledwatermark, ImageColorTransparent($img_watermark)); + + // a "cleaner" way of doing it, but can't handle the margin feature :( +// ImageSetTile($gdimg_tiledwatermark, $img_watermark); +// ImageFill($gdimg_tiledwatermark, 0, 0, IMG_COLOR_TILED); +// break; + +// ImageFill($gdimg_tiledwatermark, 0, 0, ImageColorTransparent($gdimg_tiledwatermark)); + // tile the image as many times as can fit + for ($x = $watermark_margin_x; $x < ($img_source_width + $watermark_source_width); $x += round($watermark_source_width + ((1 - $watermark_margin_percent) * $img_source_width))) { + for ($y = $watermark_margin_y; $y < ($img_source_height + $watermark_source_height); $y += round($watermark_source_height + ((1 - $watermark_margin_percent) * $img_source_height))) { + ImageCopy( + $gdimg_tiledwatermark, + $img_watermark, + $x, + $y, + 0, + 0, + min($watermark_source_width, $img_source_width - $x - ((1 - $watermark_margin_percent) * $img_source_width)), + min($watermark_source_height, $img_source_height - $y - ((1 - $watermark_margin_percent) * $img_source_height)) + ); + } + } + + $watermark_source_width = ImageSX($gdimg_tiledwatermark); + $watermark_source_height = ImageSY($gdimg_tiledwatermark); + $watermark_destination_x = 0; + $watermark_destination_y = 0; + + ImageDestroy($img_watermark); + $img_watermark = $gdimg_tiledwatermark; + } + break; + + case 'T': + $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); + $watermark_destination_y = $watermark_margin_y; + break; + + case 'B': + $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + + case 'L': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); + break; + + case 'R': + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); + break; + + case 'C': + $watermark_destination_x = round(($img_source_width / 2) - ($watermark_source_width / 2)); + $watermark_destination_y = round(($img_source_height / 2) - ($watermark_source_height / 2)); + break; + + case 'TL': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = $watermark_margin_y; + break; + + case 'TR': + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = $watermark_margin_y; + break; + + case 'BL': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + + case 'BR': + default: + $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); + $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); + break; + } + ImageAlphaBlending($gdimg_dest, false); + phpthumb_functions::gd_ImageSaveAlpha($gdimg_dest, true); + phpthumb_functions::gd_ImageSaveAlpha($img_watermark, true); + phpthumb_functions::ImageCopyRespectAlpha($gdimg_dest, $img_watermark, $watermark_destination_x, $watermark_destination_y, 0, 0, $watermark_source_width, $watermark_source_height, $watermark_opacity_percent); + + return true; + } + return false; + } + + + function DebugMessage($message, $file='', $line='') { + if (is_object($this->phpThumbObject)) { + return $this->phpThumbObject->DebugMessage($message, $file, $line); + } + return false; + } +} + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/phpthumb.functions.php b/site/runshops/phpthumb/phpthumb.functions.php new file mode 100644 index 0000000..9e29609 --- /dev/null +++ b/site/runshops/phpthumb/phpthumb.functions.php @@ -0,0 +1,707 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.functions.php - general support functions // +// /// +////////////////////////////////////////////////////////////// + +class phpthumb_functions { + + function user_function_exists($functionname) { + if (function_exists('get_defined_functions')) { + static $get_defined_functions = array(); + if (empty($get_defined_functions)) { + $get_defined_functions = get_defined_functions(); + } + return in_array(strtolower($functionname), $get_defined_functions['user']); + } + return function_exists($functionname); + } + + + function builtin_function_exists($functionname) { + if (function_exists('get_defined_functions')) { + static $get_defined_functions = array(); + if (empty($get_defined_functions)) { + $get_defined_functions = get_defined_functions(); + } + return in_array(strtolower($functionname), $get_defined_functions['internal']); + } + return function_exists($functionname); + } + + + function version_compare_replacement_sub($version1, $version2, $operator='') { + // If you specify the third optional operator argument, you can test for a particular relationship. + // The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively. + // Using this argument, the function will return 1 if the relationship is the one specified by the operator, 0 otherwise. + + // If a part contains special version strings these are handled in the following order: dev < (alpha = a) < (beta = b) < RC < pl + static $versiontype_lookup = array(); + if (empty($versiontype_lookup)) { + $versiontype_lookup['dev'] = 10001; + $versiontype_lookup['a'] = 10002; + $versiontype_lookup['alpha'] = 10002; + $versiontype_lookup['b'] = 10003; + $versiontype_lookup['beta'] = 10003; + $versiontype_lookup['RC'] = 10004; + $versiontype_lookup['pl'] = 10005; + } + if (isset($versiontype_lookup[$version1])) { + $version1 = $versiontype_lookup[$version1]; + } + if (isset($versiontype_lookup[$version2])) { + $version2 = $versiontype_lookup[$version2]; + } + + switch ($operator) { + case '<': + case 'lt': + return intval($version1 < $version2); + break; + case '<=': + case 'le': + return intval($version1 <= $version2); + break; + case '>': + case 'gt': + return intval($version1 > $version2); + break; + case '>=': + case 'ge': + return intval($version1 >= $version2); + break; + case '==': + case '=': + case 'eq': + return intval($version1 == $version2); + break; + case '!=': + case '<>': + case 'ne': + return intval($version1 != $version2); + break; + } + if ($version1 == $version2) { + return 0; + } elseif ($version1 < $version2) { + return -1; + } + return 1; + } + + + function version_compare_replacement($version1, $version2, $operator='') { + if (function_exists('version_compare')) { + // built into PHP v4.1.0+ + return version_compare($version1, $version2, $operator); + } + + // The function first replaces _, - and + with a dot . in the version strings + $version1 = strtr($version1, '_-+', '...'); + $version2 = strtr($version2, '_-+', '...'); + + // and also inserts dots . before and after any non number so that for example '4.3.2RC1' becomes '4.3.2.RC.1'. + // Then it splits the results like if you were using explode('.',$ver). Then it compares the parts starting from left to right. + $version1 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version1); + $version2 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version2); + + $parts1 = explode('.', $version1); + $parts2 = explode('.', $version1); + $parts_count = max(count($parts1), count($parts2)); + for ($i = 0; $i < $parts_count; $i++) { + $comparison = phpthumb_functions::version_compare_replacement_sub($version1, $version2, $operator); + if ($comparison != 0) { + return $comparison; + } + } + return 0; + } + + + function phpinfo_array() { + static $phpinfo_array = array(); + if (empty($phpinfo_array)) { + ob_start(); + phpinfo(); + $phpinfo = ob_get_contents(); + ob_end_clean(); + $phpinfo_array = explode("\n", $phpinfo); + } + return $phpinfo_array; + } + + + function exif_info() { + static $exif_info = array(); + if (empty($exif_info)) { + // based on code by johnschaefer at gmx dot de + // from PHP help on gd_info() + $exif_info = array( + 'EXIF Support' => '', + 'EXIF Version' => '', + 'Supported EXIF Version' => '', + 'Supported filetypes' => '' + ); + $phpinfo_array = phpthumb_functions::phpinfo_array(); + foreach ($phpinfo_array as $dummy => $line) { + $line = trim(strip_tags($line)); + foreach ($exif_info as $key => $value) { + if (strpos($line, $key) === 0) { + $newvalue = trim(str_replace($key, '', $line)); + $exif_info[$key] = $newvalue; + } + } + } + } + return $exif_info; + } + + + function ImageTypeToMIMEtype($imagetype) { + if (function_exists('image_type_to_mime_type') && ($imagetype >= 1) && ($imagetype <= 16)) { + // PHP v4.3.0+ + return image_type_to_mime_type($imagetype); + } + static $image_type_to_mime_type = array( + 1 => 'image/gif', // IMAGETYPE_GIF + 2 => 'image/jpeg', // IMAGETYPE_JPEG + 3 => 'image/png', // IMAGETYPE_PNG + 4 => 'application/x-shockwave-flash', // IMAGETYPE_SWF + 5 => 'image/psd', // IMAGETYPE_PSD + 6 => 'image/bmp', // IMAGETYPE_BMP + 7 => 'image/tiff', // IMAGETYPE_TIFF_II (intel byte order) + 8 => 'image/tiff', // IMAGETYPE_TIFF_MM (motorola byte order) + 9 => 'application/octet-stream', // IMAGETYPE_JPC + 10 => 'image/jp2', // IMAGETYPE_JP2 + 11 => 'application/octet-stream', // IMAGETYPE_JPX + 12 => 'application/octet-stream', // IMAGETYPE_JB2 + 13 => 'application/x-shockwave-flash', // IMAGETYPE_SWC + 14 => 'image/iff', // IMAGETYPE_IFF + 15 => 'image/vnd.wap.wbmp', // IMAGETYPE_WBMP + 16 => 'image/xbm', // IMAGETYPE_XBM + + 'gif' => 'image/gif', // IMAGETYPE_GIF + 'jpg' => 'image/jpeg', // IMAGETYPE_JPEG + 'jpeg' => 'image/jpeg', // IMAGETYPE_JPEG + 'png' => 'image/png', // IMAGETYPE_PNG + 'bmp' => 'image/bmp', // IMAGETYPE_BMP + 'ico' => 'image/x-icon', + ); + + return (isset($image_type_to_mime_type[$imagetype]) ? $image_type_to_mime_type[$imagetype] : false); + } + + + function HexCharDisplay($string) { + $len = strlen($string); + $output = ''; + for ($i = 0; $i < $len; $i++) { + $output .= ' 0x'.str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT); + } + return $output; + } + + + function IsHexColor($HexColorString) { + return eregi('^[0-9A-F]{6}$', $HexColorString); + } + + + function ImageColorAllocateAlphaSafe(&$gdimg_hexcolorallocate, $R, $G, $B, $alpha=false) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && ($alpha !== false)) { + return ImageColorAllocateAlpha($gdimg_hexcolorallocate, $R, $G, $B, intval($alpha)); + } else { + return ImageColorAllocate($gdimg_hexcolorallocate, $R, $G, $B); + } + } + + function ImageHexColorAllocate(&$gdimg_hexcolorallocate, $HexColorString, $dieOnInvalid=false, $alpha=false) { + if (!is_resource($gdimg_hexcolorallocate)) { + die('$gdimg_hexcolorallocate is not a GD resource in ImageHexColorAllocate()'); + } + if (phpthumb_functions::IsHexColor($HexColorString)) { + $R = hexdec(substr($HexColorString, 0, 2)); + $G = hexdec(substr($HexColorString, 2, 2)); + $B = hexdec(substr($HexColorString, 4, 2)); + return phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_hexcolorallocate, $R, $G, $B, $alpha); + } + if ($dieOnInvalid) { + die('Invalid hex color string: "'.$HexColorString.'"'); + } + return ImageColorAllocate($gdimg_hexcolorallocate, 0x00, 0x00, 0x00); + } + + + function HexColorXOR($hexcolor) { + return strtoupper(str_pad(dechex(~hexdec($hexcolor) & 0xFFFFFF), 6, '0', STR_PAD_LEFT)); + } + + + function GetPixelColor(&$img, $x, $y) { + if (!is_resource($img)) { + return false; + } + return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y)); + } + + + function GrayscaleValue($r, $g, $b) { + return round(($r * 0.30) + ($g * 0.59) + ($b * 0.11)); + } + + + function GrayscalePixel($OriginalPixel) { + $gray = phpthumb_functions::GrayscaleValue($OriginalPixel['red'], $OriginalPixel['green'], $OriginalPixel['blue']); + return array('red'=>$gray, 'green'=>$gray, 'blue'=>$gray); + } + + + function GrayscalePixelRGB($rgb) { + $r = ($rgb >> 16) & 0xFF; + $g = ($rgb >> 8) & 0xFF; + $b = $rgb & 0xFF; + return ($r * 0.299) + ($g * 0.587) + ($b * 0.114); + } + + + function ImageCopyResampleBicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) { + // ron at korving dot demon dot nl + // http://www.php.net/imagecopyresampled + + $scaleX = ($src_w - 1) / $dst_w; + $scaleY = ($src_h - 1) / $dst_h; + + $scaleX2 = $scaleX / 2.0; + $scaleY2 = $scaleY / 2.0; + + $isTrueColor = ImageIsTrueColor($src_img); + + for ($y = $src_y; $y < $src_y + $dst_h; $y++) { + $sY = $y * $scaleY; + $siY = (int) $sY; + $siY2 = (int) $sY + $scaleY2; + + for ($x = $src_x; $x < $src_x + $dst_w; $x++) { + $sX = $x * $scaleX; + $siX = (int) $sX; + $siX2 = (int) $sX + $scaleX2; + + if ($isTrueColor) { + + $c1 = ImageColorAt($src_img, $siX, $siY2); + $c2 = ImageColorAt($src_img, $siX, $siY); + $c3 = ImageColorAt($src_img, $siX2, $siY2); + $c4 = ImageColorAt($src_img, $siX2, $siY); + + $r = (( $c1 + $c2 + $c3 + $c4 ) >> 2) & 0xFF0000; + $g = ((($c1 & 0x00FF00) + ($c2 & 0x00FF00) + ($c3 & 0x00FF00) + ($c4 & 0x00FF00)) >> 2) & 0x00FF00; + $b = ((($c1 & 0x0000FF) + ($c2 & 0x0000FF) + ($c3 & 0x0000FF) + ($c4 & 0x0000FF)) >> 2); + + } else { + + $c1 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY2)); + $c2 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY)); + $c3 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY2)); + $c4 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY)); + + $r = ($c1['red'] + $c2['red'] + $c3['red'] + $c4['red'] ) << 14; + $g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6; + $b = ($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue'] ) >> 2; + + } + ImageSetPixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r+$g+$b); + } + } + return true; + } + + + function ImageCreateFunction($x_size, $y_size) { + $ImageCreateFunction = 'ImageCreate'; + if (phpthumb_functions::gd_version() >= 2.0) { + $ImageCreateFunction = 'ImageCreateTrueColor'; + } + if (!function_exists($ImageCreateFunction)) { + return phpthumb::ErrorImage($ImageCreateFunction.'() does not exist - no GD support?'); + } + if (($x_size <= 0) || ($y_size <= 0)) { + return phpthumb::ErrorImage('Invalid image dimensions: '.$ImageCreateFunction.'('.$x_size.', '.$y_size.')'); + } + return $ImageCreateFunction($x_size, $y_size); + } + + + function ImageCopyRespectAlpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct=100) { + for ($x = $src_x; $x < $src_w; $x++) { + for ($y = $src_y; $y < $src_h; $y++) { + $RealPixel = phpthumb_functions::GetPixelColor($dst_im, $dst_x + $x, $dst_y + $y); + $OverlayPixel = phpthumb_functions::GetPixelColor($src_im, $x, $y); + $alphapct = $OverlayPixel['alpha'] / 127; + $opacipct = $pct / 100; + $overlaypct = (1 - $alphapct) * $opacipct; + + $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe( + $dst_im, + round($RealPixel['red'] * (1 - $overlaypct)) + ($OverlayPixel['red'] * $overlaypct), + round($RealPixel['green'] * (1 - $overlaypct)) + ($OverlayPixel['green'] * $overlaypct), + round($RealPixel['blue'] * (1 - $overlaypct)) + ($OverlayPixel['blue'] * $overlaypct), + //$RealPixel['alpha']); + 0); + + ImageSetPixel($dst_im, $dst_x + $x, $dst_y + $y, $newcolor); + } + } + return true; + } + + + function ProportionalResize($old_width, $old_height, $new_width=false, $new_height=false) { + $old_aspect_ratio = $old_width / $old_height; + if (($new_width === false) && ($new_height === false)) { + return false; + } elseif ($new_width === false) { + $new_width = $new_height * $old_aspect_ratio; + } elseif ($new_height === false) { + $new_height = $new_width / $old_aspect_ratio; + } + $new_aspect_ratio = $new_width / $new_height; + if ($new_aspect_ratio == $old_aspect_ratio) { + // great, done + } elseif ($new_aspect_ratio < $old_aspect_ratio) { + // limited by width + $new_height = $new_width / $old_aspect_ratio; + } elseif ($new_aspect_ratio > $old_aspect_ratio) { + // limited by height + $new_width = $new_height * $old_aspect_ratio; + } + return array(round($new_width), round($new_height)); + } + + + function SafeExec($command) { + static $AllowedExecFunctions = array(); + if (empty($AllowedExecFunctions)) { + $AllowedExecFunctions = array('shell_exec'=>true, 'passthru'=>true, 'system'=>true, 'exec'=>true); + if (@ini_get('safe_mode')) { + $AllowedExecFunctions['shell_exec'] = false; + } + $disable_functions = explode(',', @ini_get('disable_functions')); + foreach ($AllowedExecFunctions as $key => $value) { + if (in_array($key, $disable_functions)) { + $AllowedExecFunctions[$key] = false; + } + } + } + foreach ($AllowedExecFunctions as $execfunction => $is_allowed) { + if (!$is_allowed) { + continue; + } + if ($execfunction == 'passthru') { + ob_start(); + $execfunction($command); + $returnvalue = ob_get_contents(); + ob_end_clean(); + } else { + $returnvalue = @$execfunction($command); + } + return $returnvalue; + } + return false; + } + + + function ApacheLookupURIarray($filename) { + // apache_lookup_uri() only works when PHP is installed as an Apache module. + if (php_sapi_name() == 'apache') { + $keys = array('status', 'the_request', 'status_line', 'method', 'content_type', 'handler', 'uri', 'filename', 'path_info', 'args', 'boundary', 'no_cache', 'no_local_copy', 'allowed', 'send_bodyct', 'bytes_sent', 'byterange', 'clength', 'unparsed_uri', 'mtime', 'request_time'); + if ($apacheLookupURIobject = @apache_lookup_uri($filename)) { + $apacheLookupURIarray = array(); + foreach ($keys as $dummy => $key) { + $apacheLookupURIarray[$key] = @$apacheLookupURIobject->$key; + } + return $apacheLookupURIarray; + } + } + return false; + } + + + function gd_is_bundled() { + static $isbundled = null; + if (is_null($isbundled)) { + $gd_info = gd_info(); + $isbundled = (strpos($gd_info['GD Version'], 'bundled') !== false); + } + return $isbundled; + } + + + function gd_version($fullstring=false) { + static $cache_gd_version = array(); + if (empty($cache_gd_version)) { + $gd_info = gd_info(); + if (eregi('bundled \((.+)\)$', $gd_info['GD Version'], $matches)) { + $cache_gd_version[1] = $gd_info['GD Version']; // e.g. "bundled (2.0.15 compatible)" + $cache_gd_version[0] = (float) $matches[1]; // e.g. "2.0" (not "bundled (2.0.15 compatible)") + } else { + $cache_gd_version[1] = $gd_info['GD Version']; // e.g. "1.6.2 or higher" + $cache_gd_version[0] = (float) substr($gd_info['GD Version'], 0, 3); // e.g. "1.6" (not "1.6.2 or higher") + } + } + return $cache_gd_version[intval($fullstring)]; + } + + + function gd_ImageSaveAlpha(&$img, $flag) { + // requires PHP >= 4.3.2 + // requires GD >= 2.0.1 + if (function_exists('ImageSaveAlpha')) { + return ImageSaveAlpha($img, $flag); + } + return false; + } + + function filesize_remote($remotefile, $timeout=10) { + $size = false; + $url = parse_url($remotefile); + if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) { + fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n"); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + stream_set_timeout($fp, $timeout); + } + while (!feof($fp)) { + $headerline = fgets($fp, 4096); + if (eregi('^Content-Length: (.*)', $headerline, $matches)) { + $size = intval($matches[1]); + break; + } + } + fclose ($fp); + } + return $size; + } + + + function filedate_remote($remotefile, $timeout=10) { + $date = false; + $url = parse_url($remotefile); + if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) { + fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n"); + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + stream_set_timeout($fp, $timeout); + } + while (!feof($fp)) { + $headerline = fgets($fp, 4096); + if (eregi('^Last-Modified: (.*)', $headerline, $matches)) { + $date = strtotime($matches[1]) - date('Z'); + break; + } + } + fclose ($fp); + } + return $date; + } + + + function md5_file_safe($filename) { + // md5_file() doesn't exist in PHP < 4.2.0 + if (function_exists('md5_file')) { + return md5_file($filename); + } + if ($fp = @fopen($filename, 'rb')) { + $filedata = fread($fp, filesize($filename)); + fclose($fp); + return md5($filedata); + } + return false; + } + + + function nonempty_min() { + $arg_list = func_get_args(); + $acceptable = array(); + foreach ($arg_list as $dummy => $arg) { + if ($arg) { + $acceptable[] = $arg; + } + } + return min($acceptable); + } + + + function LittleEndian2String($number, $minbytes=1) { + $intstring = ''; + while ($number > 0) { + $intstring = $intstring.chr($number & 255); + $number >>= 8; + } + return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT); + } + + function OneOfThese() { + // return the first useful (non-empty/non-zero/non-false) value from those passed + $arg_list = func_get_args(); + foreach ($arg_list as $key => $value) { + if ($value) { + return $value; + } + } + return false; + } + + function SafeURLread($url, &$error) { + if (function_exists('curl_version')) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); + $rawData = curl_exec($ch); + curl_close($ch); + if (strlen($rawData) > 0) { + return $rawData; + } + $error .= 'CURL available but returned no data; '; + } else { + $error .= 'CURL unavailable; '; + } + if (@ini_get('allow_url_fopen')) { + $rawData = ''; + ob_start(); + if ($fp = fopen($url, 'rb')) { + do { + $buffer = fread($fp, 8192); + $rawData .= $buffer; + } while (strlen($buffer) > 0); + fclose($fp); + } else { + $error = trim(strip_tags(ob_get_contents())); + } + ob_end_clean(); + if (!$error) { + return $rawData; + } + $error .= '; "allow_url_fopen" enabled but returned no data; '; + } else { + $error .= '"allow_url_fopen" disabled; '; + } + return false; + } + +} + + +if (!function_exists('gd_info')) { + // built into PHP v4.3.0+ (with bundled GD2 library) + function gd_info() { + static $gd_info = array(); + if (empty($gd_info)) { + // based on code by johnschaefer at gmx dot de + // from PHP help on gd_info() + $gd_info = array( + 'GD Version' => '', + 'FreeType Support' => false, + 'FreeType Linkage' => '', + 'T1Lib Support' => false, + 'GIF Read Support' => false, + 'GIF Create Support' => false, + 'JPG Support' => false, + 'PNG Support' => false, + 'WBMP Support' => false, + 'XBM Support' => false + ); + $phpinfo_array = phpthumb_functions::phpinfo_array(); + foreach ($phpinfo_array as $dummy => $line) { + $line = trim(strip_tags($line)); + foreach ($gd_info as $key => $value) { + //if (strpos($line, $key) !== false) { + if (strpos($line, $key) === 0) { + $newvalue = trim(str_replace($key, '', $line)); + $gd_info[$key] = $newvalue; + } + } + } + if (empty($gd_info['GD Version'])) { + // probable cause: "phpinfo() disabled for security reasons" + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_PNG) { + $gd_info['PNG Support'] = true; + } + if ($imagetypes & IMG_GIF) { + $gd_info['GIF Create Support'] = true; + } + if ($imagetypes & IMG_JPG) { + $gd_info['JPG Support'] = true; + } + if ($imagetypes & IMG_WBMP) { + $gd_info['WBMP Support'] = true; + } + } + // to determine capability of GIF creation, try to use ImageCreateFromGIF on a 1px GIF + if (function_exists('ImageCreateFromGIF')) { + if ($tempfilename = phpthumb::phpThumb_tempnam()) { + if ($fp_tempfile = @fopen($tempfilename, 'wb')) { + fwrite($fp_tempfile, base64_decode('R0lGODlhAQABAIAAAH//AP///ywAAAAAAQABAAACAUQAOw==')); // very simple 1px GIF file base64-encoded as string + fclose($fp_tempfile); + + // if we can convert the GIF file to a GD image then GIF create support must be enabled, otherwise it's not + $gd_info['GIF Read Support'] = (bool) @ImageCreateFromGIF($tempfilename); + } + unlink($tempfilename); + } + } + if (function_exists('ImageCreateTrueColor') && @ImageCreateTrueColor(1, 1)) { + $gd_info['GD Version'] = '2.0.1 or higher (assumed)'; + } elseif (function_exists('ImageCreate') && @ImageCreate(1, 1)) { + $gd_info['GD Version'] = '1.6.0 or higher (assumed)'; + } + } + } + return $gd_info; + } +} + + +if (!function_exists('is_executable')) { + // in PHP v3+, but v5.0+ for Windows + function is_executable($filename) { + // poor substitute, but better than nothing + return file_exists($filename); + } +} + + +if (!function_exists('file_get_contents')) { + // included in PHP v4.3.0+ + function file_get_contents($filename) { + if (eregi('^(f|ht)tp\://', $filename)) { + return SafeURLread($filename); + } + if ($fp = @fopen($filename, 'rb')) { + $buffer = fread($fp, filesize($filename)); + fclose($fp); + return $buffer; + } + return false; + } +} + + +if (!function_exists('file_put_contents')) { + // included in PHP v5.0.0+ + function file_put_contents($filename, $filedata) { + if ($fp = @fopen($filename, 'wb')) { + fwrite($fp, $filedata); + fclose($fp); + return true; + } + return false; + } +} + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/phpthumb.gif.php b/site/runshops/phpthumb/phpthumb.gif.php new file mode 100644 index 0000000..e928594 --- /dev/null +++ b/site/runshops/phpthumb/phpthumb.gif.php @@ -0,0 +1,1168 @@ + = gif_loadFile(filename, [index]) +// = gif_getSize( or filename, &width, &height) +// = gif_outputAsPng(, filename, [bgColor]) +// = gif_outputAsBmp(, filename, [bgcolor]) +// = gif_outputAsJpeg(, filename, [bgcolor]) - use cjpeg if available otherwise uses GD +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Original code by Fabien Ezber +// Modified by James Heinrich for use in phpThumb() - December 10, 2003 +// * Added function gif_loadFileToGDimageResource() - this returns a GD image resource +// * Modified gif_outputAsJpeg() to check if it's running under Windows, or if cjpeg is not +// available, in which case it will attempt to output JPEG using GD functions +// * added @ error-suppression to two lines where it checks: if ($this->m_img->m_bTrans) +// otherwise warnings are generated if error_reporting == E_ALL +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_loadFile($lpszFileName, $iIndex = 0) +{ + $gif = new CGIF(); + if ($gif->loadFile($lpszFileName, $iIndex)) { + return $gif; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// Added by James Heinrich - December 10, 2003 +function gif_loadFileToGDimageResource($gifFilename, $bgColor = -1) +{ + if ($gif = gif_loadFile($gifFilename)) { + + @set_time_limit(300); + // general strategy: convert raw data to PNG then convert PNG data to GD image resource + $PNGdata = $gif->getPng($bgColor); + if ($img = @ImageCreateFromString($PNGdata)) { + + // excellent - PNG image data successfully converted to GD image + return $img; + + } elseif ($img = $gif->getGD_PixelPlotterVersion()) { + + // problem: ImageCreateFromString() didn't like the PNG image data. + // This has been known to happen in PHP v4.0.6 + // solution: take the raw image data and create a new GD image and plot + // pixel-by-pixel on the GD image. This is extremely slow, but it does + // work and a slow solution is better than no solution, right? :) + return $img; + + } + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsBmp($gif, $lpszFileName, $bgColor = -1) +{ + if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) { + return false; + } + + $fd = $gif->getBmp($bgColor); + if (strlen($fd) <= 0) { + return false; + } + + if (!($fh = @fopen($lpszFileName, 'wb'))) { + return false; + } + @fwrite($fh, $fd, strlen($fd)); + @fflush($fh); + @fclose($fh); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsPng($gif, $lpszFileName, $bgColor = -1) +{ + if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) { + return false; + } + + $fd = $gif->getPng($bgColor); + if (strlen($fd) <= 0) { + return false; + } + + if (!($fh = @fopen($lpszFileName, 'wb'))) { + return false; + } + @fwrite($fh, $fd, strlen($fd)); + @fflush($fh); + @fclose($fh); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_outputAsJpeg($gif, $lpszFileName, $bgColor = -1) +{ + // JPEG output that does not require cjpeg added by James Heinrich - December 10, 2003 + if ((strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') && (file_exists('/usr/local/bin/cjpeg') || `which cjpeg`)) { + + if (gif_outputAsBmp($gif, $lpszFileName.'.bmp', $bgColor)) { + exec('cjpeg '.$lpszFileName.'.bmp >'.$lpszFileName.' 2>/dev/null'); + @unLink($lpszFileName.'.bmp'); + + if (@file_exists($lpszFileName)) { + if (@fileSize($lpszFileName) > 0) { + return true; + } + + @unLink($lpszFileName); + } + } + + } else { + + // either Windows, or cjpeg not found in path + if ($img = @ImageCreateFromString($gif->getPng($bgColor))) { + if (@ImageJPEG($img, $lpszFileName)) { + return true; + } + } + + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +function gif_getSize($gif, &$width, &$height) +{ + if (isSet($gif) && (@get_class($gif) == 'cgif') && $gif->loaded()) { + $width = $gif->width(); + $height = $gif->height(); + } elseif (@file_exists($gif)) { + $myGIF = new CGIF(); + if (!$myGIF->getSize($gif, $width, $height)) { + return false; + } + } else { + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFLZW +{ + var $MAX_LZW_BITS; + var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode; + var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFLZW() + { + $this->MAX_LZW_BITS = 12; + unSet($this->Next); + unSet($this->Vals); + unSet($this->Stack); + unSet($this->Buf); + + $this->Next = range(0, (1 << $this->MAX_LZW_BITS) - 1); + $this->Vals = range(0, (1 << $this->MAX_LZW_BITS) - 1); + $this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1); + $this->Buf = range(0, 279); + } + + /////////////////////////////////////////////////////////////////////////// + + function deCompress($data, &$datLen) + { + $stLen = strlen($data); + $datLen = 0; + $ret = ''; + + // INITIALIZATION + $this->LZWCommand($data, true); + + while (($iIndex = $this->LZWCommand($data, false)) >= 0) { + $ret .= chr($iIndex); + } + + $datLen = $stLen - strlen($data); + + if ($iIndex != -2) { + return false; + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function LZWCommand(&$data, $bInit) + { + if ($bInit) { + $this->SetCodeSize = ord($data{0}); + $data = substr($data, 1); + + $this->CodeSize = $this->SetCodeSize + 1; + $this->ClearCode = 1 << $this->SetCodeSize; + $this->EndCode = $this->ClearCode + 1; + $this->MaxCode = $this->ClearCode + 2; + $this->MaxCodeSize = $this->ClearCode << 1; + + $this->GetCode($data, $bInit); + + $this->Fresh = 1; + for ($i = 0; $i < $this->ClearCode; $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = $i; + } + + for (; $i < (1 << $this->MAX_LZW_BITS); $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = 0; + } + + $this->sp = 0; + return 1; + } + + if ($this->Fresh) { + $this->Fresh = 0; + do { + $this->FirstCode = $this->GetCode($data, $bInit); + $this->OldCode = $this->FirstCode; + } + while ($this->FirstCode == $this->ClearCode); + + return $this->FirstCode; + } + + if ($this->sp > 0) { + $this->sp--; + return $this->Stack[$this->sp]; + } + + while (($Code = $this->GetCode($data, $bInit)) >= 0) { + if ($Code == $this->ClearCode) { + for ($i = 0; $i < $this->ClearCode; $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = $i; + } + + for (; $i < (1 << $this->MAX_LZW_BITS); $i++) { + $this->Next[$i] = 0; + $this->Vals[$i] = 0; + } + + $this->CodeSize = $this->SetCodeSize + 1; + $this->MaxCodeSize = $this->ClearCode << 1; + $this->MaxCode = $this->ClearCode + 2; + $this->sp = 0; + $this->FirstCode = $this->GetCode($data, $bInit); + $this->OldCode = $this->FirstCode; + + return $this->FirstCode; + } + + if ($Code == $this->EndCode) { + return -2; + } + + $InCode = $Code; + if ($Code >= $this->MaxCode) { + $this->Stack[$this->sp] = $this->FirstCode; + $this->sp++; + $Code = $this->OldCode; + } + + while ($Code >= $this->ClearCode) { + $this->Stack[$this->sp] = $this->Vals[$Code]; + $this->sp++; + + if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error! + return -1; + + $Code = $this->Next[$Code]; + } + + $this->FirstCode = $this->Vals[$Code]; + $this->Stack[$this->sp] = $this->FirstCode; + $this->sp++; + + if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) { + $this->Next[$Code] = $this->OldCode; + $this->Vals[$Code] = $this->FirstCode; + $this->MaxCode++; + + if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) { + $this->MaxCodeSize *= 2; + $this->CodeSize++; + } + } + + $this->OldCode = $InCode; + if ($this->sp > 0) { + $this->sp--; + return $this->Stack[$this->sp]; + } + } + + return $Code; + } + + /////////////////////////////////////////////////////////////////////////// + + function GetCode(&$data, $bInit) + { + if ($bInit) { + $this->CurBit = 0; + $this->LastBit = 0; + $this->Done = 0; + $this->LastByte = 2; + return 1; + } + + if (($this->CurBit + $this->CodeSize) >= $this->LastBit) { + if ($this->Done) { + if ($this->CurBit >= $this->LastBit) { + // Ran off the end of my bits + return 0; + } + return -1; + } + + $this->Buf[0] = $this->Buf[$this->LastByte - 2]; + $this->Buf[1] = $this->Buf[$this->LastByte - 1]; + + $Count = ord($data{0}); + $data = substr($data, 1); + + if ($Count) { + for ($i = 0; $i < $Count; $i++) { + $this->Buf[2 + $i] = ord($data{$i}); + } + $data = substr($data, $Count); + } else { + $this->Done = 1; + } + + $this->LastByte = 2 + $Count; + $this->CurBit = ($this->CurBit - $this->LastBit) + 16; + $this->LastBit = (2 + $Count) << 3; + } + + $iRet = 0; + for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) { + $iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j; + } + + $this->CurBit += $this->CodeSize; + return $iRet; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFCOLORTABLE +{ + var $m_nColors; + var $m_arColors; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFCOLORTABLE() + { + unSet($this->m_nColors); + unSet($this->m_arColors); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, $num) + { + $this->m_nColors = 0; + $this->m_arColors = array(); + + for ($i = 0; $i < $num; $i++) { + $rgb = substr($lpData, $i * 3, 3); + if (strlen($rgb) < 3) { + return false; + } + + $this->m_arColors[] = (ord($rgb{2}) << 16) + (ord($rgb{1}) << 8) + ord($rgb{0}); + $this->m_nColors++; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function toString() + { + $ret = ''; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $ret .= + chr(($this->m_arColors[$i] & 0x000000FF)) . // R + chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G + chr(($this->m_arColors[$i] & 0x00FF0000) >> 16); // B + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function toRGBQuad() + { + $ret = ''; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $ret .= + chr(($this->m_arColors[$i] & 0x00FF0000) >> 16) . // B + chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G + chr(($this->m_arColors[$i] & 0x000000FF)) . // R + "\x00"; + } + + return $ret; + } + + /////////////////////////////////////////////////////////////////////////// + + function colorIndex($rgb) + { + $rgb = intval($rgb) & 0xFFFFFF; + $r1 = ($rgb & 0x0000FF); + $g1 = ($rgb & 0x00FF00) >> 8; + $b1 = ($rgb & 0xFF0000) >> 16; + $idx = -1; + + for ($i = 0; $i < $this->m_nColors; $i++) { + $r2 = ($this->m_arColors[$i] & 0x000000FF); + $g2 = ($this->m_arColors[$i] & 0x0000FF00) >> 8; + $b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16; + $d = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1); + + if (($idx == -1) || ($d < $dif)) { + $idx = $i; + $dif = $d; + } + } + + return $idx; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFFILEHEADER +{ + var $m_lpVer; + var $m_nWidth; + var $m_nHeight; + var $m_bGlobalClr; + var $m_nColorRes; + var $m_bSorted; + var $m_nTableSize; + var $m_nBgColor; + var $m_nPixelRatio; + var $m_colorTable; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFFILEHEADER() + { + unSet($this->m_lpVer); + unSet($this->m_nWidth); + unSet($this->m_nHeight); + unSet($this->m_bGlobalClr); + unSet($this->m_nColorRes); + unSet($this->m_bSorted); + unSet($this->m_nTableSize); + unSet($this->m_nBgColor); + unSet($this->m_nPixelRatio); + unSet($this->m_colorTable); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, &$hdrLen) + { + $hdrLen = 0; + + $this->m_lpVer = substr($lpData, 0, 6); + if (($this->m_lpVer <> 'GIF87a') && ($this->m_lpVer <> 'GIF89a')) { + return false; + } + + $this->m_nWidth = $this->w2i(substr($lpData, 6, 2)); + $this->m_nHeight = $this->w2i(substr($lpData, 8, 2)); + if (!$this->m_nWidth || !$this->m_nHeight) { + return false; + } + + $b = ord(substr($lpData, 10, 1)); + $this->m_bGlobalClr = ($b & 0x80) ? true : false; + $this->m_nColorRes = ($b & 0x70) >> 4; + $this->m_bSorted = ($b & 0x08) ? true : false; + $this->m_nTableSize = 2 << ($b & 0x07); + $this->m_nBgColor = ord(substr($lpData, 11, 1)); + $this->m_nPixelRatio = ord(substr($lpData, 12, 1)); + $hdrLen = 13; + + if ($this->m_bGlobalClr) { + $this->m_colorTable = new CGIFCOLORTABLE(); + if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) { + return false; + } + $hdrLen += 3 * $this->m_nTableSize; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFIMAGEHEADER +{ + var $m_nLeft; + var $m_nTop; + var $m_nWidth; + var $m_nHeight; + var $m_bLocalClr; + var $m_bInterlace; + var $m_bSorted; + var $m_nTableSize; + var $m_colorTable; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIFIMAGEHEADER() + { + unSet($this->m_nLeft); + unSet($this->m_nTop); + unSet($this->m_nWidth); + unSet($this->m_nHeight); + unSet($this->m_bLocalClr); + unSet($this->m_bInterlace); + unSet($this->m_bSorted); + unSet($this->m_nTableSize); + unSet($this->m_colorTable); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($lpData, &$hdrLen) + { + $hdrLen = 0; + + $this->m_nLeft = $this->w2i(substr($lpData, 0, 2)); + $this->m_nTop = $this->w2i(substr($lpData, 2, 2)); + $this->m_nWidth = $this->w2i(substr($lpData, 4, 2)); + $this->m_nHeight = $this->w2i(substr($lpData, 6, 2)); + + if (!$this->m_nWidth || !$this->m_nHeight) { + return false; + } + + $b = ord($lpData{8}); + $this->m_bLocalClr = ($b & 0x80) ? true : false; + $this->m_bInterlace = ($b & 0x40) ? true : false; + $this->m_bSorted = ($b & 0x20) ? true : false; + $this->m_nTableSize = 2 << ($b & 0x07); + $hdrLen = 9; + + if ($this->m_bLocalClr) { + $this->m_colorTable = new CGIFCOLORTABLE(); + if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) { + return false; + } + $hdrLen += 3 * $this->m_nTableSize; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIFIMAGE +{ + var $m_disp; + var $m_bUser; + var $m_bTrans; + var $m_nDelay; + var $m_nTrans; + var $m_lpComm; + var $m_gih; + var $m_data; + var $m_lzw; + + /////////////////////////////////////////////////////////////////////////// + + function CGIFIMAGE() + { + unSet($this->m_disp); + unSet($this->m_bUser); + unSet($this->m_bTrans); + unSet($this->m_nDelay); + unSet($this->m_nTrans); + unSet($this->m_lpComm); + unSet($this->m_data); + $this->m_gih = new CGIFIMAGEHEADER(); + $this->m_lzw = new CGIFLZW(); + } + + /////////////////////////////////////////////////////////////////////////// + + function load($data, &$datLen) + { + $datLen = 0; + + while (true) { + $b = ord($data{0}); + $data = substr($data, 1); + $datLen++; + + switch($b) { + case 0x21: // Extension + if (!$this->skipExt($data, $len = 0)) { + return false; + } + $datLen += $len; + break; + + case 0x2C: // Image + // LOAD HEADER & COLOR TABLE + if (!$this->m_gih->load($data, $len = 0)) { + return false; + } + $data = substr($data, $len); + $datLen += $len; + + // ALLOC BUFFER + if (!($this->m_data = $this->m_lzw->deCompress($data, $len = 0))) { + return false; + } + $data = substr($data, $len); + $datLen += $len; + + if ($this->m_gih->m_bInterlace) { + $this->deInterlace(); + } + return true; + + case 0x3B: // EOF + default: + return false; + } + } + return false; + } + + /////////////////////////////////////////////////////////////////////////// + + function skipExt(&$data, &$extLen) + { + $extLen = 0; + + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + + switch($b) { + case 0xF9: // Graphic Control + $b = ord($data{1}); + $this->m_disp = ($b & 0x1C) >> 2; + $this->m_bUser = ($b & 0x02) ? true : false; + $this->m_bTrans = ($b & 0x01) ? true : false; + $this->m_nDelay = $this->w2i(substr($data, 2, 2)); + $this->m_nTrans = ord($data{4}); + break; + + case 0xFE: // Comment + $this->m_lpComm = substr($data, 1, ord($data{0})); + break; + + case 0x01: // Plain text + break; + + case 0xFF: // Application + break; + } + + // SKIP DEFAULT AS DEFS MAY CHANGE + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + while ($b > 0) { + $data = substr($data, $b); + $extLen += $b; + $b = ord($data{0}); + $data = substr($data, 1); + $extLen++; + } + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function w2i($str) + { + return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); + } + + /////////////////////////////////////////////////////////////////////////// + + function deInterlace() + { + $data = $this->m_data; + + for ($i = 0; $i < 4; $i++) { + switch($i) { + case 0: + $s = 8; + $y = 0; + break; + + case 1: + $s = 8; + $y = 4; + break; + + case 2: + $s = 4; + $y = 2; + break; + + case 3: + $s = 2; + $y = 1; + break; + } + + for (; $y < $this->m_gih->m_nHeight; $y += $s) { + $lne = substr($this->m_data, 0, $this->m_gih->m_nWidth); + $this->m_data = substr($this->m_data, $this->m_gih->m_nWidth); + + $data = + substr($data, 0, $y * $this->m_gih->m_nWidth) . + $lne . + substr($data, ($y + 1) * $this->m_gih->m_nWidth); + } + } + + $this->m_data = $data; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class CGIF +{ + var $m_gfh; + var $m_lpData; + var $m_img; + var $m_bLoaded; + + /////////////////////////////////////////////////////////////////////////// + + // CONSTRUCTOR + function CGIF() + { + $this->m_gfh = new CGIFFILEHEADER(); + $this->m_img = new CGIFIMAGE(); + $this->m_lpData = ''; + $this->m_bLoaded = false; + } + + /////////////////////////////////////////////////////////////////////////// + + function loadFile($lpszFileName, $iIndex) + { + if ($iIndex < 0) { + return false; + } + + // READ FILE + if (!($fh = @fopen($lpszFileName, 'rb'))) { + return false; + } + $this->m_lpData = @fRead($fh, @fileSize($lpszFileName)); + fclose($fh); + + // GET FILE HEADER + if (!$this->m_gfh->load($this->m_lpData, $len = 0)) { + return false; + } + $this->m_lpData = substr($this->m_lpData, $len); + + do { + if (!$this->m_img->load($this->m_lpData, $imgLen = 0)) { + return false; + } + $this->m_lpData = substr($this->m_lpData, $imgLen); + } + while ($iIndex-- > 0); + + $this->m_bLoaded = true; + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function getSize($lpszFileName, &$width, &$height) + { + if (!($fh = @fopen($lpszFileName, 'rb'))) { + return false; + } + $data = @fRead($fh, @fileSize($lpszFileName)); + @fclose($fh); + + $gfh = new CGIFFILEHEADER(); + if (!$gfh->load($data, $len = 0)) { + return false; + } + + $width = $gfh->m_nWidth; + $height = $gfh->m_nHeight; + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + function getBmp($bgColor) + { + $out = ''; + + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $nColors = $this->m_img->m_gih->m_nTableSize; + $rgbq = $this->m_img->m_gih->m_colorTable->toRGBQuad(); + if ($bgColor != -1) { + $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor); + } + } elseif ($this->m_gfh->m_bGlobalClr) { + $nColors = $this->m_gfh->m_nTableSize; + $rgbq = $this->m_gfh->m_colorTable->toRGBQuad(); + if ($bgColor != -1) { + $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor); + } + } else { + $nColors = 0; + $bgColor = -1; + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth; + $bmp = ''; + $nPad = ($this->m_gfh->m_nWidth % 4) ? 4 - ($this->m_gfh->m_nWidth % 4) : 0; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) { + // TRANSPARENT -> BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } else { + $bmp .= $data{$nPxl}; + } + } else { + // BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } + } + $nPxl -= $this->m_gfh->m_nWidth << 1; + + // ADD PADDING + for ($x = 0; $x < $nPad; $x++) { + $bmp .= "\x00"; + } + } + + // BITMAPFILEHEADER + $out .= 'BM'; + $out .= $this->dword(14 + 40 + ($nColors << 2) + strlen($bmp)); + $out .= "\x00\x00"; + $out .= "\x00\x00"; + $out .= $this->dword(14 + 40 + ($nColors << 2)); + + // BITMAPINFOHEADER + $out .= $this->dword(40); + $out .= $this->dword($this->m_gfh->m_nWidth); + $out .= $this->dword($this->m_gfh->m_nHeight); + $out .= "\x01\x00"; + $out .= "\x08\x00"; + $out .= "\x00\x00\x00\x00"; + $out .= "\x00\x00\x00\x00"; + $out .= "\x12\x0B\x00\x00"; + $out .= "\x12\x0B\x00\x00"; + $out .= $this->dword($nColors % 256); + $out .= "\x00\x00\x00\x00"; + + // COLOR TABLE + if ($nColors > 0) { + $out .= $rgbq; + } + + // DATA + $out .= $bmp; + + return $out; + } + + /////////////////////////////////////////////////////////////////////////// + + function getPng($bgColor) + { + $out = ''; + + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $nColors = $this->m_img->m_gih->m_nTableSize; + $pal = $this->m_img->m_gih->m_colorTable->toString(); + if ($bgColor != -1) { + $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor); + } + } elseif ($this->m_gfh->m_bGlobalClr) { + $nColors = $this->m_gfh->m_nTableSize; + $pal = $this->m_gfh->m_colorTable->toString(); + if ($bgColor != -1) { + $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor); + } + } else { + $nColors = 0; + $bgColor = -1; + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = 0; + $bmp = ''; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + $bmp .= "\x00"; + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + $bmp .= $data{$nPxl}; + } else { + // BACKGROUND + if ($bgColor == -1) { + $bmp .= chr($this->m_gfh->m_nBgColor); + } else { + $bmp .= chr($bgColor); + } + } + } + } + $bmp = gzcompress($bmp, 9); + + /////////////////////////////////////////////////////////////////////// + // SIGNATURE + $out .= "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; + /////////////////////////////////////////////////////////////////////// + // HEADER + $out .= "\x00\x00\x00\x0D"; + $tmp = 'IHDR'; + $tmp .= $this->ndword($this->m_gfh->m_nWidth); + $tmp .= $this->ndword($this->m_gfh->m_nHeight); + $tmp .= "\x08\x03\x00\x00\x00"; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + /////////////////////////////////////////////////////////////////////// + // PALETTE + if ($nColors > 0) { + $out .= $this->ndword($nColors * 3); + $tmp = 'PLTE'; + $tmp .= $pal; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + } + /////////////////////////////////////////////////////////////////////// + // TRANSPARENCY + if (@$this->m_img->m_bTrans && ($nColors > 0)) { + $out .= $this->ndword($nColors); + $tmp = 'tRNS'; + for ($i = 0; $i < $nColors; $i++) { + $tmp .= ($i == $this->m_img->m_nTrans) ? "\x00" : "\xFF"; + } + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + } + /////////////////////////////////////////////////////////////////////// + // DATA BITS + $out .= $this->ndword(strlen($bmp)); + $tmp = 'IDAT'; + $tmp .= $bmp; + $out .= $tmp; + $out .= $this->ndword(crc32($tmp)); + /////////////////////////////////////////////////////////////////////// + // END OF FILE + $out .= "\x00\x00\x00\x00IEND\xAE\x42\x60\x82"; + + return $out; + } + + /////////////////////////////////////////////////////////////////////////// + + // Added by James Heinrich - January 5, 2003 + + // Takes raw image data and plots it pixel-by-pixel on a new GD image and returns that + // It's extremely slow, but the only solution when ImageCreateFromString() fails + function getGD_PixelPlotterVersion() + { + if (!$this->m_bLoaded) { + return false; + } + + // PREPARE COLOR TABLE (RGBQUADs) + if ($this->m_img->m_gih->m_bLocalClr) { + $pal = $this->m_img->m_gih->m_colorTable->toString(); + } elseif ($this->m_gfh->m_bGlobalClr) { + $pal = $this->m_gfh->m_colorTable->toString(); + } else { + die('No color table available in getGD_PixelPlotterVersion()'); + } + + $PlottingIMG = ImageCreate($this->m_gfh->m_nWidth, $this->m_gfh->m_nHeight); + $NumColorsInPal = floor(strlen($pal) / 3); + for ($i = 0; $i < $NumColorsInPal; $i++) { + $ThisImageColor[$i] = ImageColorAllocate( + $PlottingIMG, + ord($pal{(($i * 3) + 0)}), + ord($pal{(($i * 3) + 1)}), + ord($pal{(($i * 3) + 2)})); + } + + // PREPARE BITMAP BITS + $data = $this->m_img->m_data; + $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth; + for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { + set_time_limit(30); + for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { + if ( + ($x >= $this->m_img->m_gih->m_nLeft) && + ($y >= $this->m_img->m_gih->m_nTop) && + ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && + ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { + // PART OF IMAGE + if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) { + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]); + } else { + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[ord($data{$nPxl})]); + } + } else { + // BACKGROUND + ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]); + } + } + $nPxl -= $this->m_gfh->m_nWidth << 1; + + } + + return $PlottingIMG; + } + + /////////////////////////////////////////////////////////////////////////// + + function dword($val) + { + $val = intval($val); + return chr($val & 0xFF).chr(($val & 0xFF00) >> 8).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF000000) >> 24); + } + + /////////////////////////////////////////////////////////////////////////// + + function ndword($val) + { + $val = intval($val); + return chr(($val & 0xFF000000) >> 24).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF00) >> 8).chr($val & 0xFF); + } + + /////////////////////////////////////////////////////////////////////////// + + function width() + { + return $this->m_gfh->m_nWidth; + } + + /////////////////////////////////////////////////////////////////////////// + + function height() + { + return $this->m_gfh->m_nHeight; + } + + /////////////////////////////////////////////////////////////////////////// + + function comment() + { + return $this->m_img->m_lpComm; + } + + /////////////////////////////////////////////////////////////////////////// + + function loaded() + { + return $this->m_bLoaded; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/phpthumb.ico.php b/site/runshops/phpthumb/phpthumb.ico.php new file mode 100644 index 0000000..aed7214 --- /dev/null +++ b/site/runshops/phpthumb/phpthumb.ico.php @@ -0,0 +1,119 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.ico.php - .ICO output format functions // +// /// +////////////////////////////////////////////////////////////// + + +class phpthumb_ico { + + function phpthumb_ico() { + return true; + } + + + function GD2ICOstring(&$gd_image_array) { + foreach ($gd_image_array as $key => $gd_image) { + + $ImageWidths[$key] = ImageSX($gd_image); + $ImageHeights[$key] = ImageSY($gd_image); + $bpp[$key] = ImageIsTrueColor($gd_image) ? 32 : 24; + $totalcolors[$key] = ImageColorsTotal($gd_image); + + $icXOR[$key] = ''; + for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) { + for ($x = 0; $x < $ImageWidths[$key]; $x++) { + $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); + $a = round(255 * ((127 - $argb['alpha']) / 127)); + $r = $argb['red']; + $g = $argb['green']; + $b = $argb['blue']; + + if ($bpp[$key] == 32) { + $icXOR[$key] .= chr($b).chr($g).chr($r).chr($a); + } elseif ($bpp[$key] == 24) { + $icXOR[$key] .= chr($b).chr($g).chr($r); + } + + if ($a < 128) { + @$icANDmask[$key][$y] .= '1'; + } else { + @$icANDmask[$key][$y] .= '0'; + } + } + // mask bits are 32-bit aligned per scanline + while (strlen($icANDmask[$key][$y]) % 32) { + $icANDmask[$key][$y] .= '0'; + } + } + $icAND[$key] = ''; + foreach ($icANDmask[$key] as $y => $scanlinemaskbits) { + for ($i = 0; $i < strlen($scanlinemaskbits); $i += 8) { + $icAND[$key] .= chr(bindec(str_pad(substr($scanlinemaskbits, $i, 8), 8, '0', STR_PAD_LEFT))); + } + } + + } + + foreach ($gd_image_array as $key => $gd_image) { + $biSizeImage = $ImageWidths[$key] * $ImageHeights[$key] * ($bpp[$key] / 8); + + // BITMAPINFOHEADER - 40 bytes + $BitmapInfoHeader[$key] = ''; + $BitmapInfoHeader[$key] .= "\x28\x00\x00\x00"; // DWORD biSize; + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageWidths[$key], 4); // LONG biWidth; + // The biHeight member specifies the combined + // height of the XOR and AND masks. + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageHeights[$key] * 2, 4); // LONG biHeight; + $BitmapInfoHeader[$key] .= "\x01\x00"; // WORD biPlanes; + $BitmapInfoHeader[$key] .= chr($bpp[$key])."\x00"; // wBitCount; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biCompression; + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($biSizeImage, 4); // DWORD biSizeImage; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biXPelsPerMeter; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biYPelsPerMeter; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrUsed; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrImportant; + } + + + $icondata = "\x00\x00"; // idReserved; // Reserved (must be 0) + $icondata .= "\x01\x00"; // idType; // Resource Type (1 for icons) + $icondata .= phpthumb_functions::LittleEndian2String(count($gd_image_array), 2); // idCount; // How many images? + + $dwImageOffset = 6 + (count($gd_image_array) * 16); + foreach ($gd_image_array as $key => $gd_image) { + // ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) + + $icondata .= chr($ImageWidths[$key]); // bWidth; // Width, in pixels, of the image + $icondata .= chr($ImageHeights[$key]); // bHeight; // Height, in pixels, of the image + $icondata .= chr($totalcolors[$key]); // bColorCount; // Number of colors in image (0 if >=8bpp) + $icondata .= "\x00"; // bReserved; // Reserved ( must be 0) + + $icondata .= "\x01\x00"; // wPlanes; // Color Planes + $icondata .= chr($bpp[$key])."\x00"; // wBitCount; // Bits per pixel + + $dwBytesInRes = 40 + strlen($icXOR[$key]) + strlen($icAND[$key]); + $icondata .= phpthumb_functions::LittleEndian2String($dwBytesInRes, 4); // dwBytesInRes; // How many bytes in this resource? + + $icondata .= phpthumb_functions::LittleEndian2String($dwImageOffset, 4); // dwImageOffset; // Where in the file is this image? + $dwImageOffset += strlen($BitmapInfoHeader[$key]); + $dwImageOffset += strlen($icXOR[$key]); + $dwImageOffset += strlen($icAND[$key]); + } + + foreach ($gd_image_array as $key => $gd_image) { + $icondata .= $BitmapInfoHeader[$key]; + $icondata .= $icXOR[$key]; + $icondata .= $icAND[$key]; + } + + return $icondata; + } + +} + +?> \ No newline at end of file diff --git a/site/runshops/phpthumb/phpthumb.unsharp.php b/site/runshops/phpthumb/phpthumb.unsharp.php new file mode 100644 index 0000000..799b5cd --- /dev/null +++ b/site/runshops/phpthumb/phpthumb.unsharp.php @@ -0,0 +1,162 @@ + // +// for use in phpThumb() on 3 February 2003. // +// // +// phpThumb() is found at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// + +/* +WARNING! Due to a known bug in PHP 4.3.2 this script is not working well in this version. +The sharpened images get too dark. The bug is fixed in version 4.3.3. + +Unsharp masking is a traditional darkroom technique that has proven very suitable for +digital imaging. The principle of unsharp masking is to create a blurred copy of the image +and compare it to the underlying original. The difference in colour values +between the two images is greatest for the pixels near sharp edges. When this +difference is subtracted from the original image, the edges will be +accentuated. + +The Amount parameter simply says how much of the effect you want. 100 is 'normal'. +Radius is the radius of the blurring circle of the mask. 'Threshold' is the least +difference in colour values that is allowed between the original and the mask. In practice +this means that low-contrast areas of the picture are left unrendered whereas edges +are treated normally. This is good for pictures of e.g. skin or blue skies. + +Any suggenstions for improvement of the algorithm, expecially regarding the speed +and the roundoff errors in the Gaussian blur process, are welcome. +*/ + +class phpUnsharpMask { + + function applyUnsharpMask(&$img, $amount, $radius, $threshold) { + + // $img is an image that is already created within php using + // imgcreatetruecolor. No url! $img must be a truecolor image. + + // Attempt to calibrate the parameters to Photoshop: + $amount = min($amount, 500); + $amount = $amount * 0.016; + if ($amount == 0) { + return true; + } + + $radius = min($radius, 50); + $radius = $radius * 2; + + $threshold = min($threshold, 255); + + $radius = abs(round($radius)); // Only integers make sense. + if ($radius == 0) { + return true; + } + + $w = ImageSX($img); + $h = ImageSY($img); + $imgCanvas = ImageCreateTrueColor($w, $h); + $imgCanvas2 = ImageCreateTrueColor($w, $h); + ImageCopy($imgCanvas, $img, 0, 0, 0, 0, $w, $h); + ImageCopy($imgCanvas2, $img, 0, 0, 0, 0, $w, $h); + + + $builtinFilterSucceeded = false; + if ($radius == 1) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($imgCanvas, IMG_FILTER_GAUSSIAN_BLUR) && ImageFilter($imgCanvas2, IMG_FILTER_GAUSSIAN_BLUR)) { + $builtinFilterSucceeded = true; + } + } + } + + if (!$builtinFilterSucceeded) { + $imgBlur = ImageCreateTrueColor($w, $h); + $imgBlur2 = ImageCreateTrueColor($w, $h); + + /////////////////////////// + // + // Gaussian blur matrix: + // 1 2 1 + // 2 4 2 + // 1 2 1 + // + /////////////////////////// + + // Move copies of the image around one pixel at the time and merge them with weight + // according to the matrix. The same matrix is simply repeated for higher radii. + for ($i = 0; $i < $radius; $i++) { + ImageCopy ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left + ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20 ); // up + ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center + ImageCopy ($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h); + + // During the loop above the blurred copy darkens, possibly due to a roundoff + // error. Therefore the sharp picture has to go through the same loop to + // produce a similar image for comparison. This is not a good thing, as processing + // time increases heavily. + ImageCopy ($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 20 ); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 16.666667); + ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); + ImageCopy ($imgCanvas2, $imgBlur2, 0, 0, 0, 0, $w, $h); + } + ImageDestroy($imgBlur); + ImageDestroy($imgBlur2); + } + + // Calculate the difference between the blurred pixels and the original + // and set the pixels + for ($x = 0; $x < $w; $x++) { // each row + for ($y = 0; $y < $h; $y++) { // each pixel + + $rgbOrig = ImageColorAt($imgCanvas2, $x, $y); + $rOrig = (($rgbOrig >> 16) & 0xFF); + $gOrig = (($rgbOrig >> 8) & 0xFF); + $bOrig = ($rgbOrig & 0xFF); + + $rgbBlur = ImageColorAt($imgCanvas, $x, $y); + $rBlur = (($rgbBlur >> 16) & 0xFF); + $gBlur = (($rgbBlur >> 8) & 0xFF); + $bBlur = ($rgbBlur & 0xFF); + + // When the masked pixels differ less from the original + // than the threshold specifies, they are set to their original value. + $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig; + $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig; + $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig; + + if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) { + $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew); + ImageSetPixel($img, $x, $y, $pixCol); + } + } + } + ImageDestroy($imgCanvas); + ImageDestroy($imgCanvas2); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/site/runshops/rating/ajax.rate.item.php b/site/runshops/rating/ajax.rate.item.php new file mode 100644 index 0000000..9b6879b --- /dev/null +++ b/site/runshops/rating/ajax.rate.item.php @@ -0,0 +1,19 @@ + diff --git a/site/runshops/rating/classes/database.class.php b/site/runshops/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/runshops/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/runshops/rating/classes/error.class.php b/site/runshops/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/runshops/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Error Template Output + $output = "
    \r\n" . + "
    {$error}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Warning Template Output + $output = "
    \r\n" . + "
    {$warning}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/runshops/rating/classes/include.all.php b/site/runshops/rating/classes/include.all.php new file mode 100644 index 0000000..2c1fa21 --- /dev/null +++ b/site/runshops/rating/classes/include.all.php @@ -0,0 +1,7 @@ + diff --git a/site/runshops/rating/classes/rating.class.php b/site/runshops/rating/classes/rating.class.php new file mode 100644 index 0000000..7fb2dbf --- /dev/null +++ b/site/runshops/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +
    {$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
    {$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
    Overall Rating
    "; + $output .= "
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    \r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_RunshopsRating` (`runshop_id_fk`, `category_id_fk`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_RunshopsRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_RunshopsRating` WHERE `category_id_fk`='{$varItem}' AND `runshop_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_RunshopsRating` WHERE `runshop_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_RunshopsRating` WHERE `category_id_fk`='{$varItem}' AND `runshop_id_fk`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> diff --git a/site/runshops/rating/int.to.words.php b/site/runshops/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/runshops/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/runshops/rating/rating-example.php b/site/runshops/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/runshops/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

    Race Rating System:

    + + + + + + + \ No newline at end of file diff --git a/site/runshops/regionlist.php b/site/runshops/regionlist.php new file mode 100644 index 0000000..7f646ba --- /dev/null +++ b/site/runshops/regionlist.php @@ -0,0 +1,86 @@ + + + + + + + +
    + +
    +
    + + + +
    + +
    +
    + +
    +

    Running Stores

    + Back + + " class="btn btn-white float-right">Add Retailer + +
    + + +

    Region

    +
    + No running stores have been entered yet for ".$regionname. ".

    "; + } ?> + + + +
    +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/runshops/search.php b/site/runshops/search.php new file mode 100644 index 0000000..16f89d7 --- /dev/null +++ b/site/runshops/search.php @@ -0,0 +1,326 @@ + + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Search For A Running Store

    + +

    If you would like to search for a running store, please use the form below. None of the fields are mandatory. Checking no box in a field indicates you don't care if a shop has or does not have a treadmill, or motion capture system, or any of the listed brands. Checking regions selects all states in that region. Checking any state's box selects or deselects that state.

    + +
    +

    +
    +
    +
    Name Search
    +
    +
    + +
    +
    +
    +
    +
    +
    +

    Technology, Community & Education

    +
    +
    +
    +
    Diagnostic Equipment Used
    +
    +
    + "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + } + //if(!($i%4)) echo ""; + //echo("\n"); + echo(""); + + ?> +
    $row[diagnostic_name]
    ANY
    +
    +
    +
    +
    +
    +
    +

    Brands

    +
    +
    +
    +
    eCommerce Online Shopping Cart
    +
    +
    + Yes +
    +
    +
    +
    Running Shoe Brands
    +
    +
    + + "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + } + //if(!($i%4)) echo ""; + //echo("\n"); + echo(""); + + ?> +
    $row[shoe_name]
    ANY
    +
    +
    +
    +
    Sock Brands
    +
    +
    + + "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + } + //if(!($i%4)) echo ""; + //echo("\n"); + echo(""); + + ?> +
    $row[sock_name]
    ANY
    +
    +
    +
    +
    Run Apparel Brands
    +
    +
    + + "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + } + //if(!($i%4)) echo ""; + //echo("\n"); + echo(""); + + ?> +
    $row[apparel_run_name]
    ANY
    +
    +
    +
    +
    Tri Apparel Brands
    +
    +
    + "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + } + //if(!($i%4)) echo ""; + //echo("\n"); + echo(""); + + ?> +
    $row[apparel_tri_name]
    ANY
    +
    +
    +
    +
    Swim Gear
    +
    +
    + "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + } + //if(!($i%4)) echo ""; + //echo("\n"); + echo(""); + + ?> +
    $row[swimgear_name]
    Any
    +
    +
    +
    +
    Wetsuits
    +
    +
    + "); + //echo(""); + while ($row = mysql_fetch_array($results)) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + } + //if(!($i%4)) echo ""; + //echo("\n"); + echo(""); + + ?> +
    $row[wetsuit_name]
    Any
    +
    +
    +
    +
    +
    +
    +

    Location

    +
    +
    +
    +
    Region
    +
    +
    + + "; + foreach($regions AS $region => $statetag) { + if(!($i%4)) echo ""; + echo("\n"); + $i++; + + } + + ?> + +
    $region
    + +

    Selecting a region will select all states in that region. You can then deselect or select any additional states. Only the selected states will be included in your search. Leaving all boxes blank will select races in all states.

    +
    +
    +
    +
    State
    +
    +
    + + "; + while($row = mysql_fetch_array($state_list)){ + if(!($i%4)) echo ""; + echo "\n"; + $i++; + } + ?> + +
    $row[statelong]
    +

    Leave blank to select all.

    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/runshops/search_X.php b/site/runshops/search_X.php new file mode 100644 index 0000000..3722ad1 --- /dev/null +++ b/site/runshops/search_X.php @@ -0,0 +1,209 @@ += $comp_pct) { + // push this onto the array of matches + $runshop['percent'] = round($percent, 0); + //$runshop['trimmed'] = $runshop_name; + array_push($arr_Matches, $runshop); + break; + } + } + } + } + } + + if (count($arr_Matches) == 0) { + $none = TRUE; + } + $match_count = count($arr_Matches); + + //sort the array by keyword match success instead of by date + function cmp($a, $b) + { + if ($a['percent'] == $b['percent']) { + return 0; + } + return ($a['percent'] > $b['percent']) ? -1 : 1; + } + + usort($arr_Matches, "cmp"); +} +//end keyword search + +// set the page title +$pagetitle = "Search Results"; + +// set meta tags +$meta_keywords = "search, running stores, triathlon, results"; +$meta_description = "Triathlon running stores matching a user's search query. A list of matching running stores."; +?> + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Search Results

    +

    Running Stores Match Your Search

    + + + + +
    + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/runshops/statelist.php b/site/runshops/statelist.php new file mode 100644 index 0000000..e2067ca --- /dev/null +++ b/site/runshops/statelist.php @@ -0,0 +1,129 @@ + + + + + + + +
    + +
    +
    + + + +
    + +
    +
    + +
    +

    Running Stores

    + Back + + Add Retailer + +
    + + +

    State

    +
    + No running stores have been entered yet for ".$statename. ".

    "; + } ?> + + + +
    +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/runshops/top.php b/site/runshops/top.php new file mode 100644 index 0000000..9e4585e --- /dev/null +++ b/site/runshops/top.php @@ -0,0 +1,65 @@ + 10 ORDER BY score DESC, votes DESC LIMIT 10"); + +// set the page title +$pagetitle = "Top Running Stores"; + +// set meta tags +$meta_keywords = "top ranked running stores"; +$meta_description = "Top ranked running stores based on rankings submitted by the user."; +?> + + + + + + +
    + +
    +
    + + +
    + +
    +
    + +
    +

    Top Ranked Running Stores

    +
    + + + No running stores have been entered yet for $regionname.

    "; + } + ?> +

    + + + +

    + + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/runshops/validate.php b/site/runshops/validate.php new file mode 100644 index 0000000..480e5f7 --- /dev/null +++ b/site/runshops/validate.php @@ -0,0 +1,98 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Unvalidated Running Stores

    +
    + +
    +

    + +

    + +
    + + +
    Address: $row[runshop_address_two]"); } echo("
    $row[runshop_city], $row[runshop_state] $row[runshop_zip]"); ?>
    +
    +
    + $row[runshop_phone]
    Fax: $row[runshop_fax]"; + ?> +
    +
    +
    +
    + Email: $row[runshop_email]"; ?>
    + Website: $row[runshop_website]"; ?>
    + ">More information
    + Validate this running store. + Delete this running store. +
    +
    + +
    +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + + diff --git a/site/runshops/validate_X.php b/site/runshops/validate_X.php new file mode 100644 index 0000000..7612342 --- /dev/null +++ b/site/runshops/validate_X.php @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/site/runshops/wiki_buttons.php b/site/runshops/wiki_buttons.php new file mode 100644 index 0000000..2d838e3 --- /dev/null +++ b/site/runshops/wiki_buttons.php @@ -0,0 +1,21 @@ + + +
    + +
    + + +
    + +
    + + +
    + +
    diff --git a/site/runshops/wiki_edit.php b/site/runshops/wiki_edit.php new file mode 100644 index 0000000..d0e9b68 --- /dev/null +++ b/site/runshops/wiki_edit.php @@ -0,0 +1,428 @@ + + + + + + + + + +
    + +
    +
    + + +
    + +
    +
    + +
    + + +

    Thank you

    +

    Thank you. Your shop should be added within 24 hours. You will now be redirected back to the home page.

    + + +

    Edit a Shop: Step 2 of 2

    + +

    Edit a Shop: Step 1 of 2

    + +

    Thank you

    + +
    + + + +

    To edit a running store, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes as a NEW running store (for instance, if you have multiple locations), hit the "SAVE AS A NEW RUNNING STORE" button. To save changes to the existing running store entry, hit the "SAVE CHANGES TO YOUR RUNNING STORE" button. You will have a chance to review the data before confirming.

    + + + +
    +

    +
    +
    +
    Store Name
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Address 2
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    Phone
    +
    +
    + +
    +
    +
    +
    Fax
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    Online Shopping Cart:
    (Must be a fully functional ecommerce system)
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Key Tri-Specific Contact(s)
    +
    +
    + + +
    +
    +
    +
    Diagnostic Equipment
    +
    +
    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[diagnostic_name]"); +} +?> +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Running Shoes
    +
    +
    +

    IMPORTANT: Running shoe brands of which you'll have almost + full size runs in stock of most of the important run models at almost all + times.

    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[shoe_name]"); +} +?> +
    +
    +
    +
    Socks
    +
    +
    +

    IMPORTANT: Sock brands you'll keep in stock almost all the time.

    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[sock_name]\n"); +} +?> +
    +
    +
    +
    Run Focused Apparel
    +
    +
    +

    IMPORTANT: Run focus apparel brands you'll keep in stock, full size runs, almost all the time, season-appropriate.

    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[apparel_run_name]\n"); +} +?> +
    +
    +
    +
    Tri Focused Apparel
    +
    +
    +

    IMPORTANT: Run/tri apparel brands you'll keep in stock, full size runs, almost + all the time, season-appropriate.

    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[apparel_tri_name]\n"); +} +?> +
    +
    +
    +
    Swim Gear
    +
    +
    +

    IMPORTANT: Swimwear/Goggles: Brands you carry wide and deep, with models that are + swim-specific.

    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[swimgear_name]\n"); +} +?> +
    +
    +
    +
    Wetsuits
    +
    +
    +

    IMPORTANT: Wetsuit brands of which you'll have 12 or more continually in stock during the season.

    +"); +while ($fetch = mysql_fetch_array($list)) { + echo("$fetch[wetsuit_name]\n"); +} +?> +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Store Hours
    +
    +
    + +
    +
    +
    +
    Runs & Classes
    +
    +
    + +
    +
    +
    +
    Shop Info
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + +
    +
    +
    +
    + + +
    + + +
    +
    +
    + + +
    +
    + + +
    + + + + diff --git a/site/runshops/wiki_edit_X.php b/site/runshops/wiki_edit_X.php new file mode 100644 index 0000000..a290a16 --- /dev/null +++ b/site/runshops/wiki_edit_X.php @@ -0,0 +1,142 @@ +"; +}*/ + +if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[runshop_name]) ) { + // Contains invalid characters. + $errmsg = "Please use only letters and numbers in the name"; +} + +// BEGIN ERROR MESSAGE CHECK +if(!$errmsg){ + + $name = mysql_real_escape_string(trim($_POST[runshop_name])); + $name_tag = mysql_real_escape_string(strtolower(str_replace(" ","", $name))); + if(strlen($nametag) > 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = mysql_real_escape_string(trim($_POST[runshop_address])); + $address_two = mysql_real_escape_string(trim($_POST[runshop_address_two])); + $city = mysql_real_escape_string(trim($_POST[runshop_city])); + $state = mysql_real_escape_string($_POST[runshop_state]); + $state_tag = mysql_real_escape_string(strtolower(str_replace(" ","", $state))); + $zip = mysql_real_escape_string(trim($_POST[runshop_zip])); + $phone = mysql_real_escape_string(trim($_POST[runshop_phone])); + $fax = mysql_real_escape_string(trim($_POST[runshop_fax])); + $email = mysql_real_escape_string(trim($_POST[runshop_email])); + $website = mysql_real_escape_string(trim($_POST[runshop_website])); + $cart = mysql_real_escape_string(trim($_POST[runshop_cart])); + $contact = mysql_real_escape_string($_POST[runshop_contact]); + if ( $contact == 0 ){ $contact_names = NULL; }else{ $contact_names = mysql_real_escape_string(trim($_POST[runshop_contact_names])); } + /* Need to ltrim and rtrim commas before insertion --> or ltrim/rtrim before implosion*/ + $diagnostics = mysql_real_escape_string($_POST[runshop_diagnostics]); + $shoes = mysql_real_escape_string($_POST[runshop_shoes]); + $swimgear = mysql_real_escape_string($_POST[runshop_swimgear]); + $wetsuits = mysql_real_escape_string($_POST[runshop_wetsuits]); + $socks = mysql_real_escape_string($_POST[runshop_socks]); + $apparel_run = mysql_real_escape_string($_POST[runshop_apparel_run]); + $apparel_tri = mysql_real_escape_string($_POST[runshop_apparel_tri]); + $hours = mysql_real_escape_string(trim($_POST[runshop_hours])); + $classes = mysql_real_escape_string(substr(trim($_POST[runshop_classes]), 0, 4096)); + $info = mysql_real_escape_string(substr(trim($_POST[runshop_info]), 0, 4096)); + $directions = mysql_real_escape_string(substr(trim($_POST[runshop_directions]), 0, 4096)); + $submitted_by = mysql_real_escape_string($_POST[runshop_submitted_by]); + $id = mysql_real_escape_string($_POST[runshop_id]); + $edited_by = mysql_real_escape_string($_POST[edited_by]); + $edit_timestamp = mysql_real_escape_string(time()); + + // BEGIN CONFIRM ENTRY CHECK + if($_POST[confirm_entry] == 1){ + if(isset($_POST[new_shop])){ + $sql = "INSERT INTO ".$prefix."Runshops (runshop_name, runshop_name_tag, runshop_address, runshop_address_two, runshop_city, runshop_state, runshop_state_tag, runshop_zip, runshop_phone, runshop_fax, runshop_email, runshop_website, runshop_cart, runshop_contact, runshop_contact_names, runshop_diagnostics, runshop_shoes, runshop_socks, runshop_apparel_run, runshop_apparel_tri, runshop_swimgear, runshop_wetsuits, runshop_hours, runshop_classes, runshop_info, runshop_directions, runshop_submitted_by, runshop_valid) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', '$cart', $contact, '$contact_names', ',$diagnostics,', ',$shoes,', ',$socks,', ',$apparel_run,', ',$apparel_tri,', ',$swimgear,', ',$wetsuits,', '$hours', '$classes', '$info', '$directions', $submitted_by, 0)"; + //echo("shop entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/add.php?confirmed=yes'); + } elseif(isset($_POST[save_changes])) { + $sql = "INSERT INTO ".$prefix."RunshopsEdits (runshop_id_fk, editor_user_id_fk, edit_timestamp, runshop_name, runshop_name_tag, runshop_address, runshop_address_two, runshop_city, runshop_state, runshop_state_tag, runshop_zip, runshop_phone, runshop_fax, runshop_email, runshop_website, runshop_cart, runshop_contact, runshop_contact_names, runshop_diagnostics, runshop_shoes, runshop_socks, runshop_apparel_run, runshop_apparel_tri, runshop_swimgear, runshop_wetsuits, runshop_hours, runshop_classes, runshop_info, runshop_directions, runshop_submitted_by, runshop_valid) VALUES ('$id', '$edited_by', '$edit_timestamp', '$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$phone', '$fax', '$email', '$website', '$cart', $contact, '$contact_names', ',$diagnostics,', ',$shoes,', ',$socks,', ',$apparel_run,', ',$apparel_tri,', ',$swimgear,', ',$wetsuits,', '$hours', '$classes', '$info', '$directions', $submitted_by, 0)"; + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/individual.php?runshop_id='.$id.'&wiki_change=success'); + } else { + header('Location: '.$site_url.'/individual.php?runshop_id='.$id.'&changes=failure'); + } + } else { + //echo("shop NOT entered."); + $confirm = 1; + } + // END CONFIRM ENTRY CHECK +} +// END ERROR MESSAGE CHECK +?> diff --git a/site/runshops/wiki_validate.php b/site/runshops/wiki_validate.php new file mode 100644 index 0000000..13cc8bd --- /dev/null +++ b/site/runshops/wiki_validate.php @@ -0,0 +1,105 @@ + + + + + + + +
    + +
    +
    + + +
    + +
    +
    + +
    +

    Unvalidated Public Edits

    +
    +
    +

    + +

    + +
    + + +
    Edited on: by ".$editor_user_username.""; if ($boolEditorIsOwner) { echo " (original submitter)"; } else { echo ""; } ?>
    +
    +
    Info: + 400){ + $phrase = "…"; }else{ + $phrase = ""; } + + echo substr(htmlspecialchars(stripslashes($row[runshop_info])), 0, 160); + echo $phrase; + ?> +
    +
    + +
    +
    + Location:
    + ">More information
    + Validate this edit. + Delete this edit. +
    +
    + +
    + +
    + +
    + +
    +
    +
    + +
    +
    + + +
    + + + + diff --git a/site/runshops/wiki_validate_X.php b/site/runshops/wiki_validate_X.php new file mode 100644 index 0000000..31e485e --- /dev/null +++ b/site/runshops/wiki_validate_X.php @@ -0,0 +1,75 @@ + \ No newline at end of file diff --git a/site/runshops/wiki_view.php b/site/runshops/wiki_view.php new file mode 100644 index 0000000..ea6a59a --- /dev/null +++ b/site/runshops/wiki_view.php @@ -0,0 +1,304 @@ + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    + + + +
    + + + +Editor: ".$strEditor.""; ?> +
    + +Edit Date: +
    + +Street Address: +
    +Street Address Two: +
    +City: +
    +State: +
    +Zip/Postal Code: +
    +Phone: +
    +Fax / Alternate Phone: +
    +E-mail: +
    +Website: + +
    +
    + +
    + +
    + +
    +Key Tri-Specific Contact(s): +
    +Diagnostic Equipment: + +

    +
    + +
    + +
    +Shoes: + +
    +Socks: + +
    +Run-Focused Apparel: + +
    +Tri-Focused Apparel: + +
    +Swim Gear: + +
    +Wetsuits: + +

    +
    + +
    +
    +Shop Hours: +

    +Runs & Classes: +

    +Shop Info: +

    +Directions: + +
    + +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/stackreach/add_brand.php b/site/stackreach/add_brand.php new file mode 100755 index 0000000..0ab063b --- /dev/null +++ b/site/stackreach/add_brand.php @@ -0,0 +1,77 @@ +assign('values', $values); + $smarty->assign('errors', $errors); + $smarty->display('views/add_brand.tpl'); +} + +function VerifyForm(&$values, &$errors) +{ + $ret = true; + $url = htmlspecialchars($values['website']); + if (!preg_match("/^(https?:\/\/+[\w\-]+\.[\w\-]+)/i", $url)) + { + $errors["website"] = "Please check the website and resubmit"; + $ret = false; + } + if (strlen($values['name']) < 4) + { + $errors["name"] = "Please check the brand name and resubmit"; + $ret = false; + } + + return $ret; +} + +function ProcessForm($values) +{ + $brand = new Brand($values); + $brand->approved = 0; + $brand->user_id = get_user_id(); + + $brandService = new BrandService(); + $brandService->createBrand($brand); + + header('location:brands.php'); + +} + + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + $formValues = $_POST; + $formErrors = array(); + + try + { + if (!VerifyForm($formValues, $formErrors)) + DisplayForm($formValues, $formErrors); + else + ProcessForm($formValues); + } + catch (Exception $e) + { + echo $e->getMessage(); + DisplayForm($formValues, $formErrors); + } +} +else +{ + + DisplayForm(null, null); +} + +?> \ No newline at end of file diff --git a/site/stackreach/add_frame.php b/site/stackreach/add_frame.php new file mode 100755 index 0000000..64a9150 --- /dev/null +++ b/site/stackreach/add_frame.php @@ -0,0 +1,97 @@ +getBrandByName($values['brand']); + + $geometryService = new GeometryService(); + $geometries = $geometryService->getAllGeometriesByBrand($brand->id); + + $smarty = new Smarty; + $smarty->assign('values', $values); + $smarty->assign('errors', $errors); + $smarty->assign('geometries', $geometries); + $smarty->assign('brand', $brand); + $smarty->display('views/add_frame.tpl'); +} + + +function VerifyForm(&$values, &$errors) +{ + return VerifyFrame($values, $errors); +} + +function ProcessForm($values) +{ + + try + { + $frameService = new FrameService(); + $frame = new Frame($values); + $frame->approved = 0; + $frame->user_id = get_user_id(); + $frameService->createFrame($frame); + } + catch (Exception $e) + { + echo $e->getMessage(); + return; + } + + header('location:frames.php'); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + $formValues = $_POST; + $formErrors = array(); + + if (!isset($_POST['internal_headset'])) + $formValues['internal_headset'] = 0; + else + $formValues['internal_headset'] = 1; + + if (!isset($_POST['is_650'])) + $formValues['is_650'] = 0; + else + $formValues['is_650'] = 1; + + + if (!VerifyForm($formValues, $formErrors)) + DisplayForm($formValues, $formErrors); + else + ProcessForm($formValues); +} +else +{ + + if (!isset($_SESSION['brand'])) + { + $brandService = new BrandService(); + $brands = $brandService->getAllBrands(); + + $smarty = new Smarty; + $smarty->assign('brands', $brands); + $smarty->assign('action', "add_frame.php"); + $smarty->display('views/selectbrand.tpl'); + } + else + { + $formValues['brand'] = $_SESSION['brand']; + DisplayForm($formValues, null); + } +} +?> diff --git a/site/stackreach/add_geometry.php b/site/stackreach/add_geometry.php new file mode 100755 index 0000000..f047a10 --- /dev/null +++ b/site/stackreach/add_geometry.php @@ -0,0 +1,83 @@ +getAllBrands(); +// if (count($brands) == 0) +// { +// header('location:add_brand.php'); +// return; +// } + + $smarty = new Smarty; +// $smarty->assign('brands', $brands); + $smarty->assign ('values', $values); + $smarty->display ('views/add_geometry.tpl'); +} + +function VerifyForm (&$values, $errors) +{ + return true; +} + +function ProcessForm ($values) +{ + $service = new BrandService(); + $brand = $service->getBrandByName ($values['brand']); + $geometry = new Geometry ($values); + $geometry->brand_id = $brand->id; + $geometry->approved = 0; + $geometry->user_id = get_user_id (); + + $geometryService = new GeometryService(); + $geometryService->createGeometry ($geometry); + header ('location:geometries.php'); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + $formValues = $_POST; + $formErrors = array (); + + if (isset ($_POST['is_road'])) + $formValues['is_road'] = 1; + else + $formValues['is_road'] = 0; + + if (!VerifyForm ($formValues, $formErrors)) + DisplayForm ($formValues, $formErrors); + else + ProcessForm ($formValues); +} +else +{ + if (!isset ($_SESSION['brand'])) + { + $brandService = new BrandService(); + $brands = $brandService->getAllBrands (); + + $smarty = new Smarty; + $smarty->assign ('brands', $brands); + $smarty->assign ('action', "add_frame.php"); + $smarty->display ('views/selectbrand.tpl'); + } + else + { + $formValues['brand'] = $_SESSION['brand']; + DisplayForm ($formValues, null); + } +} +?> diff --git a/site/stackreach/add_model.php b/site/stackreach/add_model.php new file mode 100755 index 0000000..e524524 --- /dev/null +++ b/site/stackreach/add_model.php @@ -0,0 +1,76 @@ +getBrandByName($values['brand']); + + $geometryService = new GeometryService(); + $geometries = $geometryService->getAllGeometriesByBrand($brand->id); + + $smarty = new Smarty; + $smarty->assign('brand', $brand); + $smarty->assign('geometries', $geometries); + $smarty->display('views/add_model.tpl'); +} + +function VerifyForm(&$values, $errors) +{ + + return true; +} + +function ProcessForm($values) +{ + $modelService = new ModelService(); + $model = new Model($values); + $model->approved = 0; + $model->user_id = get_user_id(); + + $modelService->createModel($model); + header('location:models.php'); +} + + + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + $formValues = $_POST; + $formErrors = array(); + + if (!VerifyForm($formValues, $formErrors)) + DisplayForm($formValues, $formErrors); + else + ProcessForm($formValues); +} +else +{ + if (! isset($_SESSION['brand'])) + { + $brandService = new BrandService(); + $brands = $brandService->getAllBrands(); + + $smarty = new Smarty; + $smarty->assign('brands', $brands); + $smarty->assign('action', "add_frame.php"); + $smarty->display('views/selectbrand.tpl'); + } + + else + { + $formValues['brand'] = $_SESSION['brand']; + DisplayForm($formValues, null); + } +} + +?> diff --git a/site/stackreach/approve_brand.php b/site/stackreach/approve_brand.php new file mode 100755 index 0000000..bac5386 --- /dev/null +++ b/site/stackreach/approve_brand.php @@ -0,0 +1,30 @@ +getBrandByID($brand_id); + $item->approved = 1; + + $brandService->updateBrand($item); + + } +} +else +{ + echo $_SERVER['REQUEST_METHOD']; +} + +header('location:brands.php'); + +?> \ No newline at end of file diff --git a/site/stackreach/approve_frame.php b/site/stackreach/approve_frame.php new file mode 100755 index 0000000..bc32793 --- /dev/null +++ b/site/stackreach/approve_frame.php @@ -0,0 +1,31 @@ +getFrameByID($frame_id); + $item->approved = 1; + + $frameService->updateFrame($item); + + + + } +} +else +{ + echo $_SERVER['REQUEST_METHOD']; +} + +header('location:frames.php'); +?> diff --git a/site/stackreach/approve_geometry.php b/site/stackreach/approve_geometry.php new file mode 100755 index 0000000..f8b06e1 --- /dev/null +++ b/site/stackreach/approve_geometry.php @@ -0,0 +1,30 @@ +getGeometryByID($geometry_id); + $item->approved = 1; + + $geometryService->updateGeometry($item); + + + } +} +else +{ + echo $_SERVER['REQUEST_METHOD']; +} + +header('location:geometries.php'); + +?> \ No newline at end of file diff --git a/site/stackreach/approve_model.php b/site/stackreach/approve_model.php new file mode 100755 index 0000000..9f5e412 --- /dev/null +++ b/site/stackreach/approve_model.php @@ -0,0 +1,28 @@ +getModelByID($model_id); + $item->approved = 1; + $modelService->updateModel($item); + + } +} +else +{ + echo $_SERVER['REQUEST_METHOD']; +} + +header('location:models.php'); + +?> \ No newline at end of file diff --git a/site/stackreach/brands.php b/site/stackreach/brands.php new file mode 100755 index 0000000..09ec489 --- /dev/null +++ b/site/stackreach/brands.php @@ -0,0 +1,18 @@ +getAllBrands(is_updater()); + +$smarty = new Smarty; +//$smarty->caching = 1; +//$smarty->force_compile = true; +$smarty->assign('brands', $brands); +$smarty->assign('user_can_update', is_updater()); +$smarty->assign('user_logged_in', is_logged_in($user)); +$smarty->display('views/brands.tpl'); + +?> diff --git a/site/stackreach/config.php b/site/stackreach/config.php new file mode 100755 index 0000000..ac21297 --- /dev/null +++ b/site/stackreach/config.php @@ -0,0 +1,217 @@ += '4.0.4pl1' && strstr($_SERVER["HTTP_USER_AGENT"], 'compatible')) +{ + if (extension_loaded('zlib')) + { + ob_end_clean(); + ob_start('ob_gzhandler'); + } +} +else if ($phpver > '4.0') +{ + if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) + { + if (extension_loaded('zlib')) + { + $do_gzip_compress = TRUE; + ob_start(array('ob_gzhandler', 5)); + ob_implicit_flush(0); + header('Content-Encoding: gzip'); + } + } +} +*/ + +$phpver = explode(".", $phpver); +$phpver = "$phpver[0]$phpver[1]"; +if ($phpver >= 41) +{ + $PHP_SELF = $_SERVER['PHP_SELF']; +} + +if (!ini_get("register_globals")) +{ + import_request_variables('GPC'); +} + + +include_once("mysql.class.php"); +$db = new sql_db($dbhost, $dbuname, $dbpass, $dbname, false); +if (!$db->db_connect_id) +{ + + echo "


    Error:


    + Connection to database failed
    +








    "; + + exit(); +} + +function is_updater() +{ + if (is_logged_in($user)) + { + $username = base64_decode($_SESSION['user']); + } + + return (is_admin() === true); +} + +function is_admin() +{ + if (is_logged_in($user)) + { + $username = base64_decode($_SESSION['user']); + if ($username != "Slowman" && $username != "Rappstar" && $username != "Herbert" && $username != "AWright" ) + { + return false; + } + else + { + return true; + } + } + else + { + return false; + } +} + +function get_sid() +{ + if (isset($_SESSION['cookie']) and $_SESSION['cookie']) + { + return ''; + } + else + { + return '&' . SID; + } +} + +function get_user_id() +{ + if (!is_logged_in() AND !isset( $_SESSION['user_id'] )) + return null; + return base64_decode($_SESSION['user_id']); + +} + +//global function for checking whether user is logged in or not. +//you will notice we will use it everwhere in the script. +function is_logged_in($user) +{ + global $db; //, $prefix; + $prefix = "gforum_"; + + // return true if we're already logged in + if (isset($_SESSION['user']) && $_SESSION['user'] != '') + { + return 1; + } + + // try and get the session id + if (isset($_REQUEST['gforum_1022870964_session'])) + { + $session_id = $_REQUEST['gforum_1022870964_session']; + } + else if ($_REQUEST['from'] == 'gforum') + { + foreach ($_COOKIE as $key => $value) + { + if (preg_match('/gforum.*session/', $key)) + { + $session_id = $value; + break; + } + } + if (!isset($session_id)) + { + return 0; + } + } + // return false if we have no login info + else + { + return 0; + } + + $result = mysql_query("SELECT session_user_id FROM " . $prefix . "Session WHERE session_id='$session_id'") or die(mysql_error()); + $row = mysql_fetch_array($result); + $user_id = $row['session_user_id']; + $result = mysql_query("SELECT user_username,user_password,user_last_logon FROM " . $prefix . "User WHERE user_id='$user_id'"); + $row = mysql_fetch_array($result); + + $_SESSION['user'] = base64_encode($row['user_username']); + $_SESSION['password'] = base64_encode($row['user_password']); + $_SESSION['user_id'] = base64_encode($user_id); + $_SESSION['session_id'] = $session_id; + $_SESSION['cookie'] = !(isset($_REQUEST['session'])); + + if ($_SESSION['user_id'] == '') + { + return 0; + } + + // we're now logged in, so return 1 + return 1; + + // TODO: SLOWTWITCH CHANGE END +} + +?> diff --git a/site/stackreach/db_templates/include_breadcrumb.php b/site/stackreach/db_templates/include_breadcrumb.php new file mode 100755 index 0000000..c0c0293 --- /dev/null +++ b/site/stackreach/db_templates/include_breadcrumb.php @@ -0,0 +1,4 @@ + diff --git a/site/stackreach/db_templates/include_common_content.php b/site/stackreach/db_templates/include_common_content.php new file mode 100755 index 0000000..f3a9545 --- /dev/null +++ b/site/stackreach/db_templates/include_common_content.php @@ -0,0 +1,36 @@ + + +
    +
    + + + + +
    +
    + + + +
    +
    +
    +
    +
    diff --git a/site/stackreach/db_templates/include_common_footer.php b/site/stackreach/db_templates/include_common_footer.php new file mode 100755 index 0000000..521d20e --- /dev/null +++ b/site/stackreach/db_templates/include_common_footer.php @@ -0,0 +1,14 @@ +
    +
    +
    + + +
    +
    + + + +
    + + + diff --git a/site/stackreach/db_templates/include_common_head.php b/site/stackreach/db_templates/include_common_head.php new file mode 100755 index 0000000..297eb87 --- /dev/null +++ b/site/stackreach/db_templates/include_common_head.php @@ -0,0 +1,29 @@ + + + + +Slowtwitch.com Stack & Reach Database: <? echo $pagetitle; ?> + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Stack/Reach Database

    +
    diff --git a/site/stackreach/db_templates/include_navigation.php b/site/stackreach/db_templates/include_navigation.php new file mode 100755 index 0000000..c5f3eac --- /dev/null +++ b/site/stackreach/db_templates/include_navigation.php @@ -0,0 +1,15 @@ + + +
    +

    More on Stack/Reach

    + +
    diff --git a/site/stackreach/db_templates/include_sidebar.php b/site/stackreach/db_templates/include_sidebar.php new file mode 100755 index 0000000..0efc02b --- /dev/null +++ b/site/stackreach/db_templates/include_sidebar.php @@ -0,0 +1,7 @@ + + +
    + + diff --git a/site/stackreach/db_templates/include_status.php b/site/stackreach/db_templates/include_status.php new file mode 100755 index 0000000..274a313 --- /dev/null +++ b/site/stackreach/db_templates/include_status.php @@ -0,0 +1,4 @@ + + diff --git a/site/stackreach/delete_brand.php b/site/stackreach/delete_brand.php new file mode 100755 index 0000000..7d2271c --- /dev/null +++ b/site/stackreach/delete_brand.php @@ -0,0 +1,26 @@ +deleteBrand($brandID); + } +} +else +{ + echo $_SERVER['REQUEST_METHOD']; +} + +header('location:brands.php'); + +?> diff --git a/site/stackreach/delete_frame.php b/site/stackreach/delete_frame.php new file mode 100755 index 0000000..bf32812 --- /dev/null +++ b/site/stackreach/delete_frame.php @@ -0,0 +1,28 @@ +deleteFrame($frameID); + } + } +} +else +{ + echo $_SERVER['REQUEST_METHOD']; +} + +header('location:frames.php'); +?> diff --git a/site/stackreach/delete_geometry.php b/site/stackreach/delete_geometry.php new file mode 100755 index 0000000..422c970 --- /dev/null +++ b/site/stackreach/delete_geometry.php @@ -0,0 +1,24 @@ +deleteGeometry($geoID); + } +} +else +{ + echo $_SERVER['REQUEST_METHOD']; +} + +header('location:geometries.php'); + +?> diff --git a/site/stackreach/delete_model.php b/site/stackreach/delete_model.php new file mode 100755 index 0000000..3008452 --- /dev/null +++ b/site/stackreach/delete_model.php @@ -0,0 +1,27 @@ +deleteModel($modelID); + } +} +else +{ + echo $_SERVER['REQUEST_METHOD']; +} + + +header('location:models.php'); + +?> diff --git a/site/stackreach/frames.php b/site/stackreach/frames.php new file mode 100755 index 0000000..9fb6d3b --- /dev/null +++ b/site/stackreach/frames.php @@ -0,0 +1,77 @@ +getBrandByName($name); + + $brandMap = array(); + + $geometryService = new GeometryService(); + $geometries = $geometryService->getAllGeometriesByBrand($brand->id, is_updater()); + + foreach ($geometries as $geometry) + { + $modelService = new ModelService(); + $brandMap[$brand->name][$geometry->name]['models'] = $modelService->getAllModelsByGeometry($geometry->id, is_updater()); + + $frameService = new FrameService(); + $frames = $frameService->getAllFramesByGeometry($geometry->id, is_updater()); + + if ($frames === null) { header('location:add_frame.php');} + + foreach ($frames as $frame) + { + $brandMap[$brand->name][$geometry->name]['geometries'][] = $frame; + } + + } + + $smarty = new Smarty; + $smarty->assign('brandMap', $brandMap); + $smarty->assign('brand', $brand); + $smarty->assign('user_can_update', is_updater()); + $smarty->assign('user_logged_in', is_logged_in($user)); + $smarty->display('views/frames.tpl'); + +// $frameService = new FrameService(); +// $frames = $frameService->getAllFramesByBrand($brand->id, is_updater()); +// +// if ($frames) +// { +// $smarty = new Smarty; +// $smarty->assign('brand', $brand); +// $smarty->assign('frames', $frames); +// $smarty->assign('user_can_update', is_updater()); +// $smarty->display('views/frames.tpl'); +// } +// else +// { +// header("location:add_frame.php?brand=$name"); +// } + } + else + { + $brandService = new BrandService(); + $brands = $brandService->getAllBrands(); + + $smarty = new Smarty; + $smarty->assign('brands', $brands); + $smarty->assign('action', "frames.php"); + $smarty->display('views/selectbrand.tpl'); + } +} + +?> diff --git a/site/stackreach/framesX.php b/site/stackreach/framesX.php new file mode 100755 index 0000000..08be1ce --- /dev/null +++ b/site/stackreach/framesX.php @@ -0,0 +1,58 @@ +getAllBrands (); +?> +
    +' . $brand->name . ''; + + $geometryService = new GeometryService(); + $geometries = $geometryService->getAllGeometriesByBrand ($brand->id); + + foreach ($geometries as $geometry) + { + + $modelService = new ModelService(); + $models = $modelService->getAllModelsByGeometry ($geometry->id); + + $frameService = new FrameService(); + $frames = $frameService->getAllFramesByGeometry ($geometry->id); + $cnt = count ($frames); + + echo ''; + foreach ($models as $model) + { + echo "$model->name
    "; + } + echo ""; + + foreach ($frames as $frame) + { + ?>size_name ?> + stack ?> + reach ?> + trail ?> + front_center ?> + head_tube ?> + internal_headset ?> + sta_min ?> + sta_max ?> + is_650 ?> + "; + } +} +?> + +
    diff --git a/site/stackreach/geometries.php b/site/stackreach/geometries.php new file mode 100755 index 0000000..d486fc2 --- /dev/null +++ b/site/stackreach/geometries.php @@ -0,0 +1,58 @@ +getBrandByName($brandName); + + $geometryService = new GeometryService(); + $geometries = $geometryService->getAllGeometriesByBrand($brand->id, is_updater()); + + $models = array(); + foreach ($geometries as $geo) + { + $modelService = new ModelService(); + $models[$geo->id] = $modelService->getAllModelsByGeometry($geo->id, is_updater()); + } + + if ($geometries) + { + $smarty = new Smarty; + $smarty->assign('brand', $brand); + $smarty->assign('geometries', $geometries); + if ($models) + { + $smarty->assign('models', $models); + } + $smarty->assign('geometries', $geometries); + $smarty->assign('user_can_update', is_updater()); + $smarty->assign('user_logged_in', is_logged_in($user)); + $smarty->display('views/geometries.tpl'); + } + else + { + header('location:add_geometry.php?brand=' . $brand->name); + } + } + else + { + $brandService = new BrandService(); + $brands = $brandService->getAllBrands(); + + $smarty = new Smarty; + $smarty->assign('brands', $brands); + $smarty->assign('action', "geometries.php"); + $smarty->display('views/selectbrand.tpl'); + } +} +?> diff --git a/site/stackreach/index.php b/site/stackreach/index.php new file mode 100755 index 0000000..9df06ef --- /dev/null +++ b/site/stackreach/index.php @@ -0,0 +1,52 @@ + +getAllBrands(); + + $brandMap = array(); + + foreach ($brands as $brand) + { + + $geometryService = new GeometryService(); + $geometries = $geometryService->getAllTriGeometriesByBrand($brand->id); + + foreach ($geometries as $geometry) + { + $modelService = new ModelService(); + $brandMap[$brand->name][$geometry->name]['models'] = $modelService->getAllModelsByGeometry($geometry->id); + + $frameService = new FrameService(); + $frames = $frameService->getAllFramesByGeometry($geometry->id); + + if ($frames === null) { header('location:add_frame.php');} + + foreach ($frames as $frame) + { + $brandMap[$brand->name][$geometry->name]['geometries'][] = $frame; + } + } + } + + $smarty = new Smarty; + $smarty->assign('brandMap', $brandMap); + $smarty->display('views/index.tpl'); + +} +catch (Exception $e) +{ + echo 'Caught exception: ', $e->getMessage(), "\n"; +} + + +?> + diff --git a/site/stackreach/info.php b/site/stackreach/info.php new file mode 100755 index 0000000..7859b50 --- /dev/null +++ b/site/stackreach/info.php @@ -0,0 +1,17 @@ +cache_dir; +//$smarty->clearAllCache(); +//$smarty->assign('user_can_update', is_updater()); + +//if (is_logged_in($user)) +//{ +// $username = base64_decode($_SESSION['user']); +// echo ($username); +//} + +?> \ No newline at end of file diff --git a/site/stackreach/logout.php b/site/stackreach/logout.php new file mode 100755 index 0000000..2234eee --- /dev/null +++ b/site/stackreach/logout.php @@ -0,0 +1,7 @@ + diff --git a/site/stackreach/models.php b/site/stackreach/models.php new file mode 100755 index 0000000..146dca1 --- /dev/null +++ b/site/stackreach/models.php @@ -0,0 +1,46 @@ +getBrandByName($name); + + $modelService = new ModelService(); + $models = $modelService->getAllModelsByBrand($brand->id, is_updater()); + + if ($models) + { + $smarty = new Smarty; + $smarty->assign('brand', $name); + $smarty->assign('models', $models); + $smarty->assign('user_can_update', is_updater()); + $smarty->assign('user_logged_in', is_logged_in($user)); + $smarty->display('views/models.tpl'); + } + else + { + header("location:add_model.php?brand=$name"); + } + } + else + { + $brandService = new BrandService(); + $brands = $brandService->getAllBrands(); + + $smarty = new Smarty; + $smarty->assign('brands', $brands); + $smarty->assign('action', "models.php"); + $smarty->display('views/selectbrand.tpl'); + } +} + +?> diff --git a/site/stackreach/models/services/BrandService.php b/site/stackreach/models/services/BrandService.php new file mode 100644 index 0000000..ca93604 --- /dev/null +++ b/site/stackreach/models/services/BrandService.php @@ -0,0 +1,226 @@ + $v) + { + $this->{$k} = mysql_real_escape_string ($v); + } + } + +} + +class BrandService extends Database +{ + + var $tablename = "brand"; + var $connection; + + public function __construct ($tablename="") + { + if (! empty($tablename)) + $this->tablename = $tablename; + + $this->connection = mysqli_connect ( + $this->server, $this->username, $this->password, $this->databasename + ); + + $this->throwExceptionOnError ($this->connection); + } + + public function getAllBrands ($updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename"; + else + $query = "SELECT * FROM $this->tablename WHERE approved=1 ORDER BY name ASC"; + + $stmt = mysqli_prepare ($this->connection, $query); + $this->throwExceptionOnError (); + + mysqli_stmt_execute ($stmt); + $this->throwExceptionOnError (); + + $rows = array (); + + mysqli_stmt_bind_result ($stmt, $row->id, $row->name, $row->website, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch ($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result ($stmt, $row->id, $row->name, $row->website, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result ($stmt); + mysqli_close ($this->connection); + + return $rows; + } + + public function getBrandByName ($name) + { + + $stmt = mysqli_prepare ($this->connection, "SELECT * FROM $this->tablename where name like ?"); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_param ($stmt, 's', $name); + $this->throwExceptionOnError (); + + mysqli_stmt_execute ($stmt); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_result ($stmt, $row->id, $row->name, $row->website, $row->approved, $row->user_id); + + if (mysqli_stmt_fetch ($stmt)) + { + return $row; + } + else + { + return null; + } + } + + public function getBrandByID ($itemID) + { + + $stmt = mysqli_prepare ($this->connection, "SELECT * FROM $this->tablename where id=?"); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_param ($stmt, 'i', $itemID); + $this->throwExceptionOnError (); + + mysqli_stmt_execute ($stmt); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_result ($stmt, $row->id, $row->name, $row->website, $row->approved, $row->user_id); + + if (mysqli_stmt_fetch ($stmt)) + { + return $row; + } + else + { + return null; + } + } + + public function createBrand ($item) + { + + $stmt = mysqli_prepare ($this->connection, "INSERT INTO $this->tablename (name, website, approved, user_id) VALUES (?, ?, ?, ?)"); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_param ($stmt, 'ssii', $item->name, $item->website, $item->approved, $item->user_id); + $this->throwExceptionOnError (); + + mysqli_stmt_execute ($stmt); + $this->throwExceptionOnError (); + + $autoid = mysqli_stmt_insert_id ($stmt); + + mysqli_stmt_free_result ($stmt); + mysqli_close ($this->connection); + + return $autoid; + } + + public function updateBrand ($item) + { + + $stmt = mysqli_prepare ($this->connection, "UPDATE $this->tablename SET name=?, website=?, approved=?, user_id=? WHERE id=?"); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_param ($stmt, 'ssiii', $item->name, $item->website, $item->approved, $item->user_id, $item->id); + $this->throwExceptionOnError (); + + mysqli_stmt_execute ($stmt); + $this->throwExceptionOnError (); + + mysqli_stmt_free_result ($stmt); + mysqli_close ($this->connection); + } + + public function deleteBrand ($itemID) + { + + $stmt = mysqli_prepare ($this->connection, "DELETE FROM $this->tablename WHERE id = ?"); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_param ($stmt, 'i', $itemID); + mysqli_stmt_execute ($stmt); + $this->throwExceptionOnError (); + + mysqli_stmt_free_result ($stmt); + mysqli_close ($this->connection); + } + + public function count () + { + $stmt = mysqli_prepare ($this->connection, "SELECT COUNT(*) AS COUNT FROM $this->tablename"); + $this->throwExceptionOnError (); + + mysqli_stmt_execute ($stmt); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_result ($stmt, $rec_count); + $this->throwExceptionOnError (); + + mysqli_stmt_fetch ($stmt); + $this->throwExceptionOnError (); + + mysqli_stmt_free_result ($stmt); + mysqli_close ($this->connection); + + return $rec_count; + } + + public function getBrand_paged ($startIndex, $numItems) + { + + $stmt = mysqli_prepare ($this->connection, "SELECT * FROM $this->tablename LIMIT ?, ?"); + $this->throwExceptionOnError (); + + mysqli_stmt_bind_param ($stmt, 'ii', $startIndex, $numItems); + mysqli_stmt_execute ($stmt); + $this->throwExceptionOnError (); + + $rows = array (); + + mysqli_stmt_bind_result ($stmt, $row->id, $row->name, $row->website, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch ($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result ($stmt, $row->id, $row->name, $row->website, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result ($stmt); + mysqli_close ($this->connection); + + return $rows; + } + + private function throwExceptionOnError ($link = null) + { + if ($link == null) + { + $link = $this->connection; + } + if (mysqli_error ($link)) + { + $msg = mysqli_errno ($link) . ": " . mysqli_error ($link); + throw new Exception ('MySQL Error - ' . $msg); + } + } + +} + +?> diff --git a/site/stackreach/models/services/Database.php b/site/stackreach/models/services/Database.php new file mode 100644 index 0000000..18152a4 --- /dev/null +++ b/site/stackreach/models/services/Database.php @@ -0,0 +1,38 @@ + diff --git a/site/stackreach/models/services/FrameService.php b/site/stackreach/models/services/FrameService.php new file mode 100644 index 0000000..14a4122 --- /dev/null +++ b/site/stackreach/models/services/FrameService.php @@ -0,0 +1,382 @@ + $v) { + $this->{$k} = mysql_real_escape_string($v); + } + } +} + +function ensure_digits($test, $len, &$values, &$errors) +{ + if (strlen($values[$test]) !== $len OR !ctype_digit($values[$test])) + { + $errors[$test] = "$test needs to be a $len digit number"; + return false; + } + + return true; +} + +function ensure_range($test, $max, $min, &$values, &$errors) +{ + if (strlen($values[$test]) > $max OR strlen($values[$test]) < $min OR !ctype_digit($values[$test])) + { + $errors[$test] = "$test needs to be a $min to $max digit number"; + return false; + } + + return true; +} + +function VerifyFrame(&$values, &$errors) +{ + $ret = true; + if (!ensure_digits('stack', 3, $values, $errors)) + $ret = false; + + if (!ensure_digits('reach', 3, $values, $errors)) + $ret = false; + + if (!ensure_digits('trail', 2, $values, $errors)) + $ret = false; + + if (!ensure_digits('front_center', 3, $values, $errors)) + $ret = false; + + if (!ensure_range('head_tube', 3, 2, $values, $errors)) + $ret = false; + + if (!ensure_digits('sta_min', 2, $values, $errors)) + $ret = false; + + if (isset($values['sta_max'])) + { + if (!ensure_digits('sta_max', 2, $values, $errors)) + $ret = false; + } + + return $ret; +} + +class FrameService extends Database +{ + + var $tablename = "frame"; + var $editstablename = "frame_edits"; + var $connection; + + public function __construct($tablename="") + { + if (! empty($tablename)) + $this->tablename = $tablename; + + $this->connection = mysqli_connect( + $this->server, + $this->username, + $this->password, + $this->databasename + ); + + $this->throwExceptionOnError($this->connection); + } + + public function getAllFrames($updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename"; + else + $query = "SELECT * FROM $this->tablename WHERE approved=1"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getAllFramesOrdered($updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename where approved=1 ORDER BY brand_id, geometry_id, is_650 DESC, reach"; + else + $query = "SELECT * FROM $this->tablename ORDER BY brand_id, geometry_id, is_650 DESC, reach"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getAllFramesByBrand($brand, $updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename where brand_id=? ORDER BY geometry_id, is_650 DESC, reach"; + else + $query = "SELECT * FROM $this->tablename where brand_id=? and approved=1 ORDER BY geometry_id, is_650 DESC, reach"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $brand); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getAllFramesByGeometry($geo, $updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename where geometry_id=? ORDER BY is_650 DESC, reach"; + else + $query = "SELECT * FROM $this->tablename where geometry_id=? AND approved=1 ORDER BY is_650 DESC, reach"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $geo); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getFrameByID($itemID) + { + + $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename where id=?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $itemID); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + + if (mysqli_stmt_fetch($stmt)) + { + return $row; + } + else + { + return null; + } + } + + public function createFrame($item) + { + + $stmt = mysqli_prepare($this->connection, "INSERT INTO $this->tablename (brand_id, geometry_id, size_name, stack, reach, trail, front_center, head_tube, internal_headset, sta_min, sta_max, is_650, approved, user_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'iisiiiiiiiiiii', + $item->brand_id, + $item->geometry_id, + $item->size_name, + $item->stack, + $item->reach, + $item->trail, + $item->front_center, + $item->head_tube, + $item->internal_headset, + $item->sta_min, + $item->sta_max, + $item->is_650, + $item->approved, + $item->user_id); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $autoid = mysqli_stmt_insert_id($stmt); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $autoid; + } + + public function updateFrame($item) + { + $stmt = mysqli_prepare($this->connection, "UPDATE $this->tablename SET brand_id=?, geometry_id=?, size_name=?, stack=?, reach=?, trail=?, front_center=?, head_tube=?, internal_headset=?, sta_min=?, sta_max=?, is_650=?, approved=?, user_id=? WHERE id=?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'iisiiiiiiiiiiii', + $item->brand_id, + $item->geometry_id, + $item->size_name, + $item->stack, + $item->reach, + $item->trail, + $item->front_center, + $item->head_tube, + $item->internal_headset, + $item->sta_min, + $item->sta_max, + $item->is_650, + $item->approved, + $item->user_id, + $item->id); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + } + + public function deleteFrame($itemID) + { + + $stmt = mysqli_prepare($this->connection, "DELETE FROM $this->tablename WHERE id = ?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $itemID); + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + } + + public function count() + { + $stmt = mysqli_prepare($this->connection, "SELECT COUNT(*) AS COUNT FROM $this->tablename"); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_result($stmt, $rec_count); + $this->throwExceptionOnError(); + + mysqli_stmt_fetch($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rec_count; + } + + public function getFrame_paged($startIndex, $numItems) + { + + $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename LIMIT ?, ?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'ii', $startIndex, $numItems); + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->size_name, $row->stack, $row->reach, $row->trail, $row->front_center, $row->head_tube, $row->internal_headset, $row->sta_min, $row->sta_max, $row->is_650, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + private function throwExceptionOnError($link = null) + { + if ($link == null) + { + $link = $this->connection; + } + if (mysqli_error($link)) + { + $msg = mysqli_errno($link) . ": " . mysqli_error($link); + throw new Exception('MySQL Error - ' . $msg); + } + } + +} + +?> diff --git a/site/stackreach/models/services/GeometryService.php b/site/stackreach/models/services/GeometryService.php new file mode 100644 index 0000000..18bbe8f --- /dev/null +++ b/site/stackreach/models/services/GeometryService.php @@ -0,0 +1,304 @@ + $v) { + $this->{$k} = mysql_real_escape_string($v); + } + } +} + +class GeometryService extends Database +{ + + var $tablename = "geometry"; + var $connection; + + public function __construct($tablename="") + { + if (! empty($tablename)) + $this->tablename = $tablename; + + $this->connection = mysqli_connect( + $this->server, + $this->username, + $this->password, + $this->databasename + ); + + $this->throwExceptionOnError($this->connection); + } + + public function getAllGeometries($updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename"; + else + $query = "SELECT * FROM $this->tablename WHERE approved=1"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getAllGeometriesByBrand($brand, $updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename where brand_id=?"; + else + $query = "SELECT * FROM $this->tablename where brand_id=? AND approved=1"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $brand); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getAllTriGeometriesByBrand($brand, $updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename where brand_id=? AND is_road IS NOT TRUE"; + else + $query = "SELECT * FROM $this->tablename where brand_id=? AND approved=1 AND is_road IS NOT TRUE"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $brand); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getAllRoadGeometriesByBrand($brand, $updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename where brand_id=? AND is_road IS NOT FALSE"; + else + $query = "SELECT * FROM $this->tablename where brand_id=? AND approved=1 AND is_road IS NOT FALSE"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $brand); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getGeometryByID($itemID) + { + + $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename where id=?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $itemID); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name, $row->approved, $row->user_id, $row->is_road); + + if (mysqli_stmt_fetch($stmt)) + { + return $row; + } + else + { + return null; + } + } + + public function createGeometry($item) + { + + $stmt = mysqli_prepare($this->connection, "INSERT INTO $this->tablename (brand_id, name, approved, user_id, is_road) VALUES (?, ?, ?, ?, ?)"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'isiii', $item->brand_id, $item->name, $row->approved, $row->user_id, $row->is_road); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $autoid = mysqli_stmt_insert_id($stmt); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $autoid; + } + + public function updateGeometry($item) + { + + $stmt = mysqli_prepare($this->connection, "UPDATE $this->tablename SET brand_id=?, name=?, approved=?, user_id=?, is_road=? WHERE id=?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'isiiii', $item->brand_id, $item->name, $item->approved, $item->user_id, $item->is_road, $item->id); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + } + + public function deleteGeometry($itemID) + { + + $stmt = mysqli_prepare($this->connection, "DELETE FROM $this->tablename WHERE id = ?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $itemID); + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + } + + public function count() + { + $stmt = mysqli_prepare($this->connection, "SELECT COUNT(*) AS COUNT FROM $this->tablename"); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_result($stmt, $rec_count); + $this->throwExceptionOnError(); + + mysqli_stmt_fetch($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rec_count; + } + + public function getGeometry_paged($startIndex, $numItems) + { + + $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename LIMIT ?, ?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'ii', $startIndex, $numItems); + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->name); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + private function throwExceptionOnError($link = null) + { + if ($link == null) + { + $link = $this->connection; + } + if (mysqli_error($link)) + { + $msg = mysqli_errno($link) . ": " . mysqli_error($link); + throw new Exception('MySQL Error - ' . $msg); + } + } + +} + +?> diff --git a/site/stackreach/models/services/ModelService.php b/site/stackreach/models/services/ModelService.php new file mode 100644 index 0000000..123383c --- /dev/null +++ b/site/stackreach/models/services/ModelService.php @@ -0,0 +1,269 @@ + $v) { + $this->{$k} = mysql_real_escape_string($v); + } + } +} + +class ModelService extends Database +{ + + var $tablename = "model"; + var $connection; + + public function __construct($tablename="") + { + if (! empty($tablename)) + $this->tablename = $tablename; + + $this->connection = mysqli_connect( + $this->server, + $this->username, + $this->password, + $this->databasename + ); + + $this->throwExceptionOnError($this->connection); + } + + public function getAllModels($updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename"; + else + $query = "SELECT * FROM $this->tablename WHERE approved=1"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getAllModelsByBrand($brand, $updater = false) + { + if ($updater) + $query = "SELECT * FROM $this->tablename where brand_id=?"; + else + $query = "SELECT * FROM $this->tablename where brand_id=? AND approved=1"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $brand); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getAllModelsByGeometry($geo, $updater = false) + { + + if ($updater) + $query = "SELECT * FROM $this->tablename where geometry_id=?"; + else + $query = "SELECT * FROM $this->tablename where geometry_id=? and approved=1"; + + $stmt = mysqli_prepare($this->connection, $query); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $geo); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + public function getModelByID($itemID) + { + + $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename where id=?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $itemID); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + + if (mysqli_stmt_fetch($stmt)) + { + return $row; + } + else + { + return null; + } + } + + public function createModel($item) + { + + $stmt = mysqli_prepare($this->connection, "INSERT INTO $this->tablename (brand_id, geometry_id, name, notes, approved, user_id) VALUES (?, ?, ?, ?, ?, ?)"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'iissii', $item->brand_id, $item->geometry_id, $item->name, $item->notes, $item->approved, $item->user_id); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $autoid = mysqli_stmt_insert_id($stmt); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $autoid; + } + + public function updateModel($item) + { + + $stmt = mysqli_prepare($this->connection, "UPDATE $this->tablename SET brand_id=?, geometry_id=?, name=?, notes=?, approved=?, user_id=? WHERE id=?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'iissiii', $item->brand_id, $item->geometry_id, $item->name, $item->notes, $item->approved, $item->user_id, $item->id); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + } + + public function deleteModel($itemID) + { + + $stmt = mysqli_prepare($this->connection, "DELETE FROM $this->tablename WHERE id = ?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'i', $itemID); + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + } + + public function count() + { + $stmt = mysqli_prepare($this->connection, "SELECT COUNT(*) AS COUNT FROM $this->tablename"); + $this->throwExceptionOnError(); + + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_result($stmt, $rec_count); + $this->throwExceptionOnError(); + + mysqli_stmt_fetch($stmt); + $this->throwExceptionOnError(); + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rec_count; + } + + public function getModel_paged($startIndex, $numItems) + { + + $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename LIMIT ?, ?"); + $this->throwExceptionOnError(); + + mysqli_stmt_bind_param($stmt, 'ii', $startIndex, $numItems); + mysqli_stmt_execute($stmt); + $this->throwExceptionOnError(); + + $rows = array(); + + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + + while (mysqli_stmt_fetch($stmt)) + { + $rows[] = $row; + $row = new stdClass(); + mysqli_stmt_bind_result($stmt, $row->id, $row->brand_id, $row->geometry_id, $row->name, $row->notes, $row->approved, $row->user_id); + } + + mysqli_stmt_free_result($stmt); + mysqli_close($this->connection); + + return $rows; + } + + private function throwExceptionOnError($link = null) + { + if ($link == null) + { + $link = $this->connection; + } + if (mysqli_error($link)) + { + $msg = mysqli_errno($link) . ": " . mysqli_error($link); + throw new Exception('MySQL Error - ' . $msg); + } + } + +} + +?> diff --git a/site/stackreach/mysql.class.php b/site/stackreach/mysql.class.php new file mode 100755 index 0000000..6d82189 --- /dev/null +++ b/site/stackreach/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/stackreach/paths.php b/site/stackreach/paths.php new file mode 100755 index 0000000..65b0936 --- /dev/null +++ b/site/stackreach/paths.php @@ -0,0 +1,10 @@ + diff --git a/site/stackreach/road.php b/site/stackreach/road.php new file mode 100755 index 0000000..00cb98a --- /dev/null +++ b/site/stackreach/road.php @@ -0,0 +1,50 @@ +getAllBrands(); + + $brandMap = array(); + + foreach ($brands as $brand) + { + + $geometryService = new GeometryService(); + $geometries = $geometryService->getAllRoadGeometriesByBrand($brand->id); + + foreach ($geometries as $geometry) + { + $modelService = new ModelService(); + $brandMap[$brand->name][$geometry->name]['models'] = $modelService->getAllModelsByGeometry($geometry->id); + + $frameService = new FrameService(); + $frames = $frameService->getAllFramesByGeometry($geometry->id); + + if ($frames === null) { header('location:add_frame.php');} + + foreach ($frames as $frame) + { + $brandMap[$brand->name][$geometry->name]['geometries'][] = $frame; + } + } + } + + $smarty = new Smarty; + $smarty->assign('brandMap', $brandMap); + $smarty->display('views/index.tpl'); + +} +catch (Exception $e) +{ + echo 'Caught exception: ', $e->getMessage(), "\n"; +} + +?> + diff --git a/site/stackreach/select_preferred.php b/site/stackreach/select_preferred.php new file mode 100755 index 0000000..de7262b --- /dev/null +++ b/site/stackreach/select_preferred.php @@ -0,0 +1,94 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $sql = "DELETE FROM preferred WHERE user_id=:user_id"; + $sth = $dbh->prepare($sql); + $sth->execute(array(':user_id' => get_user_id())); + + $user_id = get_user_id(); + + foreach ($ids as $id) + { + $sql = "INSERT INTO preferred (user_id, brand_id) VALUES (:user_id, :brand_id)"; + $sth = $dbh->prepare($sql); + $sth->execute(array(':user_id' => $user_id, ':brand_id' => $id)); + } +} + +function get_preferred_brands() +{ + global $host, $dbname, $user, $pass; + $dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); + $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + # creating the statement + $sql = "SELECT brand_id from preferred where user_id=:user_id"; + $sth = $dbh->prepare($sql); + $sth->setFetchMode(PDO::FETCH_OBJ); + $sth->execute(array(':user_id' => get_user_id())); + + $brands = $sth->fetchAll(); + foreach ($brands as $brand) + { + $ret[$brand->brand_id] = $brand->brand_id; + } + + return $ret; + +} + + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + try + { + save_preferred_brands ($_POST['ids']); + header('location:view_preferred.php'); + } + catch (Exception $e) + { + echo $e->getMessage(); + } +} +else +{ + try + { + $brandService = new BrandService(); + $brands = $brandService->getAllBrands(); + $preferred = get_preferred_brands(); + + foreach ($brands as $brand) + { + if (isset($preferred[$brand->id])) + { + $brand->checked = true; + } + } + + $smarty = new Smarty; + $smarty->assign('brands', $brands); + $smarty->display('views/select_preferred.tpl'); + } + catch (Exception $e) + { + echo $e->getMessage(); + } +} +?> diff --git a/site/stackreach/selectbrand.php b/site/stackreach/selectbrand.php new file mode 100755 index 0000000..2a9f507 --- /dev/null +++ b/site/stackreach/selectbrand.php @@ -0,0 +1,25 @@ +getAllBrands (); + + $smarty = new Smarty; + $smarty->assign ('brands', $brands); + $smarty->assign ('action', "selectbrand.php"); + $smarty->assign ('current_brand', $_SESSION['brand']); + $smarty->display ('views/selectbrand.tpl'); +} +?> diff --git a/site/stackreach/update_brand.php b/site/stackreach/update_brand.php new file mode 100755 index 0000000..71030ce --- /dev/null +++ b/site/stackreach/update_brand.php @@ -0,0 +1,82 @@ +assign('values', $values); + $smarty->assign('errors', $errors); + $smarty->display('views/update_brand.tpl'); +} + +function VerifyForm(&$values, &$errors) +{ + $ret = true; + $url = htmlspecialchars($values['website']); + if (!preg_match("/^(https?:\/\/+[\w\-]+\.[\w\-]+)/i", $url)) + { + $errors["website"] = "Please check the website and resubmit"; + $ret = false; + } + if (strlen($values['name']) < 2) + { + $errors["name"] = "Please check the brand name and resubmit"; + $ret = false; + } + + return $ret; +} + +function ProcessForm($values) +{ + $brand = new Brand($values); + $brand->approved = 0; + $brand->user_id = get_user_id(); + + $brandService = new BrandService(); + $ret = $brandService->updateBrand($brand); + + header("location:brands.php?brand=$brand->name"); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + $formValues = $_POST; + $formErrors = array(); + + try + { + if (!VerifyForm($formValues, $formErrors)) + DisplayForm($formValues, $formErrors); + else + ProcessForm($formValues); + } + catch (Exception $e) + { + echo $e->getMessage(); + DisplayForm($formValues, $formErrors); + } +} +else +{ + if (isset($_GET['brand_id'])) + { + $brand_id = $_GET['brand_id']; + + $brandService = new BrandService(); + $brand = $brandService->getBrandByID($brand_id); + if ($brand !== null) + DisplayForm((array) $brand, null); + else + header('location:brands.php'); + } +} + + +?> + diff --git a/site/stackreach/update_frame.php b/site/stackreach/update_frame.php new file mode 100755 index 0000000..8154a5d --- /dev/null +++ b/site/stackreach/update_frame.php @@ -0,0 +1,93 @@ +getAllGeometriesByBrand ($values['brand_id']); + + $brandService = new BrandService(); + $brand = $brandService->getBrandByID ($values['brand_id']); + + $smarty = new Smarty; + $smarty->assign ('values', $values); + $smarty->assign ('errors', $errors); + $smarty->assign ('geometries', $geometries); + $smarty->assign ('brand', $brand); + + $smarty->display ('views/update_frame.tpl'); +} + +function VerifyForm (&$values, &$errors) +{ + return VerifyFrame ($values, $errors); +} + +function ProcessForm ($values) +{ + + $frame = new Frame ($values); + $frame->approved = 0; + $frame->user_id = get_user_id (); + + + $frameService = new FrameService(); + $frameService->updateFrame ($frame); + + header ('location:frames.php?brand=' . $values['brand']); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + $formValues = $_POST; + $formErrors = array (); + + if (!isset($_POST['internal_headset'])) + $formValues['internal_headset'] = 0; + else + $formValues['internal_headset'] = 1; + + if (!isset($_POST['is_650'])) + $formValues['is_650'] = 0; + else + $formValues['is_650'] = 1; + + try + { + if (!VerifyForm ($formValues, $formErrors)) + DisplayForm ($formValues, $formErrors); + else + ProcessForm ($formValues); + } + catch (Exception $e) + { + echo $e->getMessage (); + DisplayForm ($formValues, $formErrors); + } +} +else +{ + + $frame_id = $_GET['id']; + + if ($frame_id !== null) + { + + $frameService = new FrameService(); + $frame = $frameService->getFrameByID ($frame_id); + + if ($frame !== null) + DisplayForm ((array) $frame, null); + else + header ('location:frames.php'); + } +} +?> diff --git a/site/stackreach/update_geometry.php b/site/stackreach/update_geometry.php new file mode 100755 index 0000000..4788522 --- /dev/null +++ b/site/stackreach/update_geometry.php @@ -0,0 +1,89 @@ +assign ('values', $values); + $smarty->assign ('errors', $errors); + + $smarty->display ('views/update_geometry.tpl'); +} + +function VerifyForm (&$values, &$errors) +{ +// if (!preg_match("/^(https?:\/\/+[\w\-]+\.[\w\-]+)/i", $url)) +// { +// $errors["website"] = "Please check the website and resubmit"; +// $ret = false; +// } + + return true; +} + +function ProcessForm ($values) +{ + $geometry = new Geometry ($values); + $geometry->approved = 0; + $geometry->user_id = get_user_id (); + + try + { +// echo __LINE__ . "\n"; + $geometryService = new GeometryService(); + $geometryService->updateGeometry ($geometry); +// echo __LINE__ . "\n"; + } + catch (Exception $e) + { +// echo 'Caught exception: ', $e->getMessage (), "\n"; + return; + } + + header ('location:geometries.php?brand=' . $values['brand']); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + $formValues = $_POST; + $formErrors = array (); + + if (isset ($_POST['is_road'])) + $formValues['is_road'] = 1; + else + $formValues['is_road'] = 0; + + try + { + if (!VerifyForm ($formValues, $formErrors)) + DisplayForm ($formValues, $formErrors); + else + ProcessForm ($formValues); + } + catch (Exception $e) + { + echo $e->getMessage (); + DisplayForm ($formValues, $formErrors); + } +} +else +{ + $geoID = $_GET['id']; + + if ($geoID !== null) + { + $geometryService = new GeometryService(); + $geometry = $geometryService->getGeometryByID ($geoID); + if ($geometry !== null) + DisplayForm ((array) $geometry, null); + else + header ('location:geometries.php'); + } +} +?> diff --git a/site/stackreach/update_model.php b/site/stackreach/update_model.php new file mode 100755 index 0000000..dea16e7 --- /dev/null +++ b/site/stackreach/update_model.php @@ -0,0 +1,84 @@ +getAllGeometriesByBrand($values['brand_id']); + + $smarty = new Smarty; + $smarty->assign('values', $values); + $smarty->assign('geometries', $geometries); + $smarty->assign('errors', $errors); + $smarty->display('views/update_model.tpl'); +} + +function VerifyForm(&$values, &$errors) +{ +// $ret = true; +// $url = htmlspecialchars($values['website']); +// if (!preg_match("/^(https?:\/\/+[\w\-]+\.[\w\-]+)/i", $url)) +// { +// $errors["website"] = "Please check the website and resubmit"; +// $ret = false; +// } +// if (strlen($values['name']) < 2) +// { +// $errors["name"] = "Please check the brand name and resubmit"; +// $ret = false; +// } + + return true; +} + +function ProcessForm($values) +{ + $model = new Model($values); + $model->approved = 0; + $model->user_id = get_user_id(); + + $modelService = new ModelService(); + $modelService->updateModel($model); + header('location:models.php'); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST') +{ + $formValues = $_POST; + $formErrors = array(); + + try + { + if (!VerifyForm($formValues, $formErrors)) + DisplayForm($formValues, $formErrors); + else + ProcessForm($formValues); + } + catch (Exception $e) + { + echo $e->getMessage(); + DisplayForm($formValues, $formErrors); + } +} +else +{ + if (isset($_GET['model_id'])) + { + $model_id = $_GET['model_id']; + $modelService = new ModelService(); + $model = $modelService->getModelByID($model_id); + if ($model !== null) + DisplayForm((array) $model, null); + else + header('location:models.php'); + } +} + +?> diff --git a/site/stackreach/view_preferred.php b/site/stackreach/view_preferred.php new file mode 100755 index 0000000..d5557df --- /dev/null +++ b/site/stackreach/view_preferred.php @@ -0,0 +1,81 @@ +setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); + + # creating the statement + $sql = "SELECT brand_id from preferred where user_id=:user_id"; + $sth = $dbh->prepare($sql); + $sth->setFetchMode(PDO::FETCH_OBJ); + $sth->execute(array(':user_id' => get_user_id())); + $preferred = $sth->fetchAll(); + + + foreach ($preferred as $brand) + { + $bs = new BrandService(); + $brands[] = $bs->getBrandByID($brand->brand_id); + $bs = null; + } + + $brandMap = array(); + + foreach ($brands as $brand) + { + + $geometryService = new GeometryService(); + $geometries = $geometryService->getAllGeometriesByBrand($brand->id); + + foreach ($geometries as $geometry) + { + $modelService = new ModelService(); + $brandMap[$brand->name][$geometry->name]['models'] = $modelService->getAllModelsByGeometry($geometry->id); + + $frameService = new FrameService(); + $frames = $frameService->getAllFramesByGeometry($geometry->id); + + + if ($frames === null) { header('location:add_frame.php');} + + foreach ($frames as $frame) + { + $brandMap[$brand->name][$geometry->name]['geometries'][] = $frame; + } + } + } + + $smarty = new Smarty; + $smarty->assign('brandMap', $brandMap); + $smarty->display('views/index.tpl'); + +} +catch(PDOException $e) +{ + echo 'Caught exception: ', $e->getMessage(), "\n"; +} +catch (Exception $e) +{ + echo 'Caught exception: ', $e->getMessage(), "\n"; +} + +?> + diff --git a/site/triclubs/add.php b/site/triclubs/add.php new file mode 100644 index 0000000..d485618 --- /dev/null +++ b/site/triclubs/add.php @@ -0,0 +1,333 @@ + + +"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); +?> + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + +

    Thank you

    + Thank you. Your club should be added within 24 hours. You will now be redirected back to the add page.

    "; + echo ""; + } else if($confirm == 1) { ?> +

    Add a Triathlon Club: Step 2 of 2

    + +

    Add a Triathlon Club: Step 1 of 2

    + +

    Thank you

    + +

    If you would like to add your triathlon club to our website, simply fill out the form below. Be sure to fill out every field. After filling out each field, click submit. You will then be prompted to confirm your information before the information is sent to us.

    + + + + + +
    +

    +
    +
    +
    Club Name
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Address 2
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    President
    +
    +
    + +
    +
    +
    +
    Board Members(s)
    +
    +
    + >None + >Yes, Their Names: + +
    +
    +
    +
    Total Membership
    +
    +
    + (number of members only) +
    +
    +
    +
    Dues
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Club Info
    +
    +
    + +
    +
    +
    +
    Sponsors
    +
    +
    + +
    +
    +
    +
    Discounts
    +
    +
    + +
    +
    +
    +
    Directions to Workouts & Meeting Location(s)
    +
    +
    + +
    +
    +
    +
    Workout
    +
    +
    + +
    +
    +
    +
    Meetings
    +
    +
    + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + Thank you. Your club should be added within 24 hours. You will now be redirected back to the add page.

    "; + echo ""; + } + + if($confirm == 1){ + $confirm = 0; + include("include_add_confirm.php"); + } + } ?> + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/triclubs/add_X.php b/site/triclubs/add_X.php new file mode 100644 index 0000000..9b19eb8 --- /dev/null +++ b/site/triclubs/add_X.php @@ -0,0 +1,124 @@ +"; + $errmsg = rtrim($errmsg, ", "); + } + if (!is_numeric($_POST[membership])) $errmsg = $errmsg."Membership must be a number ONLY
    "; + $start_url = "(http(s)?\:\/\/)?"; // start url + $dots = "([\w_-]{2,}\.)+"; // one or more parts containing a '.' at the end + $last_part = "([\w_-]{2,})"; // last part doesn't contain a dot + $user = "((\/)(\~)[\w_=-]+)?((\/)[\w_=-]+)*"; // maybe subdirectories - possibly with user ~ + $end = "((\/)|(\/)[\w_-]+\.[\w]{2,})?"; // maybe a slash at the end or slash+file+extension + $qstring1 = "((\?[\w_-]+\=([^\#]+)){0,1}"; // querystring - first argument (?a=b) + $qstring2 = "(\&[\w_-]+\=([^\#]+))*)?"; // querystring - following arguments (&c=d) + $bkmrk = "(#[\w_-]+)?"; // bookmark + + $exp = "/^".$start_url.$dots.$last_part.$user.$end.$qstring1.$qstring2.$bkmrk."$/i"; + if( !preg_match($exp, $_POST[website]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
    "; + } + if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[name]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Please use only letters and numbers in the name
    "; + } + if(!$errmsg){ + + $name = trim($_POST[name]); + $name_tag = strtolower(str_replace(" ","", $name)); + if(strlen($nametag) > 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = mysql_escape_string(trim($_POST[address])); + if (isset($_POST['address_two'])) { $address_two = mysql_escape_string(trim($_POST[address_two])); } else { $address_two = NULL; } + $city = mysql_escape_string(trim($_POST[city])); + $state = $_POST[state]; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = mysql_escape_string(trim($_POST[zip])); + $email = mysql_escape_string(trim($_POST[email])); + $website = mysql_escape_string(trim($_POST[website])); + $president = mysql_escape_string(trim($_POST[president])); + $dues = mysql_escape_string(trim($_POST[dues])); + $membership = mysql_escape_string(trim($_POST[membership])); + $board = $_POST[board]; + if ( $board == 0 ){ $board_names = NULL; }else{ $board_names = mysql_escape_string(trim($_POST[board_names])); } + $info = mysql_escape_string(nl2br(substr(trim($_POST[info]), 0, 4096))); + $sponsors = mysql_escape_string(nl2br(substr(trim($_POST[sponsors]), 0, 4096))); + $discounts = mysql_escape_string(nl2br(substr(trim($_POST[discounts]), 0, 4096))); + $directions = mysql_escape_string(nl2br(substr(trim($_POST[directions]), 0, 4096))); + $workouts = mysql_escape_string(nl2br(substr(trim($_POST[workouts]), 0, 4096))); + $meetings = mysql_escape_string(nl2br(substr(trim($_POST[meetings]), 0, 4096))); + $submitted_by = $_POST[submitted_by]; + + if($_POST[confirm1] == 1){ + $sql = "INSERT INTO ".$prefix."Triclubs (triclub_name, triclub_name_tag, triclub_address, triclub_address_two, triclub_city, triclub_state, triclub_state_tag, triclub_zip, triclub_email, triclub_website, triclub_president, triclub_board, triclub_board_names, triclub_membership, triclub_dues, triclub_info, triclub_sponsors, triclub_discounts, triclub_directions, triclub_workouts, triclub_meetings, triclub_submitted_by, triclub_valid) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$email', '$website', '$president', $board, '$board_names', '$membership', '$dues', '$info', '$sponsors', '$discounts', '$directions', '$workouts', '$meetings', '$submitted_by', 0)"; + //echo("shop entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + //exit(); + }else{ + //echo("shop NOT entered."); + $confirm = 1; +} + } +//}else{ + // $errmsg = 'Incorrect key.'; +//} +?> diff --git a/site/triclubs/ajax.rate.item.php b/site/triclubs/ajax.rate.item.php new file mode 100644 index 0000000..2b62953 --- /dev/null +++ b/site/triclubs/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/triclubs/class/mysql.class.php b/site/triclubs/class/mysql.class.php new file mode 100644 index 0000000..6d82189 --- /dev/null +++ b/site/triclubs/class/mysql.class.php @@ -0,0 +1,339 @@ +persistency = $persistency; + $this->user = $sqluser; + $this->password = $sqlpassword; + $this->server = $sqlserver; + $this->dbname = $database; + + if($this->persistency) + { + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $this->password); + } + else + { + $this->db_connect_id = @mysql_connect($this->server, $this->user, $this->password); + } + if($this->db_connect_id) + { + if($database != "") + { + $this->dbname = $database; + $dbselect = @mysql_select_db($this->dbname); + if(!$dbselect) + { + @mysql_close($this->db_connect_id); + $this->db_connect_id = $dbselect; + } + } + return $this->db_connect_id; + } + else + { + return false; + } + } + + // + // Other base methods + // + function sql_close() + { + if($this->db_connect_id) + { + if($this->query_result) + { + @mysql_free_result($this->query_result); + } + $result = @mysql_close($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + + // + // Base query method + // + function sql_query($query = "", $transaction = FALSE) + { + // Remove any pre-existing queries + unset($this->query_result); + if($query != "") + { + + $this->query_result = @mysql_query($query, $this->db_connect_id); + + } + if($this->query_result) + { + unset($this->row[$this->query_result]); + unset($this->rowset[$this->query_result]); + return $this->query_result; + } + else + { + return ( $transaction == END_TRANSACTION ) ? true : false; + } + } + + // + // Other query methods + // + function sql_numrows($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_rows($query_id); + return $result; + } + else + { + return false; + } + } + function sql_affectedrows() + { + if($this->db_connect_id) + { + $result = @mysql_affected_rows($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_numfields($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_num_fields($query_id); + return $result; + } + else + { + return false; + } + } + function sql_fieldname($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_name($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fieldtype($offset, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_field_type($query_id, $offset); + return $result; + } + else + { + return false; + } + } + function sql_fetchrow($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $this->row[$query_id] = @mysql_fetch_array($query_id); + return $this->row[$query_id]; + } + else + { + return false; + } + } + function sql_fetchrowset($query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + while($this->rowset[$query_id] = @mysql_fetch_array($query_id)) + { + $result[] = $this->rowset[$query_id]; + } + return $result; + } + else + { + return false; + } + } + function sql_fetchfield($field, $rownum = -1, $query_id = 0) + { + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + if($rownum > -1) + { + $result = @mysql_result($query_id, $rownum, $field); + } + else + { + if(empty($this->row[$query_id]) && empty($this->rowset[$query_id])) + { + if($this->sql_fetchrow()) + { + $result = $this->row[$query_id][$field]; + } + } + else + { + if($this->rowset[$query_id]) + { + $result = $this->rowset[$query_id][$field]; + } + else if($this->row[$query_id]) + { + $result = $this->row[$query_id][$field]; + } + } + } + return $result; + } + else + { + return false; + } + } + function sql_rowseek($rownum, $query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + if($query_id) + { + $result = @mysql_data_seek($query_id, $rownum); + return $result; + } + else + { + return false; + } + } + function sql_nextid(){ + if($this->db_connect_id) + { + $result = @mysql_insert_id($this->db_connect_id); + return $result; + } + else + { + return false; + } + } + function sql_freeresult($query_id = 0){ + if(!$query_id) + { + $query_id = $this->query_result; + } + + if ( $query_id ) + { + unset($this->row[$query_id]); + unset($this->rowset[$query_id]); + + @mysql_free_result($query_id); + + return true; + } + else + { + return false; + } + } + function sql_error($query_id = 0) + { + $result["message"] = @mysql_error($this->db_connect_id); + $result["code"] = @mysql_errno($this->db_connect_id); + + return $result; + } + +} // class sql_db + +} // if ... define + +?> diff --git a/site/triclubs/class/rating/ajax.rate.item.php b/site/triclubs/class/rating/ajax.rate.item.php new file mode 100644 index 0000000..38c90de --- /dev/null +++ b/site/triclubs/class/rating/ajax.rate.item.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/triclubs/class/rating/classes/database.class.php b/site/triclubs/class/rating/classes/database.class.php new file mode 100644 index 0000000..bebb80c --- /dev/null +++ b/site/triclubs/class/rating/classes/database.class.php @@ -0,0 +1,406 @@ + $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + case "mysqli": + $row = 0; + while ($currentResult = @mysqli_fetch_assoc(self::$savedQueries[$name])) + { + $col = 0; + foreach ($currentResult as $key => $value) + { + $results[$row][$col] = $value; + $results[$row][$key] = $value; + $col++; + } + + $row++; + } + break; + } + + self::$savedResults[$name] = $results; + } + else + { + $results = self::$savedResults[$name]; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Fetch Results Name Missing", "The name parameter was empty, the name is required so it knows which results to return."); + } + else + { + Error::LogError("Fetch Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + + return $results; + } + + // Free SQL Query Results + // Returns nothing + public static function FreeResults($name) + { + if (self::$connection) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedQueries)) + { + switch (self::$type) + { + case "mysql": + @mysql_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysql_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + case "mysqli": + @mysqli_free_result(self::$savedQueries[$name]) or Error::LogError("Free Results Error", mysqli_error(self::$connection)); + unset(self::$savedQueries[$name]); + break; + } + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Free Results Name Missing", "The name parameter was empty, the name is required so it knows which results to free up from memory."); + } + else + { + Error::LogWarning("Free Results Name ('{$name}') Not Found", "The name provided did not have any query results associated with it."); + } + } + } + } + + // Remove Saved Results + // Returns nothing + public static function RemoveSavedResults($name) + { + if (strlen(trim($name)) != 0 && array_key_exists($name, self::$savedResults)) + { + unset(self::$savedResults[$name]); + } + else + { + if (strlen(trim($name)) == 0) + { + Error::LogError("Remove Saved Result Name Missing", "The name parameter was empty, the name is required so it knows which query to remove."); + } + else + { + Error::LogWarning("Remove Saved Result Name ('{$name}') Not Found", "The name provided was not a saved query."); + } + } + } + + // Attempt Connect To Database + // Returns true or false depending on if the connection failed or succeeded + public static function AttemptConnectToDatabase($varType, $varHost, $varPort, $varDatabase, $varUsername, $varPassword) + { + self::$type = $varType; + self::$host = $varHost; + self::$port = $varPort; + self::$database = $varDatabase; + self::$username = $varUsername; + self::$password = $varPassword; + + Error::ClearErrors(); + self::$connection = self::ConnectToDatabase(); + + if (!Error::HasErrors()) + { + return true; + } + else + { + return false; + } + } + + // MySQL Version + // Returns the mysql version number + public static function MysqlVersion() + { + $version = ""; + if (self::$connection) + { + switch (self::$type) + { + case "mysql": + $version = mysql_get_server_info(self::$connection); + break; + case "mysqli": + $version = mysqli_get_server_info(self::$connection); + break; + } + } + + return $version; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Connect to Database + // Returns the database connection resource + private static function ConnectToDatabase() + { + $link = null; + + switch (self::$type) + { + case "mysql": + if (strlen(trim(self::$port)) != 0) + { + $link = mysql_connect(self::$host . ":" . self::$port, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + else + { + $link = mysql_connect(self::$host, self::$username, self::$password) or Error::LogError("Database Error", mysql_error()); + } + break; + case "mysqli": + $link = mysqli_connect(self::$host, self::$username, self::$password, self::$database, self::$port) or Error::LogError("Database Error", mysqli_connect_error()); + break; + } + + return $link; + } + + // Select the Database + // Returns nothing + private static function SelectTheDatabase() + { + switch (self::$type) + { + case "mysql": + @mysql_select_db(self::$database, self::$connection) or Error::LogError("Database Selection", mysql_error(self::$connection)); + break; + } + } + + // Valid Database Types + // Returns true or false depending on if the database type is valid + private static function ValidDatabaseTypes($varType) + { + $types = split(',', str_replace(" ", "", self::DB_TYPES)); + + return in_array($varType, $types); + } + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/triclubs/class/rating/classes/error.class.php b/site/triclubs/class/rating/classes/error.class.php new file mode 100644 index 0000000..311343e --- /dev/null +++ b/site/triclubs/class/rating/classes/error.class.php @@ -0,0 +1,258 @@ + 0) + { + if (self::$numErrors > 1) + { + $error = "ERRORS"; + } + else + { + $error = "ERROR"; + } + + // Loop through Error Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "ERROR") + { + // Output each individual Error + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Error Template Output + $output = "
    \r\n" . + "
    {$error}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Error Message Output + return $output; + } + + // Retrieve Last Error + // Returns the title and description of the last error in an array + public static function RetrieveLastError() + { + $output = array(); + + // Check to see if 1 error occurred or more than one. + if (self::$numErrors > 0) + { + for ($i = sizeof(self::$title) - 1; $i >= 0; $i++) + { + if (self::$type[$i] == "ERROR") + { + array_push($output, self::$title[$i]); + array_push($output, self::$description[$i]); + break; + } + } + } + + return $output; + } + + // Clear Errors + // Returns nothing + public static function ClearErrors() + { + self::$numErrors = 0; + + for ($i = 0; $i < sizeof(self::$type); $i++) + { + if (self::$type[$i] == "ERROR") + { + self::$title[$i] = null; + self::$type[$i] = null; + self::$description[$i] = null; + self::$datetime[$i] = null; + } + } + } + + // Has Errors + // Returns true or false on whether errors exist + public static function HasErrors() + { + if (self::$numErrors > 0) + { + return true; + } + + return false; + } + + // Log Warning Method (receives Name and Description) + // Returns true or false depending on if logging the warning was successful + public static function LogWarning($varTitle, $varDescription) + { + // Check Parameters + if (strlen(trim($varTitle)) != 0 && strlen(trim($varDescription)) != 0) + { + array_push(self::$title, $varTitle); + array_push(self::$type, "WARNING"); + array_push(self::$description, $varDescription); + array_push(self::$datetime, date("m/d/Y H:i:s")); + self::$numWarnings++; + + return true; + } + + return false; + } + + // Show Warning Messages + // Returns the Warning Message Output (in HTML format) + public static function ShowWarningMessages() + { + $output = ""; + + // Check to see if 1 warning occurred or more than one. + if (self::$numWarnings > 0) + { + if (self::$numWarnings > 1) + { + $warning = "WARNINGS"; + } + else + { + $warning = "WARNING"; + } + + // Loop through Warning Messages + for ($i = 0; $i < sizeof(self::$title); $i++) + { + if (self::$type[$i] == "WARNING") + { + // Output each individual Warning + $output .= "
    \r\n" . + " " . self::$title[$i] . "\r\n" . + " at " . self::$datetime[$i] . "\r\n" . + "
    \r\n" . + "
    " . self::$description[$i] . "

    \r\n"; + } + } + + // Write Warning Template Output + $output = "
    \r\n" . + "
    {$warning}:
    \r\n" . + "
    \r\n" . $output . "\r\n
    \r\n" . + "
    \r\n"; + } + + // Return the Warning Message Output + return $output; + } + + // Has Warnings + // Returns true or false on whether there are any Warnings + public static function HasWarnings() + { + if (self::$numWarnings > 0) + { + return true; + } + + return false; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + ## END PRIVATE METHODS + + ## PROTECTED METHODS + ## END PROTECTED METHODS + } +?> \ No newline at end of file diff --git a/site/triclubs/class/rating/classes/include.all.php b/site/triclubs/class/rating/classes/include.all.php new file mode 100644 index 0000000..2c1fa21 --- /dev/null +++ b/site/triclubs/class/rating/classes/include.all.php @@ -0,0 +1,7 @@ + diff --git a/site/triclubs/class/rating/classes/rating.class.php b/site/triclubs/class/rating/classes/rating.class.php new file mode 100644 index 0000000..57a49fc --- /dev/null +++ b/site/triclubs/class/rating/classes/rating.class.php @@ -0,0 +1,279 @@ +
    {$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + else + { + $classes = "rated " . Rating::ShowStars($averageStars); + $cat_info = Rating::FetchCategoryInfo($varItem); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + $output .= "
    {$cat_info['rating_cat_name']}
    \r\n"; + $output .= "
    {$cat_info['rating_cat_min']}
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    {$cat_info['rating_cat_max']}
    \r\n"; + } + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the item name for this function to find the average."); + } + + return $output; + } + + public static function OutputParentRating($varParent) + { + // Verify $varParent was provided + if ($varParent != null && strlen(trim($varParent)) != 0) + { + // Check if Magic QUotes is ON + if (!get_magic_quotes_gpc()) + { + $varParent = addslashes($varParent); + } + + // Information for the Output + $averageStars = Rating::CalculateAverageParentRating($varParent); + + $classes = "rated " . Rating::ShowStars($averageStars); + //$parent_info = Rating::FetchParentInfo($varParent); + + // Write Output HTML for the Rating Data + $output = "\r\n"; + //$output .= "
    Overall Rating
    "; + $output .= "
      \r\n"; + $output .= "
    • 1
    • \r\n"; + $output .= "
    • 2
    • \r\n"; + $output .= "
    • 3
    • \r\n"; + $output .= "
    • 4
    • \r\n"; + $output .= "
    • 5
    • \r\n"; + $output .= "
    \r\n"; + } + else + { + $output = ""; + // This is a major issue. NO information can be retrieve if an item name is not passed. + Error::LogError("Variable Missing", "You must provide the parent name for this function to find the average."); + } + + return $output; + } + + // Rate an Item + // Returns the name/value pair of new class names and the item name + public static function RateItem($varParent, $varItem, $varRating, $varClasses) + { + $newClassNames = $varClasses; + + // Verify $varName was provided + if ($varParent != null && strlen(trim($varParent)) != 0 + && $varItem != null && strlen(trim($varItem)) != 0 + && $varRating != null && strlen(trim($varRating)) != 0 && is_numeric($varRating) + && $varClasses != null && strlen(trim($varClasses)) != 0) + { + // Check if Magic Quotes is ON + if (!get_magic_quotes_gpc()) + { + $varItem = addslashes($varItem); + $varParent = addslashes($varParent); + } + + // Check to see that the user has not already rated this item + if (Rating::CheckRatingsByIp($varParent, $varItem) == 0) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + $tempTime = time(); + + Database::ExecuteQuery("INSERT INTO `gforum_TriclubsRating` (`triclub_id_fk`, `category_id_fk`, `rating_vote`, `rating_ip`, `rating_date`) VALUES ('{$varParent}', '{$varItem}', {$varRating}, '{$ipAddress}', '{$tempTime}')", "InsertRating"); + Database::FetchResults("InsertRating"); + Database::FreeResults("InsertRating"); + Database::RemoveSavedResults("InsertRating"); + + // Information for the Output + $averageStars = Rating::CalculateAverageRating($varParent, $varItem); + $newClassNames = "rated " . Rating::ShowStars($averageStars); + $averageStars = Rating::CalculateAverageParentRating($varParent); + $newClassParent = "rated " . Rating::ShowStars($averageStars); + } + } + else + { + // This is a major issue. NOT enough information was sent to log the item + Error::LogError("Variable(s) Missing", "You must provide all of the information to log the rating of this item."); + } + + // Build Name/Value Pair to return + $nameValue = "classes={$newClassNames}&item={$varItem}&parent={$varParent}&parentClass={$newClassParent}"; + return $nameValue; + } + ## END PUBLIC METHODS + + ## PRIVATE METHODS + // Fetch Category Names & Min/Max Values + private static function FetchCategoryInfo($varItem) + { + // Query Category Info for a specific Category ID + Database::ExecuteQuery("SELECT * FROM `gforum_TriclubsRatingCategory` WHERE `rating_cat_id`='{$varItem}'", "CategoryInfo"); + $results = Database::FetchResults("CategoryInfo"); + Database::FreeResults("CategoryInfo"); + Database::RemoveSavedResults("CategoryInfo"); + + return $results[0]; + + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageRating($varParent, $varItem) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_TriclubsRating` WHERE `category_id_fk`='{$varItem}' AND `triclub_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Calculate Average Rating + // Returns the number of stars to show + private static function CalculateAverageParentRating($varParent) + { + $averageStars = 0; + + // Query Average Rating for a specific Item + Database::ExecuteQuery("SELECT AVG(`rating_vote`) AS `averageRating` FROM `gforum_TriclubsRating` WHERE `triclub_id_fk`='{$varParent}'", "AverageRating"); + $results = Database::FetchResults("AverageRating"); + Database::FreeResults("AverageRating"); + Database::RemoveSavedResults("AverageRating"); + + // Round the Average into a Whole Number + if (sizeof($results) == 1) + { + if ($results[0]['averageRating'] != null) + { + $averageStars = round($results[0]["averageRating"], 0); + } + } + else + { + // This is simply a warning, as it isn't vital if no results were found, as the item may be new. + Error::LogWarning("Rating Data Missing", "No entries were found for '{$varName}', this might be the first entry."); + } + + return $averageStars; + } + + // Show Stars + // Returns the class information for the number of stars to show + private static function ShowStars($varStars) + { + // Select the Number of Stars Class + switch ($varStars) + { + case 1: + $classes .= "onestar"; + break; + case 2: + $classes .= "twostar"; + break; + case 3: + $classes .= "threestar"; + break; + case 4: + $classes .= "fourstar"; + break; + case 5: + $classes .= "fivestar"; + break; + default: + $classes .= "nostar"; + break; + } + + return $classes; + } + + // Check Ratings By IP Address + // Returns the number of ratings for an item by an ip address + private static function CheckRatingsByIp($varParent, $varItem) + { + $ipAddress = $_SERVER['REMOTE_ADDR']; + + Database::ExecuteQuery("SELECT COUNT(*) AS `totalRatings` FROM `gforum_TriclubsRating` WHERE `category_id_fk`='{$varItem}' AND `triclub_id_fk`='{$varParent}' AND `rating_ip`='{$ipAddress}'", "AlreadyRated"); + $results = Database::FetchResults("AlreadyRated"); + Database::FreeResults("AlreadyRated"); + Database::RemoveSavedResults("AlreadyRated"); + + // Check to see that the user has not already rated this item + if ($results != null && $results[0]['totalRatings'] != null) + { + return $results[0]['totalRatings']; + } + + return 0; + } + ## END PRIVATE METHODS + } +?> diff --git a/site/triclubs/class/rating/int.to.words.php b/site/triclubs/class/rating/int.to.words.php new file mode 100644 index 0000000..dd1e6cf --- /dev/null +++ b/site/triclubs/class/rating/int.to.words.php @@ -0,0 +1,55 @@ + "thirty", 40 => "forty", 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", 90 => "ninety" ); + +function int_to_words($x) { + global $nwords; + + if(!is_numeric($x)) + $w = '#'; + else if(fmod($x, 1) != 0) + $w = '#'; + else { + if($x < 0) { + $w = 'minus '; + $x = -$x; + } else + $w = ''; + // ... now $x is a non-negative integer. + + if($x < 21) // 0 to 20 + $w .= $nwords[$x]; + else if($x < 100) { // 21 to 99 + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + $w .= '-'. $nwords[$r]; + } else if($x < 1000) { // 100 to 999 + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + $w .= ' and '. int_to_words($r); + } else if($x < 1000000) { // 1000 to 999999 + $w .= int_to_words(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $w .= 'and '; + $w .= int_to_words($r); + } + } else { // millions + $w .= int_to_words(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) { + $w .= ' '; + if($r < 100) + $word .= 'and '; + $w .= int_to_words($r); + } + } + } + return $w; +} + +?> \ No newline at end of file diff --git a/site/triclubs/class/rating/rating-example.php b/site/triclubs/class/rating/rating-example.php new file mode 100644 index 0000000..187dc02 --- /dev/null +++ b/site/triclubs/class/rating/rating-example.php @@ -0,0 +1,71 @@ + + + + + + CSS Star Rating System fully functional using AJAX + + + + + +

    Race Rating System:

    + + + + + + + \ No newline at end of file diff --git a/site/triclubs/comments_add.php b/site/triclubs/comments_add.php new file mode 100644 index 0000000..cbaff9a --- /dev/null +++ b/site/triclubs/comments_add.php @@ -0,0 +1,35 @@ + + +
    + + + + +
    + +Add A Comment +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    + + +
    diff --git a/site/triclubs/comments_add_X.php b/site/triclubs/comments_add_X.php new file mode 100644 index 0000000..51c1a1a --- /dev/null +++ b/site/triclubs/comments_add_X.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/site/triclubs/comments_show.php b/site/triclubs/comments_show.php new file mode 100644 index 0000000..752ea42 --- /dev/null +++ b/site/triclubs/comments_show.php @@ -0,0 +1,18 @@ + + + +" data-num-posts="5" data-width="500">
    */ ?> +" num_posts="5" width="500">**/ ?> + diff --git a/site/triclubs/comments_validate.php b/site/triclubs/comments_validate.php new file mode 100644 index 0000000..5669fbf --- /dev/null +++ b/site/triclubs/comments_validate.php @@ -0,0 +1,88 @@ + + + + + + +
    + + +
    + + + + + +

    Unvalidated Comments

    +
    +
    + + + + "> + + + +
    Reviewed by: ".$commenter_user_username.""; echo " on ".date("F j, Y g:i A", $arrComments[comment_time]); echo " about ".$triclub_name."";?>
    + +
    Validate this comment. Delete this comment.
    +
    + +
    +
    + + +
    + +
    + + + \ No newline at end of file diff --git a/site/triclubs/comments_validate_X.php b/site/triclubs/comments_validate_X.php new file mode 100644 index 0000000..314f419 --- /dev/null +++ b/site/triclubs/comments_validate_X.php @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/site/triclubs/config.php b/site/triclubs/config.php new file mode 100644 index 0000000..d5662b2 --- /dev/null +++ b/site/triclubs/config.php @@ -0,0 +1,79 @@ += '4.0.4pl1' && strstr($_SERVER["HTTP_USER_AGENT"],'compatible')) { + if (extension_loaded('zlib')) { + ob_end_clean(); + ob_start('ob_gzhandler'); + } +} else if ($phpver > '4.0') { + if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) { + if (extension_loaded('zlib')) { + $do_gzip_compress = TRUE; + ob_start(array('ob_gzhandler',5)); + ob_implicit_flush(0); + header('Content-Encoding: gzip'); + } + } +} +$phpver = explode(".", $phpver); +$phpver = "$phpver[0]$phpver[1]"; +if ($phpver >= 41) { + $PHP_SELF = $_SERVER['PHP_SELF']; +} + +if (!ini_get("register_globals")) { + #import_request_variables('GPC'); +} + + +$statecount = mysql_num_rows(mysql_query("SELECT * FROM gforum_Triclubs WHERE triclub_valid = 1")); + +function curPageURL() { + $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); + $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); + $port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : ''; + $url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.$_SERVER["REQUEST_URI"]; + return $url; +} + +?> diff --git a/site/triclubs/delete_X.php b/site/triclubs/delete_X.php new file mode 100644 index 0000000..f753744 --- /dev/null +++ b/site/triclubs/delete_X.php @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/site/triclubs/include_add_confirm.php b/site/triclubs/include_add_confirm.php new file mode 100644 index 0000000..734429d --- /dev/null +++ b/site/triclubs/include_add_confirm.php @@ -0,0 +1,206 @@ +

    Please confirm your club information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your club information before submitting.

    + + +
    +
    +
    Club Name
    +
    +
    + +
    +
    +
    +
    Street Address
    +
    +
    + +
    +
    +
    +
    Street Address Two
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    President
    +
    +
    + +
    +
    +
    +
    Board Member(s)
    +
    +
    + +
    +
    +
    +
    Membership
    +
    +
    + +
    +
    +
    +
    Dues
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Club Info
    +
    +
    + +
    +
    +
    +
    Sponsors
    +
    +
    + +
    +
    +
    +
    Discounts
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    Workouts
    +
    +
    + +
    +
    +
    +
    Meetings
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + diff --git a/site/triclubs/include_breadcrumb.php b/site/triclubs/include_breadcrumb.php new file mode 100644 index 0000000..f272a64 --- /dev/null +++ b/site/triclubs/include_breadcrumb.php @@ -0,0 +1,12 @@ + diff --git a/site/triclubs/include_buttons.php b/site/triclubs/include_buttons.php new file mode 100644 index 0000000..9af7b0b --- /dev/null +++ b/site/triclubs/include_buttons.php @@ -0,0 +1,108 @@ + + +
    +
    + + + + + + +
    +
    " style="display: inline;"> + +
    + +
    " style="display: inline;"> + +
    + +
    " style="display: inline;"> + +
    + + + +
    + + +
    + +
    Entered By: $username"); + } +} +?> +
    diff --git a/site/triclubs/include_common_content.php b/site/triclubs/include_common_content.php new file mode 100644 index 0000000..e886434 --- /dev/null +++ b/site/triclubs/include_common_content.php @@ -0,0 +1,45 @@ + + + +> + + +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    +
    +
    diff --git a/site/triclubs/include_common_footer.php b/site/triclubs/include_common_footer.php new file mode 100644 index 0000000..7812696 --- /dev/null +++ b/site/triclubs/include_common_footer.php @@ -0,0 +1 @@ + diff --git a/site/triclubs/include_common_head.php b/site/triclubs/include_common_head.php new file mode 100644 index 0000000..605a8c0 --- /dev/null +++ b/site/triclubs/include_common_head.php @@ -0,0 +1,23 @@ + + + + + +Slowtwitch.com Triclub Database: <? echo $pagetitle; ?> + + + + + + + + + diff --git a/site/triclubs/include_edit_confirm.php b/site/triclubs/include_edit_confirm.php new file mode 100644 index 0000000..cd1fa6d --- /dev/null +++ b/site/triclubs/include_edit_confirm.php @@ -0,0 +1,221 @@ +

    Please confirm your club information. If everything is correct, click the submit button. Otherwise, you may click the edit button to change your club information before submitting.

    + +
    +
    +
    Club Name
    +
    +
    + +
    +
    +
    +
    Street Address
    +
    +
    + +
    +
    +
    +
    Street Address Two
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    President
    +
    +
    + +
    +
    +
    +
    Board Member(s)
    +
    +
    + +
    +
    +
    +
    Membership
    +
    +
    + +
    +
    +
    +
    Dues
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Club Info
    +
    +
    + +
    +
    +
    +
    Sponsors
    +
    +
    + +
    +
    +
    +
    Discounts
    +
    +
    + +
    +
    +
    +
    Directions
    +
    +
    + +
    +
    +
    +
    Workouts
    +
    +
    + +
    +
    +
    +
    Meetings
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + This data will be saved as a NEW CLUB. + + + + This data will be saved as a modification to the EXISTING CLUB. + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    diff --git a/site/triclubs/include_navigation.php b/site/triclubs/include_navigation.php new file mode 100644 index 0000000..faaddcc --- /dev/null +++ b/site/triclubs/include_navigation.php @@ -0,0 +1,64 @@ + + +
    +

    Browse TriClubs

    +
    +$currentregion ($regioncount)$state_string"; + echo ("
    " . $currentregion . " (" . $regioncount . ")+
    "); + echo $tempstring; + echo ("
    \n"); + } + $currentregion = $rowregionlist[regionlong]; + $currentrid = $rowregionlist[regionid]; + $currenttag = $rowregionlist[regionname]; + $regioncount = 0; + $tempstring = ''; + $state_string = ''; + } + if ($selected_item == $rowregionlist[statetag]) { + $selected_state = ' selected="selected"'; + } + $state_string .= ""; + $tempstring = $tempstring. "$rowregionlist[statelong] ($rowregionlist[numclubs])\n"; + $regioncount += $rowregionlist[numclubs]; +} + +echo ("
    ".$currentregion." (".$regioncount.")+
    "); +echo $tempstring; +echo ('
    '); +if ( $selected_item == 'top') { $selected_region = ' selected="selected"'; } +$region_dropdown .= ""; +?> + +
    +
    diff --git a/site/triclubs/include_sidebar.php b/site/triclubs/include_sidebar.php new file mode 100644 index 0000000..eb5439c --- /dev/null +++ b/site/triclubs/include_sidebar.php @@ -0,0 +1,14 @@ + + +
    + + + +
    + + diff --git a/site/triclubs/include_status.php b/site/triclubs/include_status.php new file mode 100644 index 0000000..a77b6cf --- /dev/null +++ b/site/triclubs/include_status.php @@ -0,0 +1,12 @@ + +
    Admin:"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table." WHERE ".$field_lead."_valid = 0")); + echo("
    Validate Entries (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Edits")); + echo("
    Validate Edits (".$unvalid_count.")"); + $unvalid_count = mysql_num_rows(mysql_query("SELECT * FROM ".$prefix.$main_table."Comment WHERE comment_valid = 0")); + echo("
    Validate Comments (".$unvalid_count.")"); +} +?> diff --git a/site/triclubs/include_store.php b/site/triclubs/include_store.php new file mode 100644 index 0000000..f8b55de --- /dev/null +++ b/site/triclubs/include_store.php @@ -0,0 +1,23 @@ +
    +
    +

    ">

    +
    + +

    (Avg. rating based on )

    + +
    + $row[triclub_address_two]"); } + echo("
    $row[triclub_city], $row[triclub_state] $row[triclub_zip]"); + ?> +
    Phone: +
    Fax: +
    +
    + Email: $row[triclub_email]"; ?>
    + Website: $row[triclub_website]"; ?>
    + "); } ?> + ">More info > +
    +
    diff --git a/site/triclubs/index.php b/site/triclubs/index.php new file mode 100644 index 0000000..6de567f --- /dev/null +++ b/site/triclubs/index.php @@ -0,0 +1,118 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Triathlon Clubs

    + + Add TriClub + +
    + + +
    +
    +
    + +
    + +

    Welcome to Slowtwitch.com's North American Triathlon & Multisport Club Database

    +

    clubs and counting. This collection of triclubs is the most complete and comprehensive + selection of tri-specific clubs in North America.

    + +

    Browsing the database

    +

    + You do not need to log in to do this. You'll find a list of clubs in + your region by clicking the regional links on the left. Click the (+) sign + and the region will expand to expose the individual states. Click on the + state to show that list of clubs in it. If you want to see clubs in + multiple states, but not those states we've aggregated into the regions you + see at left, you may do this via our Advanced Search. +

    + +

    Showing solidarity with your club

    +

    + When you see your local club listed here, you may click the "I'M A MEMBER" button. Your User Name will be added to the clubs's list of members, + just like your User Name appends to those races you choose when you build + your Slowtwitch Personal Race Calendar. Likewise, your Forum User Profile + will show that this is your club of choice. +

    + +

    How to enter a club

    +

    You must be a registered user to add a club to the database. There is + one common type of registration on Slowtwitch, and if you are registered to + post on our Reader Forum you are one of + + who have made a registration, + and this means you're able to add clubs to our database. +

    + If you're not registered, the login prompt is to the left of the page, near + the top. The registration process is straightforward, easy, and free. It + will require you to receive an email and click on a link to complete your + registration. All this should take you only a minute or two. Then... +

    + 1. Click the ADD A CLUB button to begin adding to the database. +

    + 2. Once you SUBMIT your club, you'll also need to CONFIRM your submission + via a link at the bottom of the page. +

    + 3. Once you successfully add your club, it will not immediately be visible + to you. We must validate the addition on our end before anyone can see it. + We do this so that spammers won't use the club registration as a way to spam + our database. +

    +

    How to edit published information about a triclub

    +

    Any registered user may edit information for a listing. We will review the full contents of each update before confirming any changes that are made. A list of all editors who have made changes is visible at the bottom of each listing. If an entry has been updated, but those changes have not yet been confirmed, this is evident via a note on the individual page for that particular entry. This is to prevent conflicting updates from occuring simultaneously. If you wish to update an entry with pending changes, please wait until we have had a chance to review those changes first. Someone may have already changed the information you were going to change yourself.

    +

    How to comment on a club

    +

    Any registered user may make a comment on a club listing. These comments are subject to validation by an administrator before being published.

    +

    Global tri club map

    +

    The map below shows the location of all registered Slowtwitch triathlon clubs around the globe. You can drag the map, zoom-in, zoom-out, and use any other of the standard Google Maps features. Anywhere you see a red icon, you can click to see the name of that triathlon club and a street address.

    + +
    +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/triclubs/individual.php b/site/triclubs/individual.php new file mode 100644 index 0000000..a2df0a0 --- /dev/null +++ b/site/triclubs/individual.php @@ -0,0 +1,207 @@ + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + +

    Triathlon Clubs

    + +
    + +
    + + Back +
    + + +
    +
    +

    +
    +
    + Comment +
    +
    +
    +
    + "); } ?> + ,
    + Phone:
    + Fax: +
    +
    + Email:
    + Website: +
    +
    + +

    Commenter: your comments have been submitted and will be validated within 24 hours.

    + + + +

    Editor: your changes have been submitted and will be validated within 24 hours.

    + + + +

    Group Edits: there are group edits waiting to be validated.

    + +
    + +
    +
    +

    Membership

    +
    + Club President:
    + Board Member(s):
    + Total Membership:
    + Club Dues: +
    +
    +
    +

    General Information

    +
    + Club Info: +
    + Club Sponsors: +
    + Club Discounts: +
    + Directions to Workouts & Meeting Location(s): +
    + Club Workout Schedule: +
    + Club Meetings & Events Schedule: +
    +
    +
    +
    +
    + +
    + + Map location is based off of a geocode of the addressed entered using Google's Google Maps API. If your address does not geocode properly, you can either update the address (we will attempt to re-geocode after any updates to your entry) or you can use Google's geocoding tool found here: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html to obtain a lat/long for your location and enter that. To use the utility, type in an address that is close to your location and then drag-and-drop the marker to obtain the desired lat/long. If you choose to enter a lat/long, you must check the box on the edit page that says, "override geocode with entered lat/long." + +
    +
    +
    +

    Racers

    +
    + + + 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$value'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i > 1){ echo ", "; } + echo "$temprow[user_username]"; + } + $i++; + } + ?> +
    +
    +
    + + +

    +
    + = 0){ + $tempresults = mysql_query("SELECT user_username FROM ".$prefix."User WHERE user_id='$row[user_id_fk]'") or die (mysql_error()); + $temprow = mysql_fetch_array($tempresults); + if($i >= 1){ echo "
    "; } + // TODO: SLOWTWITCH EDIT + //echo "$temprow[user_username]"; + // replace the link above with the link below for integration into gforum + echo "$temprow[user_username] at ".date("F j, Y g:i A", $row[edit_timestamp]); + // TODO: SLOWTWITCH EDIT END + } + $i++; + } + if($numcount <= 0){ echo "No users"; } + ?> +
    +
    +
    +
    + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/triclubs/logout.php b/site/triclubs/logout.php new file mode 100644 index 0000000..4f628c8 --- /dev/null +++ b/site/triclubs/logout.php @@ -0,0 +1,7 @@ + diff --git a/site/triclubs/regionlist.php b/site/triclubs/regionlist.php new file mode 100644 index 0000000..a517bfc --- /dev/null +++ b/site/triclubs/regionlist.php @@ -0,0 +1,82 @@ + + + + + + +
    + +
    +
    + + + +
    + +
    +
    + +
    +

    Triathlon Clubs

    + Back + + " class="btn btn-white float-right">Add TriClub + +
    + + +

    Region

    +
    + No triathlon clubs have been entered yet for $regionname.

    "; + } + ?> + + + +
    + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/triclubs/statelist.php b/site/triclubs/statelist.php new file mode 100644 index 0000000..dc77905 --- /dev/null +++ b/site/triclubs/statelist.php @@ -0,0 +1,127 @@ + + + + + + +
    + +
    +
    + + + +
    + +
    +
    + +
    +

    Triathlon Clubs

    + Back + + Add TriClub + +
    + + +

    State

    +
    + + No triathlon clubs have been entered yet for $statename.

    "; + } + ?> + + + +
    +
    +
    +
    + +
    +
    + + +
    + + + + + diff --git a/site/triclubs/top.php b/site/triclubs/top.php new file mode 100644 index 0000000..89c545c --- /dev/null +++ b/site/triclubs/top.php @@ -0,0 +1,71 @@ + 10 ORDER BY score DESC, votes DESC LIMIT 10"); + +$none = FALSE; +if (mysql_num_rows($results) == 0) { + $none = TRUE; +} + +// set the page title +$pagetitle = "Top Triathlon Clubs"; + +// set meta tags +$meta_keywords = "top ranked triclubs"; +$meta_description = "Top ranked triathlon clubs based on rankings submitted by the user."; +?> + + + + + + +
    + +
    +
    + + +
    + +
    +
    + +
    +

    Top Ranked Triathlon Clubs

    +
    + + + No running stores have been entered yet for $regionname.

    "; + } + ?> +

    + + + +

    + + +
    +
    +
    + +
    +
    + + +
    + + + diff --git a/site/triclubs/validate.php b/site/triclubs/validate.php new file mode 100644 index 0000000..0da3f0d --- /dev/null +++ b/site/triclubs/validate.php @@ -0,0 +1,83 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Unvalidated Triclubs

    +
    + +
    + + +
    Address: $row[triclub_address_two]"); } echo("
    $row[triclub_city], $row[triclub_state] $row[triclub_zip]"); ?>
    +
    + Email: $row[triclub_email]"; ?>
    + Website: $row[triclub_website]"; ?> +
    + ">More information +
    Validate this triclub. Delete this triclub. +
    + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/triclubs/validate_X.php b/site/triclubs/validate_X.php new file mode 100644 index 0000000..a9a51a2 --- /dev/null +++ b/site/triclubs/validate_X.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/site/triclubs/wiki_buttons.php b/site/triclubs/wiki_buttons.php new file mode 100644 index 0000000..e059361 --- /dev/null +++ b/site/triclubs/wiki_buttons.php @@ -0,0 +1,21 @@ + + +
    + +
    + + +
    + +
    + + +
    + +
    diff --git a/site/triclubs/wiki_edit.php b/site/triclubs/wiki_edit.php new file mode 100644 index 0000000..8083897 --- /dev/null +++ b/site/triclubs/wiki_edit.php @@ -0,0 +1,352 @@ + + +"Alabama", + 'AK'=>"Alaska", + 'AB'=>'Alberta', + 'AZ'=>"Arizona", + 'AR'=>"Arkansas", + 'BC'=>'British Columbia', + 'CB'=>"Caribbean", + 'CA'=>"California", + 'CM'=>"Central America", + 'CO'=>"Colorado", + 'CT'=>"Connecticut", + 'DE'=>"Delaware", + 'DC'=>"District of Columbia", + 'FL'=>"Florida", + 'GA'=>"Georgia", + 'HI'=>"Hawaii", + 'ID'=>"Idaho", + 'IL'=>"Illinois", + 'IN'=>"Indiana", + 'IA'=>"Iowa", + 'KS'=>"Kansas", + 'KY'=>"Kentucky", + 'LA'=>"Louisiana", + 'ME'=>"Maine", + 'MB'=>'Manitoba', + 'MD'=>"Maryland", + 'MA'=>"Massachusetts", + 'MX'=>"Mexico", + 'MI'=>"Michigan", + 'MN'=>"Minnesota", + 'MS'=>"Mississippi", + 'MO'=>"Missouri", + 'MT'=>"Montana", + 'NE'=>"Nebraska", + 'NV'=>"Nevada", + 'NB'=>'New Brunswick', + 'NL'=>'Newfoundland', + 'NH'=>"New Hampshire", + 'NJ'=>"New Jersey", + 'NM'=>"New Mexico", + 'NY'=>"New York", + 'NC'=>"North Carolina", + 'ND'=>"North Dakota", + 'NS'=>'Nova Scotia', + 'OH'=>"Ohio", + 'OK'=>"Oklahoma", + 'ON'=>'Ontario', + 'OR'=>"Oregon", + 'PA'=>"Pennsylvania", + 'PE'=>'Prince Edward Island', + 'QC'=>'Quebec', + 'RI'=>"Rhode Island", + 'SK'=>'Saskatchewan', + 'SC'=>"South Carolina", + 'SD'=>"South Dakota", + 'TN'=>"Tennessee", + 'TX'=>"Texas", + 'UT'=>"Utah", + 'VT'=>"Vermont", + 'VA'=>"Virginia", + 'WA'=>"Washington", + 'WV'=>"West Virginia", + 'WI'=>"Wisconsin", + 'WY'=>"Wyoming"); +?> + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    + +

    Thank you

    + Thank you. Your club should be added within 24 hours. You will now be redirected back to the add page.

    "; + echo ""; + } else if($confirm == 1){ ?> +

    Edit a Club: Step 2 of 2

    + +

    Edit a Club: Step 1 of 2

    + +

    Thank you

    + +

    To edit a club, simply change the data you wish. If you make a mistake, just hit the reset button. To save the changes as a NEW club (for instance, if you have multiple chapters), hit the "SAVE AS A NEW CLUB" button. To save changes to the existing club entry, hit the "SAVE CHANGES TO YOUR CLUB" button. You will have a chance to review the data before confirming.

    + + + + +
    +

    +
    +
    +
    Store Name
    +
    +
    + +
    +
    +
    +
    Address
    +
    +
    + +
    +
    +
    +
    Address 2
    +
    +
    + +
    +
    +
    +
    City
    +
    +
    + +
    +
    +
    +
    State
    +
    +
    + +
    +
    +
    +
    Zip/Postal Code
    +
    +
    + +
    +
    +
    +
    E-mail
    +
    +
    + +
    +
    +
    +
    Website
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    President
    +
    +
    + +
    +
    +
    +
    Board Members(s)
    +
    +
    + >None + >Yes, Their Names: + +
    +
    +
    +
    Total Membership
    +
    +
    + (number of members only) +
    +
    +
    +
    Dues
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    Club Info
    +
    +
    + +
    +
    +
    +
    Sponsors
    +
    +
    + +
    +
    +
    +
    Discounts
    +
    +
    + +
    +
    +
    +
    Directions to Workouts & Meeting Location(s)
    +
    +
    + +
    +
    +
    +
    Workout
    +
    +
    + +
    +
    +
    +
    Meetings
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + +
    +
    +
    +
    + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/triclubs/wiki_edit_X.php b/site/triclubs/wiki_edit_X.php new file mode 100644 index 0000000..c5f86e1 --- /dev/null +++ b/site/triclubs/wiki_edit_X.php @@ -0,0 +1,135 @@ +"; + $errmsg = rtrim($errmsg, ", "); + } + if (!is_numeric($_POST[triclub_membership])) $errmsg = $errmsg."Membership must be a number ONLY
    "; + $start_url = "(http(s)?\:\/\/)?"; // start url + $dots = "([\w_-]{2,}\.)+"; // one or more parts containing a '.' at the end + $last_part = "([\w_-]{2,})"; // last part doesn't contain a dot + $user = "((\/)(\~)[\w_=-]+)?((\/)[\w_=-]+)*"; // maybe subdirectories - possibly with user ~ + $end = "((\/)|(\/)[\w_-]+\.[\w]{2,})?"; // maybe a slash at the end or slash+file+extension + $qstring1 = "((\?[\w_-]+\=([^\#]+)){0,1}"; // querystring - first argument (?a=b) + $qstring2 = "(\&[\w_-]+\=([^\#]+))*)?"; // querystring - following arguments (&c=d) + $bkmrk = "(#[\w_-]+)?"; // bookmark + + $exp = "/^".$start_url.$dots.$last_part.$user.$end.$qstring1.$qstring2.$bkmrk."$/i"; + if( !preg_match($exp, $_POST[triclub_website]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Invalid Web Address
    "; + } + if( preg_match('/[^a-zA-Z0-9\. ]/', $_POST[triclub_name]) ) { + // Contains invalid characters. + $errmsg = $errmsg."Please use only letters and numbers in the name
    "; + } + if(!$errmsg){ + + $name = trim($_POST[triclub_name]); + $name_tag = strtolower(str_replace(" ","", $name)); + if(strlen($nametag) > 12){ //Shorten it + $name_tag = substr($nametag, 0, 12); + } + $address = mysql_escape_string(trim($_POST[triclub_address])); + if (isset($_POST['triclub_address_two'])) { $address_two = mysql_escape_string(trim($_POST[triclub_address_two])); } else { $triclub_address_two = NULL; } + $city = mysql_escape_string(trim($_POST[triclub_city])); + $state = $_POST[triclub_state]; + $state_tag = strtolower(str_replace(" ","", $state)); + $zip = mysql_escape_string(trim($_POST[triclub_zip])); + $email = mysql_escape_string(trim($_POST[triclub_email])); + $website = mysql_escape_string(trim($_POST[triclub_website])); + $president = mysql_escape_string(trim($_POST[triclub_president])); + $dues = mysql_escape_string(trim($_POST[triclub_dues])); + $membership = mysql_escape_string(trim($_POST[triclub_membership])); + $board = $_POST[triclub_board]; + if ( $board == 0 ){ $board_names = NULL; }else{ $board_names = mysql_escape_string(trim($_POST[triclub_board_names])); } + $info = mysql_escape_string(nl2br(substr(trim($_POST[triclub_info]), 0, 4096))); + $sponsors = mysql_escape_string(nl2br(substr(trim($_POST[triclub_sponsors]), 0, 4096))); + $discounts = mysql_escape_string(nl2br(substr(trim($_POST[triclub_discounts]), 0, 4096))); + $directions = mysql_escape_string(nl2br(substr(trim($_POST[triclub_directions]), 0, 4096))); + $workouts = mysql_escape_string(nl2br(substr(trim($_POST[triclub_workouts]), 0, 4096))); + $meetings = mysql_escape_string(nl2br(substr(trim($_POST[triclub_meetings]), 0, 4096))); + $submitted_by = $_POST[triclub_submitted_by]; + $id = $_POST[triclub_id]; + $edited_by = $_POST[edited_by]; + $edit_timestamp = time(); + + // BEGIN CONFIRM ENTRY CHECK + if($_POST[confirm_entry] == 1){ + if(isset($_POST[new_club])){ + $sql = "INSERT INTO ".$prefix."Triclubs (triclub_name, triclub_name_tag, triclub_address, triclub_address_two, triclub_city, triclub_state, triclub_state_tag, triclub_zip, triclub_email, triclub_website, triclub_president, triclub_board, triclub_board_names, triclub_membership, triclub_dues, triclub_info, triclub_sponsors, triclub_discounts, triclub_directions, triclub_workouts, triclub_meetings, triclub_submitted_by, triclub_valid) VALUES ('$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$email', '$website', '$president', $board, '$board_names', '$membership', '$dues', '$info', '$sponsors', '$discounts', '$directions', '$workouts', '$meetings', '$submitted_by', 0)"; + //echo("club entered!"); + //echo($sql); + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/add.php?confirmed=yes'); + } elseif(isset($_POST[save_changes])) { + $sql = "INSERT INTO ".$prefix."TriclubsEdits (triclub_id_fk, editor_user_id_fk, edit_timestamp, triclub_name, triclub_name_tag, triclub_address, triclub_address_two, triclub_city, triclub_state, triclub_state_tag, triclub_zip, triclub_email, triclub_website, triclub_president, triclub_board, triclub_board_names, triclub_membership, triclub_dues, triclub_info, triclub_sponsors, triclub_discounts, triclub_directions, triclub_workouts, triclub_meetings, triclub_submitted_by, triclub_valid) VALUES ('$id', '$edited_by', '$edit_timestamp', '$name', '$name_tag', '$address', '$address_two', '$city', '$state', '$state_tag', '$zip', '$email', '$website', '$president', $board, '$board_names', '$membership', '$dues', '$info', '$sponsors', '$discounts', '$directions', '$workouts', '$meetings', '$submitted_by', 0)"; + mysql_query($sql) OR die(mysql_error()); + header('Location: '.$site_url.'/individual.php?triclub_id='.$id.'&wiki_change=success'); + } else { + header('Location: '.$site_url.'/individual.php?triclub_id='.$id.'&changes=failure'); + } + } else { + //echo("club NOT entered."); + $confirm = 1; + } + // END CONFIRM ENTRY CHECK + } + // END ERROR MESSAGE CHECK +?> diff --git a/site/triclubs/wiki_validate.php b/site/triclubs/wiki_validate.php new file mode 100644 index 0000000..b58404f --- /dev/null +++ b/site/triclubs/wiki_validate.php @@ -0,0 +1,98 @@ + + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    Unvalidated Public Edits

    +
    + +
    + + +
    Edited on: by ".$editor_user_username.""; if ($boolEditorIsOwner) { echo " (original triclub submitter)"; } else { echo ""; } ?>
    +
    Info: + 400){ + $phrase = "…"; }else{ + $phrase = ""; } + + echo substr(htmlspecialchars(strip_tags(stripslashes($row[triclub_info]))), 0, 160); + echo $phrase; + ?> +
    + +
    + Location:
    + ">More information +
    Validate this edit. Delete this edit. +
    + +
    + + + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/site/triclubs/wiki_validate_X.php b/site/triclubs/wiki_validate_X.php new file mode 100644 index 0000000..75b8860 --- /dev/null +++ b/site/triclubs/wiki_validate_X.php @@ -0,0 +1,103 @@ + \ No newline at end of file diff --git a/site/triclubs/wiki_view.php b/site/triclubs/wiki_view.php new file mode 100644 index 0000000..d06ce80 --- /dev/null +++ b/site/triclubs/wiki_view.php @@ -0,0 +1,148 @@ + + + + + + +
    + +
    +
    + + +
    + + +
    +
    + +
    +

    + + + +
    + + + +Editor: ".$strEditor.""; ?> +
    + +Edit Date: +
    + +Street Address: +
    +Street Address Two: +
    +City: +
    +State: +
    +Zip/Postal Code: +
    +E-mail: +
    +Website: + +
    +
    + +
    + +
    + +
    +Club President: +
    +Board Member(s): +
    +Total Membership: +
    +Club Dues: + +

    +
    + +
    +
    +Club Info: +

    +Club Sponsors: +

    +Club Discounts: +

    +Directions to Meeting Location(s): +

    +Club Workout Schedule: +

    +Club Meetings & Events Schedule: +

    +Directions to Workouts & Meeting Location(s): + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    + + +
    + + + diff --git a/slowtwitch.com/ads.txt b/slowtwitch.com/ads.txt new file mode 100644 index 0000000..9a7d983 --- /dev/null +++ b/slowtwitch.com/ads.txt @@ -0,0 +1 @@ +google.com, pub-3783965151563160, DIRECT, f08c47fec0942fa0 \ No newline at end of file diff --git a/slowtwitch.com/ads3.txt b/slowtwitch.com/ads3.txt new file mode 100644 index 0000000..ee07e67 --- /dev/null +++ b/slowtwitch.com/ads3.txt @@ -0,0 +1,2 @@ +rhythmone.com, 3246069104, RESELLER, a670c89d4a324e47 sovrn.com, 57813, RESELLER, fafdf38b16bf6b2b lijit.com, 57813, RESELLER, fafdf38b16bf6b2b rubiconproject.com, 17544, RESELLER, 0bfd66d529a55807 appnexus.com, 8438, RESELLER openx.com, 540134626, RESELLER, 6a698e2ec38604c6 conversantmedia.com, 21347, RESELLER 33across.com, 0010b00001u6VjdAAE, RESELLER adtech.com, 10048, RESELLER contextweb.com, 558211, RESELLER, 89ff185a4c4e857c openx.com, 540062960, RESELLER, 6a698e2ec38604c6 districtm.io, 101085, RESELLER pubmatic.com, 157660, RESELLER, 5d62403b186f2ace indexexchange.com, 187790, RESELLER sonobi.com, 93215fc1c4, RESELLER, d1a215d9eb5aee9e lockerdome.com, 11118976357066496, RESELLER gumgum.com, 13593, RESELLER, ffdef49475d318a9 rtb.pretiox.com, 262, RESELLER +google.com, pub-3783965151563160, DIRECT, f08c47fec0942fa0 \ No newline at end of file diff --git a/slowtwitch.com/glist.txt b/slowtwitch.com/glist.txt new file mode 100644 index 0000000..2add8bd --- /dev/null +++ b/slowtwitch.com/glist.txt @@ -0,0 +1,2224 @@ +13oceans@gmail.com +2walter@comcast.net +3.14mark@gmail.com +40acres@rochester.rr.com +9dir@qlink.queensu.ca +a.karcz@mchsi.com +aaronburstein@snet.net +aauld@silvercross.com +abelgiovine@gmail.com +abent@aetinc.com +abski@sbcglobal.net +acece@csquared-design.com +aconcors@juno.com +acron55@hotmail.com +adam.borah@gmail.com +adam.borah@iraq.centcom.mil +adam.borah@us.army.mil +adam6@unm.edu +adambushnoe@hotmail.com +adampom@alumni.unc.edu +adampom@email.unc.edu +adam_pomerantz@unc.edu +adevoe@bhfs.com +admillard@excite.com +ads_cb@hotmail.com +adventuress@gmail.com +aecky01@vt.edu +aelisan510@yahoo.com +aelisan@hotmail.com +aerod@clix.pt +afe4@aol.com +afreakan@gmail.com +aglacet@essilorusa.com +aglacet@tampabay.rr.com +agordon@mapcoprinters.com +ahariton@bellsouth.net +aherring@unc.edu +ajhodges@gmail.com +ajmilk@comcast.net +akjayhawk@yahoo.com +alaida@comcast.net +alaida@midsouth.rr.com +albertgeerling@yahoo.com +aleozzy@yahoo.com +alex@sbcpas.com +alex@vogenthaler.com +alexbjohnson@yahoo.com +alexroseinnes@gmail.com +alex_sara@hotmail.com +aligni@charter.net +alivadariu@hotmail.com +alkaloids@gmail.com +allan.faulds@sympatico.ca +allegrasf@comcast.net +allezjohn@yahoo.com +alliauw@gmail.com +allyourvwsrbelong2us@gmail.com +alui042@uottawa.ca +amb18@cornell.edu +amclaughlin@southeastcompanies.com +amishrakebattle@gmail.com +amy.krieg@gmail.com +amycastillo78@gmail.com +amycutler5@hotmail.com +amykrupka@yahoo.com +amymike123@sbcglobal.net +amy_seale@hotmail.com +andersc@gwu.edu +andjeff@us.ibm.com +andohert@hotmail.com +andre.lui@gmail.com +andrew.castle@gmail.com +andrew.inkpen@thunderbird.edu +andrew.leick@disney.com +andrew.prinz@capgemini.com +andrewjjoyce@sbcglobal.net +andy.bent@gmail.com +andy.coro@hp.com +andyjengrove@comcast.net +andyran26.2@gmail.com +andytn.a4@gmail.com +anik.mercure@gmail.com +anik@tommyimports.ca +aniska@sympatico.ca +ankarcz@eiu.edu +ankarcz@indiana.edu +anna.crespo@gmail.com +annaria@gmail.com +annette509@yahoo.com +anthony.cece@gmail.com +ap.elisan@gmail.com +argrove@hotmail.com +ariel@malvina.com +armstronga@ottawapolice.ca +armychemguy@hotmail.com +arnozilla@yahoo.com +arodi_riveral_llinas@hotmail.com +aromania@cox.net +artfuldodger99@yahoo.com +artsosa@roadrunner.com +aschappe@charter.net +aseanor@blackmont.com +aseanor@rogers.com +asher.kuper@gmail.com +ashleysg@bellsouth.net +asierra@coqui.net +asisson@igneite.com +asisson@scalabilityexperts.com +asisson@verizon.net +astewartmn@hotmail.com +atkid@yahoo.com +atomicspoo@cinci.rr.com +atp@nc.rr.com +attamimia@gmail.com +austinjeff98@yahoo.com +avid.sisson@sbcglobal.net +awm8@aol.com +awost1@yahoo.com +ax@larsenglobal.com +a_schmutz@yahoo.com +b4surf@hotmail.com +babsmayfield@austin.rr.com +bao_kogan@allergan.com +baranski@tri-mag.de +barker1.matt@gmail.com +barnes@bx3.com +barrett@chapman.com +barrs04@frontiernet.net +barry@bookweb.org +barrysobolewski@yahoo.com +bassnjenn@aol.com +batesrt@hotmail.com +bauntorun@gmail.com +baywoodnet@optonline.net +bbaehrens@gmail.com +bbartlome@motivace.com +bbieberitz@dharter.net +bbornhurst@enclos.com +bbradley@auroragov.org +bbursey@snowpro.com +bcg17@mac.com +bconway6650@comcast.net +bconway6650@gmail.com +bconway6650@hotmail.com +bcropp@shaw.ca +bdc71@hotmail.com +bdobbs@austin.rr.com +bdu38459@bigpond.net,au +bealsm82@gmail.com +beaversrl@aol.com +beckyf@hudsonassoc.com +bedmorris@gmail.com +beitzen@att.net +ben.hemson@gmail.com +ben@nebmot.com +benjamin.nye@mattel.com +benjprice@yahoo.com +benrob@gmail.com +benrob@uga.edu +benswimsfree@aol.com +ben_nyeuk@yahoo.co.uk +bepowell@aol.com +bernbros@chartermi.net +berndoggiedog@yahoo.com +bernieconway@mycingular.blackberry.net +bernie_conway@finnandconway.com +bernie_conway@finnandconwayglatte.com +bestonadventures@gmail.com +beth@etsy.com +betoandsho@gmail.com +betsy@fuelbelt.com +bfangad@gmail.com +bfitzh2o@aol.com +bfitzlaw@aol.com +bgennari@emdeon.com +bgfreelance@earthlink.net +bgraham@maine.rr.com +bgreen@presidio.com +bhbh5@hotmail.com +bhemson40@hotmail.com +biff@charterdev.com +bigalbennett@hotmail.com +bignewf2@aol.com +bikerbiker@gmail.com +bikeweenie@comcast.net +bill@morgananddylan.com +bill@springfield-armory.com +billrollins@gmail.com +bissonp@olywa.net +bjafur@hotmail.com +bjarte.furnes@gmail.com +bjtriguy@yahoo.com +bkbeeker@yahoo.com +blair@sealimports.co.nz +blamonta@gmail.com +blarrain@aol.com +bleese@omm.com +blisle5561@charter.net +bnsvirga@earthlink.net +bob@actionshots.ca +bobcole@cfl.rr.com +bobdaw@gmail.com +bolltem@clarkson.edu +boothrand@sbcglobal.net +borisevich_a@inbox.ru +bouker.poo@rodale.com +bouker.pool@gmail.com +bparney@hotmail.com +bpdream@aol.com +bpe@comcast.net +brad.boyd@netzero.com +bradcollins@socal.rr.com +bradtho@hotmail.com +brandauer@gmail.com +brandon.hutcherson@capitalone.com +brburns@clarku.edu +brendan.gately@eurorscg.com +brendangately@gmail.com +brendangately@yahoo.com +brennera@rockfordsystems.com +brewerbry@aol.com +brhauser@prairieinet.net +brian.j.schoenholz@boeing.com +brian.kirkpatrick11@gmail.com +brian.plitnick@fedex.com +brian.quigley@brooks.com +briank@email.arizona.edu +brianschoenholz@yahoo.com +briansevall@yahoo.com +brian_edmonds@merck.com +brian_keast@rogers.com +briderdt@yahoo.com +bridgetd@hotmail.com +brittanyikatz@hotmail.com +brlists@verizon.net +brplit@hotmail.com +bruce.mason@rogers.com +brucebornhurst@yahoo.com +brucejunk@verizon.net +bryan.bursey@gmail.com +bryan.jaffe@gmail.com +bryan.s.bursey@esso.ca +bryan.s.bursey@exxonmobil.com +bryanfraser@msn.com +bryanrhodsey@hotmail.com +bryan_bursey@hotmail.com +bryan_watabe@yahoo.com +brynje_r@hotmail.com +bsc0034@aim.com +bthomp22@juno.com +buff@wdst.com +bullnfurstie@gmail.com +bushido55@gmail.com +busygemini@yahoo.com +bwingfield@comcast.net +byll.cawley@gmail.com +caesar74@cox.net +calebmax@gmail.com +camnut@gmail.com +canthony@umich.edu +cantswim24@yahoo.co.uk +caragleason@hotmail.com +carlos.figueroa@eniac-copr.com +carlosf@eniac-copr.com +carlosfg@onelinkpr.net +carlosfg@prtc.net +carolinawindandwater@yahoo.com +carriecgilbert@hotmail.com +carsm@bsci.com +casa@sedona.net +casciod@comcast.net +casey_1977@hotmail.com +cateringbyjeff@yahoo.com +catherinealee@gmail.com +cathy.galvan@verizon.net +cathy.morgan@pillsburylaw.com +cathychris@cal.berkeley.edu +cbrewer@bpmmlaw.com +ccail1@hotmail.com +ccavanaugh1@san.rr.com +ccmhunt2003@sbcglobal.net +ccmhunt@aol.com +ccorning@comcast.net +ccw2@earthlink.net +cdoody414@yahoo.com +cdrisk@aol.com +celebratinglife@charter.net +cello7@aol.com +cerivero@yahoo.com +cervelo1@gmail.com +cervelo3@yahoo.com +cgleason@theroselawfirm.com +cgoodwin@knex.com +chad.brown@ge.com +chad.brown@med.ge.com +chad.walton@usmc.mil +chambrin@bellsouth.net +changster121@sbcglobal.net +charles.gerlach@reedbusiness.com +charlesfmoss@hotmail.com +charlesgerlach@yahoo.com +charlesmeehan@sympatico.ca +charles_ehm@yahoo.com +charliemroberts@gmail.com +chartrandkevin@yahoo.com +chasinmaleia2@junp.com +chesnutt@chebucto.ns.ca +chestnutavenue@comcast.net +chewgl@gmail.com +chewgl@mit.edu +chewgl@yahoo.com +chewiesweetheart@hotmail.com +chez202@gmail.com +chiefmoc@charter.net +chipatcgv@aol.com +chipmisc@sbcglobal.net +chris.fiddes@gecas.com +chris.goldman@target.com +chris.gossard@gmail.com +chris.may35@gmail.com +chris.obrien@sky.com +chris.parker@gmail.com +chris.reynolds@weyerhaeuser.com +chris.wilkes@invoke.com +chris9595@gmail.com +chris@chriswhyte.net +chris@lymanpr.com +chrisfrnsn@yahoo.com +chrisgoodwin@yahoo.com +chrisharris@triathlete.com +chrismatlock@gmail.com +chrisofferson.anders@gmail.com +chrisrunzs26@yahoo.com +christmask8y@yahoo.com +christopher.a.matlock@ampf.com +christopher.jang@gmail.com +christopher.morris@pearson.com +christopher@tricolour.queensu.ca +christopherasweet@hotmail.com +christopher_burns@mgic.com +christopher_kautz@yahoo.com +christopher_sander@hotmail.com +chrisw@followup.net +chuck@preislaw.com +chuck_gordon@yahoo.com +cidewar@gmail.com +cifl@mchsi.com +cindyandross@telus.net +citrine090@yahoo.com +cjhuff@shaw.ca +cjknox@mac.com +cjriley@iastate.edu +cjspread@sbcglobal.net +ckotte@gmail.com +ckraemer@sympatico.ca +clash@gocougs.wsu.edu +cliffordwj@hotmail.com +cliffordwj@yahoo.com +clulrich@yahoo.com +cmetri8@yahoo.com +cmiller150@tampabay.rr.com +cmm4218@lausd.net +cmwilkes98@aol.com +cnbaucom@gmail.com +coachkstow@yahoo.com +coachrhodes@hotmail.com +coach_talsma@hotmail.com +colin.callaghan@capmark.com +colin.lacy@aciworldwide.com +colincallaghan@sbcglobal.net +colinlacy@gmail.com +colinlacy@rogers.com +colin_callaghan@gmaccm.com +colin_sparks@pch.gc.ca +concerned4lv@yahoo.com +connie.kraemer@agfa.com +coolmobill@gmail.com +cooperva@verizon.net +corin.wright@gmail.com +corn552@aol.com +cowgirlinthesand@hawaii.rr.com +coypelon@cox.net +coypelon@msn.com +cpathompson@yahoo.com +cpaulson@surfbest.net +cpcowley@gmail.com +cpcreateit@aol.com +cpdtriathlon@yahoo.com +cpplyr@yahoo.com +cprestonoc@yahoo.com +craig.climber@gmail.com +craig.preston@noraneng.com +craig.shepherd@poolepartners.com.au +craig.spreadbury@meritenergy.com +craiganderson56@gmail.com +craigzilla02@yahoo.com +crashward@yahoo.com +crazytriathlete@gmail.com +cristoforbuller@yahoo.com +critcommute@gmail.com +cronkhia@pbcc.edu +cronkhite@gmail.com +crystalrhodes20@hotmail.com +cspreadbury@yahoo.com +cstevenson@gza.com +cstine@indiana.edu +cthomposon@callsesco.com +cthompson@powercityelectric.com +cutlerpj@potsdam.edu +cvcoop@charter.net +cvillatri@yahoo.com +cwarner@erickson.com +cwarner@ericksonmail.com +cycleforce@dslextreme.com +cycleforce@dslextreme.net +cyclepath01@yahoo.com +cyclisto@gmail.com +d-weisbach@uchicago.edu +d.napoli@gmail.com +d.sisson@sbcglobal.net +d1193@truman.edu +d3andp@msn.com +dabeaven@hotmail.com +dadkisondo@embarqmail.com +daggcd@aol.com +daggettcd@aol.com +daleb29@aol.com +dallas@firebird.bc.ca +dalrymplewebster@gmail.com +dan@m2sport.com +dan@socie.com +danacyphert-pate@baileysgym.com +daniebr@umich.edu +daniel.decarolis@gmail.com +danoisjr@comcast.net +danosju@gmail.com +dantrott@hotmail.com +danwcampbell@msn.com +darobertson@shaw.ca +darrelleng@yahoo.com +darrenjacoby13@yahoo.com +daryl@advantagemultisport.com +dashrunning@yahoo.com +dashswimming@yahoo.com +dave.macluskie@gmail.com +dave.r.delucchi@lmco.com +dave.sebba@gmail.com +dave@arthistory.cc +dave@sdri.net +davebeitel@cs.com +davecb@frontiernet.net +davefish@charter.net +davemccarry@hotmail.com +daveweilacher@bellsouth.net +daveweilacher@gmail.com +davew_39@yahoo.com +davhamm@gmail.com +davhamm@yahoo.com +davhammfan@yahoo.com +david.b.clayton@gmail.com +david.barclay@rogers.com +david.bruce@queensu.ca +david.judice@ecl-eng.com +david.liles@ntlworld.com +david.meadows@healthsouth.com +david.robertson@viha.ca +david.sisson@airliance.com +david@jepson.org +david@softsphinx.com +davidadelsberg@hotmail.com +davidcallahan@hotmail.com +davidcla@usc.edu +daviddiviney@yahoo.com +davidlburns@gmail.com +davidsavoie5522@yahoo.com +david_durkin@yahoo.com +dawnyoung@sympatico.ca +daxczl@cinci.rr.com +dbarr@karmak.com +dbarron3@yahoo.com +dbdonnal@eos.ncsu.edu +dbdonnal@ncsu.edu +dbdonnal@unity.ncsu.edu +dbearware@msn.com +dbeitel@davisdavisco.com +dbell.in.bc@gmail.com +dbh1@msn.com +dcc2aia@earthlink.net +dcc2aia@embarq.com +dcduguid@hotmail.com +dchapma3@hotmail.com +dcohn03@yahoo.com +dcovington@spectrumpc.com +dcverner@comcast.net +ddungan@insightbb.com +ddungan@mac.com +deboer_shawn@hotmail.com +decharter2@gmail.com +del.hansen@gmail.com +dendelong@aol.com +denvertylee@hotmail.com +derek.lejeune@gmail.com +devin.cashman@regiscollege.edu +dfontenot@iqmail.net +dfwilding@aol.com +dgliddon@sympatico.ca +dhaddox2@yahoo.com +dhammelef@yahoo.com +dhart7777@sbcglobal.net +dhinds57@gmail.com +dhinds@cafuelsupply.com +dhsalz13@yahoo.com +diehlphillips@insightbb.com +dillon.fritz@med.fsu.edu +disleib@na.cokecce.com +djmikkelson@yahoo.com +djteed@hotmail.com +dklevin@cox.net +dkupe1@yahoo.com +dkuper@woodcraftunlimited.com +dlitherland@yahoo.com +dmdicocco@mmm.com +dmh970@msn.com +dmpmd@hotmail.com +dnelson@maytagaircraft.com +dogmanvegas@earthlink.net +don.gustavson@webloyalty.com +don@webloyalty.com +donaldemarshall@gmail.com +donaldemarshall@yahoo.com +donato@zenhiking.com +dongustav@hotmail.com +donutgestapo@gmail.com +don_simon@admworld.com +dottorejekyll@gmail.com +doug@ibexeng.ca +dougclark@alcatel-lucent.com +douglassj@gmail.com +dougmhenderson@shaw.ca +dougrosen38@hotmail.com +dpatterson70@yahoo.com +dpbauer1@adelphia.net +dr.skidmore@gmail.com +dramosh@gmail.com +drbjarte@bjartefurnes.com +dreimer121@yahoo.com +drffishman@mac.com +drhelened@aol.com +drkraemer@dearbornhealth.com +drmthtr@gmail.com +drodgers72@gmail.com +droscoe@umassd.edu +drothjr@ampli.com +dru1406@yahoo.com +drwerbs@cox.net +dr_brausefrosch@web.de +ds17@duke.edu +dsebba@hotmail.com +dsemtp@aol.com +dsepucha@gmail.com +dshields110@comcast.net +dsportse@hotmail.com +dstevenson@edc.ca +dtinsurance@gmail.com +duffeymt@gmail.com +duffney@hccl.ca +dugas@spawar.navy.mil +dukeseal@hotmail.com +duluray@gmail.com +duluray@netzero.net +duluray@yahoo.com +durrwa04@newpaltz.edu +dustyf18@yahoo.com +dvdjks@aol.com +dvining@aya.yale.edu +dvracing@hotmail.com +dware@evans-dixon.com +dwick353@yahoo.com +dwtdct@aol.com +dyoung@aac-us.com +dzmike@gmail.com +e2king@lasd.org +earnd193@yahoo.com +ebinzer@insightbb.com +ecdolphin@hotmail.com +ed.winczowski@suhsd.k12.ca.us +edw724@gmail.com +edward.l.johnston@bendbroadband.com +eighteenbucks@yahoo.com +ejohns3992@yahoo.com +ejohnson26@msn.com +eliotd@hotmail.com +elisabgreenwood@yahoo.com +ellyk9@hotmail.com +emacfar@gmail.com +emacfar@luc.edu +emacfarl@hotmail.com +emailtodave@bellsouth.net +emeraldandcolin@rogers.com +emkornfield@gmail.com +emmamac@wi.net +emmiejacobs@comcast.net +emreialbayrak@gmail.com +enduranceman@gmail.com +entry_entry@yahoo.com +eopdyke@hotmail.com +eopdyke@optonline.net +eric@ericbarna.org +ericdtrainer@hotmail.com +erichollins@gmail.com +ericking@sbcglobal.net +ericvalyko@hotmail.com +eric_ewan@hotmail.com +erik.clark@mlcampbell.com +erik.mason@gmail.com +erika.mceachran@ottawa.ca +erikbell@comcast.net +erikbell@gmail.com +erikfloden@gmail.com +erinmierzwa@hotmail.com +eschbach@meredith.edu +eshanon@law.gwu.edu +esj@ckwllc.com +etalsma@hamiltonschools.us +etmdet@comcast.net +evan.macfarlane@att.net +evanthayer@gmail.com +evan_berger@hotmail.com +ewan.hardie@gmail.com +ewolfson.oper@gmail.com +ewolfson@bezeqint.net +exercisetest@hotmail.com +f18dusty@gmail.com +fal7@ix.netcom.com +farnesmatt@yahoo.com +fasterthanyou71@yahoo.com +fatsoontheloose@gmail.com +fatzbinx@hotmail.com +fbrissette@ctn.etsmtl.ca +fbrissette@gmail.com +fegirl1@yahoo.com +feistydaichi@gmail.com +feistydaichi@hotmail.com +felipe@felipe-bastos.com +felipe@felipebastos.com +felix.weilenmann@gmx.ch +felix__w@hotmail.com +feman007@hotmail.com +feman007@yahoo.com +ferreiradesousa@gmail.com +ffmtb1@comcast.net +fgilbert@go2uti.com +fhasle@leapstone.com +fhines@gmail.com +firefighter126@yahoo.com +fjfowler@mindspring.com +flammerouge@aol.com +flee@bosscoindustries.com +flozert@yahoo.com +fluetst@spsd.org +flying_illini@hotmail.com +forumsnow1202@yahoo.com +fourgagniers@netzero.com +fraserb@us.ibm.com +fredgilbert@gmail.com +fredrik@digitalcom.no +fred_hasle@yahoo.ca +fremidel@yahoo.ca +frenchbc@gmail.com +frint40@optonline.net +frobscottle@gmail.com +frogievbt@aol.com +fryguy@comcast.net +fulldraw45@yahoo.com +furnes@gmail.com +furstie1@gmail.com +fwcampbell@yahoo.com +fweilenmann@zumbach.ch +fwwest@acsalaska.net +g2photography@mac.com +ga4str@yahoo.com +gake@tampabay.rr.com +galarson1@comcast.net +galarson@hewitt.com +ganzer@san.rr.com +garmingeek@gmail.com +gary1406@yahoo.com +gary@geigerphoto.com +gaugustine@riveroaksimaging.com +gavinhill@deloitte.co.uk +gavnunns@hotmail.com +gbe@worldnet.att.net +gbgtriathlon@yahoo.com +geiger5318@aol.com +genatons18@earthlink.net +geoffjulie@cox.net +geoffpatterson@gmail.com +georgiaguy1976@gmail.com +geraldo@kona.net +gerzabek@comcast.net +get_faster@hotmail.com +gfarwell@cis.net +gfdems@cox.net +ggtriguy@gmail.com +ghunt@lawtonps.org +gienopes@yahoo.com +gienopie@temple.edu +gierutfamily@gmail.com +gilberto@gvalverde.com +glassjt@yahoo.com +glenn.larson@hewitt.com +glenn_c@denison.edu +glen_maceachern@hotmail.com +glucia@vivometrics.com +glyn.learmonth@hoerbiger.com +gmartindale@blgcanada.com +gmcelroy@elp.rr.com +gminard@utmem.edu +go2mikey@gmail.com +gonnatri@gmail.com +gordon.mcgregor@verilab.com +gossard-chris@aramark.com +gotriit@aol.com +go_plato@hotmail.com +go_plato@yahoo.com +gp0507@yahoo.com +graceregan1@yahoo.com +graihala@woh.rr.com +grant.reuter@gmail.com +graphics@gibraltar.gi +greenshopper@sbcglobal.net +greenswim@sbcglobal.net +greg.prosser@cnh.com +greg.sheehan@am.jll.com +gregory_bradley@keybank.com +gregwalden@city.chatham-kent.on.ca +gregwalden@hotmail.com +grhadley@xtra.co.nz +grigsby1017@aol.com +grovea2@nationwide.com +grovefamily2001@yahoo.com +gshystad@comcast.net +gsnow@gdatp.com +gssheehan@aol.com +gtimewell@telus.net +gundogdoc@gundogdoc.com +guruscott@hotmail.com +gwherrick@charter.net +gyanwn@hotmail.com +h2ofun@h2ofun.net +haikalas@mac.com +halasy.michael@mayo.edu +hallie@iccmo.org +hammerkitten@yahoo.com +hankrearden@sbcglobal.net +hannusch1@rogers.com +hans.schlecht@aurora.org +harmvanbaar@casema.nl +hbrauch@earthlink.net +hcurnutt@hotmail.com +heather@acvim.org +heathergately@gmail.com +hein.vanzanten@bms.com +hein@vanzanten.us +help@ukscuba.com +hemsonb@onid.orst.edu +hengesj@yahoo.com +henry.hensun@gmail.com +herve.chambrin@sita.aero +hess@meredith.edu +heygoalie31@verizon.net +heygoalie31@yahoo.com +hinds57@comcast.net +hjm@shaw.ca +hlefler@earthlink.net +hlusak@yahoo.com +hmikewilliams65@bellsouth.net +hoagy1212@hotmail.com +hobsonc@sbcglobal.net +hooper@bundigi.com +hosayif@gmail.com +hosayifbr@gmail.com +hosspro@hotmail.com +hosspro@rogers.com +housingshortage@hotmail.com +hpl@meredith.edu +hthomasmorganjr@hotmail.com +hvanzanten@businessedge.com +hwtoft@hotmail.com +iahawkeye@gmail.com +iamkmac@triathlete.com +iandaniel@optusnet.com.au +ian_donohue@hotmail.com +ian_w_young@hotmail.com +idaniel@ozdoc.com.au +idutri@hotmail.com +ilovemycervelo@gmail.com +imcg2004@yahoo.ca +imf44@aol.com +imnervous44@yahoo.com +impuskas@yahoo.com +imukpr@aol.com +info@tommyimports.ca +ingalula@yahoo.com +ingray@uwm.edu +iron.cramer@gmail.com +ironbabe@gmail.com +ironcam@gmail.com +ironclm@mac.com +ironcouple@cogeco.ca +ironcraigp@yahoo.com +irongirl5@hotmail.com +ironjohn36@hotmail.com +ironman@fnwusers.com +ironmanatee@roadrunner.com +ironmanjr99@yahoo.com +ironmanrex@charter.net +ironmitch@gmail.com +ironmom141@comcast.net +ironranger@nc.rr.com +irontitanik@gmail.com +irontitanik@hotmail.com +irontrev@gmail.com +irvin_tang@hotmail.com +isaiah_gray@hotmail.com +isutriguy@yahoo.com +itsagreatdaytobeatriathlete@yahoo.com +itsunclephil@yahoo.com +iugrad2x@yahoo.com +ivan_glymph_lmt@yahoo.com +iyoung@brocku.ca +j.oc@earthlink.net +j.r.cameron@sympatico.ca +jaa125@columbia.edu +jab@icon-arch.com +jacjacbooboo@yahoo.com +jack.cartwright@gmail.com +jack.mott@gmail.com +jacobhartsoch@yahoo.com +jahansen_28@hotmail.com +jamca@cogeco.ca +james.a.harris@eds.com +james.harrington@delucaliquor.com +james.r.rogers@navy.mil +james.t.ridout@uk.pwc.com +jamesathomas1@yahoo.com +jamesdougal@msn.com +jameshwilson3@hotmail.com +jamie@listcompany.com +jamiewilson3@excite.com +janetperrino@yahoo.com +janinemolloy@xtra.co.nz +janmckay1@yahoo.com +jannajosh@yahoo.com +janus.chris@gmail.com +januszno@yahoo.com +jarrodmorrison@hotmail.com +jason-slowtwitch@elys.com +jason.k.reynolds@gmail.com +jason.p.klein@gmail.com +jason@drinkmorewater.com +jasoneaddy@gmail.com +jasonhmatthews@yahoo.com +jasonmcooke@yahoo.com +jasonpretty@nl.rogers.com +jasonspencerlewiss@yahoo.com +jason_p_klein@yahoo.com +jason_rohrer@yahoo.com +javerstr8@gmail.com +jay370@gmail.com +jaylew@mail.utexas.edu +jbergmann@wpsdk12.org +jbhurdlez@hotmail.com +jbrazelton@nmusd.us +jbrideout@yahoo.com +jbwilking@yahoo.com +jc.mdphd@gmail.com +jc528@cornell.edu +jcalvert5@cox.net +jcfreese@gmail.com +jconlin1@gmail.com +jcrane19@gmail.com +jcronje@hotmail.com +jcronje@yahoo.com +jcurtis73@comcast.net +jdgriffis@suddenlink.net +jdpaustin@juno.com +jd_griffis@yahoo.com +jeanneyvonne@aol.com +jeepsweetheart@yahoo.com +jeff.ernst@pacificsoils.com +jeff@freshairsports.com +jeff@mbhcpa.com +jeffpatterson@bendbroadband.com +jeffrey.good@usmc.mil +jeffrey.huntley@asu.edu +jeffrey.j.hopkins@lmco.com +jeffrey.umbreit@ge.com +jeffreyfarwell@hotmail.com +jeffrey_rodgers@hotmail.com +jeffsritchie@verizon.net +jeff_lundgren@hotmail.com +jegood78@gmail.com +jengrove@comcast.net +jenniferworthen@cox.net +jennyfer@nycap.rr.com +jenscalise@comcast.net +jenwilliford@hotmail.com +jeremiahkane@gmail.com +jeremykaczor@gmail.com +jeremysipos@comcast.net +jesper.andersen@globalcrossing.com +jessicatwne@yahoo.com.tw +jetplane19@yahoo.com +jeyake2000@yahoo.com +jfdurand@pacbell.net +jfm225@gmail.com +jfrazetta@aol.com +jfuentes05@gmail.com +jgleduc@hotmail.com +jhawkins@psislidell.com +jhblackwel@aol.com +jhimes@elp.rr.com +jhorlikowski@hotmail.com +jhulax@gmail.com +jian1986@hotmail.com +jill.beveridge@ucalgary.ca +jillandbryan@shaw.ca +jill_beveridge@hotmail.com +jim.kuiper@ge.com +jim.mckay@galderma.com +jim.schmitt@morleynet.com +jim10901090@yahoo.com +jim10901091@yahoo.com +jim@bowregards.com +jim@eatworms.swmed.edu +jim@jimvanceracing.com +jim@northwesttool.com +jimdohertyjim@aol.com +jimhamner1@bellsouth.net +jimhamner1@comcast.net +jimmybuff100@hotmail.com +jimr@hgbcs.org +jimrhansen@comcast.net +jimwegner@comcast.net +jim_hurrell@msn.com +jjkehm@cox.net +jjkehm@yahoo.com +jjkern75@yahoo.com +jk121222@teradata.com +jkane@paramount-group.com +jkatsoudas@yahoo.com +jkbraz@sbcglobal.net +jkg9814@aut.ac.nz +jklundin@gmai.com +jklundin@gmail.com +jkosich@e-s-g.com +jk_allen13@hotmail.com +jloria23@hotmail.com +jloria@pershing.com +jlynch@orlandoheart.com +jm22508@yahoo.com +jmanton@earthlink.net +jmarshall@andersonenergy.ca +jma_tri@yahoo.com +jmcooper@beeb.net +jmickle@comcast.net +jmmassie@massiefirm.com +jmmckenzie@gmail.com +jmooney562@verizon.net +jmsdgriffis@gmail.com +jnieuwsma@yahoo.com +joanne@3pconsults.com +joea@olg.com +joeconn4@comcast.net +joel.toms@gmail.com +joel.toms@ms.com +joelk94@gmail.com +joepereyra@hotmail.com +joezonts@hotmail.com +joe_conlin@conlins.com +johan@lundintriathlon.com +john.bergquist@charter.net +john.duffney@sympatico.ca +john.friebely@opco.com +john.labonte@sbcglobal.net +john@angusmedical.com +john@broadmarkets.com +john@konadreaming.com +john@kosich.net +john@windowgang.com +johna@mac.com +johndesselletdy@yahoo.com +johnfell4@hotmail.com +johnjwatkins@nyc.rr.com +johnkim@mac.com +johnmhimes@yahoo.com +johnnyfranzen@hotmail.com +johnpflores@gmail.com +johnrandallkim@gmail.com +johnrkim@lycos.com +johnrkim@yahoo.com +johnwcoffey@comcast.net +john_p_katsoudas@amat.com +john_ransweiler@yahoo.com +jollyrogers@cox.net +jollyrogrs@hotmail.com +jon@jonmcdonnell.com +jonathan.salkin@rbs.com +jonblyer@yahoo.com +jongalvan@verizon.net +jonnyfudge@yahoo.ca +jordanrapp@gmail.com +jorge@pbmcoaching.com +josharper@hotmail.com +joshaughn@hotmail.com +joshua.thigpen@gmail.com +joshweiss@sbcglobal.net +joslynn_k@yahoo.com +joury.gokel@skynet.be +jovaniglesias@yahoo.com +jpmadzin@hotmail.com +jprusso@cox.net +jpvaud@comcast.net +jp_bachman@yahoo.com +jradench@cityofgp.com +jrfalck2@yahoo.com +jrfalck@verizon.net +jrfalck@yahoo.com +jridout83@yahoo.co.uk +jriosa@earthlink.net +jrxl99@aim.com +js140usa@optonline.com +js@jschwarz.com +jsandula@visteon.com +jsargevt@gmail.com +jschwarz@microsoft.com +jshunt1@yahoo.com +jsmyklebust@yahoo.com +jstonebarger@tufts-nemc.org +jtaylor1024@gmail.com +jthweatt0816@aol.com +jthweatt@nis-retail.com +jtsiofas@sympatico.ca +juancarlos_ramirez@yahoo.com +juddshea@kc.rr.com +juddshea@ku.edu +judiced@yahoo.com +judicekay@yahoo.com +judyreiberg@aol.com +juli530@hotmail.com +juliad@rogers.com +julian.allen@nats.co.uk +julie.beston@gmail.com +julie.beston@umontana.com +julieandadam@gmail.com +jungletrauma@gmail.com +juno@dogmile.com +just2dream@earthlink.net +justgoldens@aol.com +justin.baum@jwt.com +justin.jakowski@sbcglobal.net +justin.jakowski@ticketmaster.com +justin@justin-baum.com +justinbaum34@gmail.com +juststef@roadrunner.com +juweiss@gmail.com +jverstraete@usg.com +jwilson60@mail.gatech.edu +jwmtri@gmail.com +jwrdds@comcast.net +jwrdds@midsouth.rr.com +jwthomps@yahoo.com +j_supak@hotmail.com +k05@aol.com +kac94@alum.dartmouth.org +kachinarescue@cox.net +kakita87@yahoo.com +kanpantanapichet@yahoo.com +kansaiben@hotmail.com +karindole@hotmail.com +kate.mcswain@gmail.com +kathleen.shannon@gmail.com +kathy_645@yahoo.com +katie@fleetfeetstlouis.com +katy@kona.net +kbenton@socs.k12.in.us +kbiek@sbcglobal.net +kbk69@hotmail.com +kbrauer@elknet.net +kbschab@comcast.net +kbuonerba@hotmail.com +kbuonerba@stanfordalumni.org +kbuonerba@yahoo.com +kcolborne@smwauto.com +kcorwen@bellatlantic.net +kcorwen@verizon.net +kdhood2202@sbcglobal.net +keauwong@gmail.cm +keauwong@yahoo.com +keen@frisks.dk +kellybenit@hotmail.com +kellybergkessel@gmail.com +ken.corwen@verizon.net +ken@pr.uoguelph.ca +kendrabail@aol.com +kenku@pr.uoguelph.ca +kenluvsjody@msn.com +kenneth.a.corwen.94@alum.dartmouth.org +kennlaura@yahoo.com +kent@homelogic.cc +kentonmann@gmail.com +kenwil1@mac.com +keren.miers@oakwoodasia.com +kerstenlumber@charter.net +kestrelgurl@yahoo.com +kevin@kabuilders.com +kevin@mckenna2.demon.co.uk +kevinhetzel@hotmail.com +kevinmlong@gmail.com +kevinrise@cox.net +kevprcll@aol.com +keymastr1@earthlink.net +khai.lee@mckesson.com +khailee@gmail.com +khanson@colonyins.com +khetzel01@hotmail.com +khoskinson@hembreeco.com +kichula1@comcast.net +kichula@yahoo.com +kidsintraining@nc.rr.com +kimiroinla@yahoo.com +kirgisdc@embarqmail.com +kjd650@hotmail.com +kkokal@gmail.com +kkupe2@yahoo.com +klehner@att.net +klein.jason@principal.com +klein8527@gmail.com +kloemail@optonline.net +klucy@u.washington.edu +klucy_26@yahoo.com +kluoni@aol.com +kluoni@comcast.net +kmanning@bbn.com +kmceneaney@yahoo.com +kmdillon@charter.net +kmiers@hotmail.com +kmiers@oakwood.jp +kmtanzer@sbcglobal.net +kndalternate@yahoo.com +knwatari@yahoo.com +kogan.bao@gmail.com +komspoon@aol.com +komspoon@hotmail.com +konabound5175@gmail.com +kory.kozar@gmail.com +kozz_mo@yahoo.com +krab1310@sbcglobal.net +krc2293@yahoo.com +krgregg@gmail.com +kristenruffner@aol.com +kristinaogjesper@mail.dk +kristinaogjesper@yahoo.dk +krmorrissey@earthlink.net +krverstraete@yahoo.com +kschab@comcast.net +kschmottlach@hotmail.com +kschreiner21@hotmail.com +kseelman@charter.net +ktanzer@imperialcapital.com +kthieme@sbcglobal.net +ktkva@msn.com +ktokany@mts.net +kuchman@gmail.com +kudo@sentex.ca +kurt.jackson@udayton.edu +kurt@kurtluoni.com +kurt@pbmcoaching.com +kurtandjulie@bigfoot.com +kwelch@alum.mit.edu +kwman@verizon.net +kyillee@yahoo.com +kyle.pawlaczyk@gmail.com +kylegillooly@gmail.com +kyleyost@gmail.com +kyleyost@hotmail.com +kyleyost@yahoo.com +kyoung@b-online.com +kyra.gilbert@pepsi.com +kyragilbert@gmail.com +l8wahoo@yahoo.com +lakersoversuns@hotmail.com +lanawolpert@hotmail.com +landrews@wesleyan.edu +lantz2@llnl.gov +laraandandrew@hotmail.com +larkincarter@comcast.net +larkinkk@hotmail.com +larsdunlap@hotmail.com +larserik.gustafsson@gmail.com +laurent-natalie@bluewin.ch +lauriefamily@telus.net +lawrence.and.trish@sympatico.ca +lawrencebain@yahoo.ca +lbkissel@comcast.net +lcaugustine@yahoo.com +ldsloan@attglobal.net +leanne.charnas@hyradix.com +leanne@tritechmultisport.com +leannecharnas@yahoo.com +leannmb@frontiernet.net +lee.robb@sbcglobal.net +lee.schwartzman@gmail.com +lee@robbsw.com +lee@zn4.org +legendontour@gmail.com +legonis@hotmail.com +lennart.quecke@web.de +leslie.teed@gmail.com +lesliebagalso@gmail.com +lesliebagalso@yahoo.com +leslieshea@kc.rr.com +lethbri1@gmail.com +leung1234@rogers.com +lexi.tejeda@c-b.com +lexiehinds@yahoo.com +lheppler@comcast.net +liam.woods@bms.com +liberty797@aol.com +lighthouse1123@yahoo.com +lindell@isomedia.com +lisasslimstud@yahoo.com +lisa_parillo@yahoo.com +litch@clm.utexas.edu +litch@stanford.edu +littlejuls@gmail.com +liyagilbert@gmail.com +lkukta@sbcglobal.net +llblack@uab.edu +llcljx@gmail.com +lmbarr@frontiernet.net +lmcguire@iit.edu +lmkern@hotmail.com +lmlivingston@comcast.net +longcoursetri@yahoo.com +lourencob@hotmail.com +lparillo@adobe.com +lpp5189@gw.njsp.org +lrobb2@gmail.com +lschmutz@probert.com +lschwartzman@ssds-hartford.org +lsh18@hotmail.com +lstiteswhite@aol.com +lurchi321@web.de +lynda@hickmanstein.ca +l_gramann@hotmail.com +m.holitzer@gmx.net +m.perry@ndy.com +m1sh4p@hotmail.com +m5189@optonline.net +ma1708@hotmail.com +mabbott1@nc.rr.com +mac@rdahead.com +madisonbucky@uwalumni.com +mae.resurreccion@morganstanley.com +maggi.mark@bls.gov +maggs.morris@gmail.com +maggsmorris@gmail.com +maijaleenalow@hotmail.com +maijaleena_zucker@atlanticmutual.com +mailbox.anonymous@gmail.com +malivar@yahoo.com +malodoen@yahoo.com +malte.buchholz@online.de +manukau@bikebarn.co.nz +marathoner31@hotmail.com +marathoner@gmail.com +marathonnh@yahoo.com +marcel@ecoscreen.ca +marcelnavarro86@gmail.com +marcielou2@yahoo.com +marcos@ccem.com.br +marcos@zekiturbo.com +marcostilkian@hotmail.com +marcrospam@robards.org +marf27@gmail.com +marianaphipps@yahoo.com +mark.daniel2@verizon.net +mark.frederickson1@navy.mil +mark.kirby@kimball.com +mark.seale1@cingular.com +mark.seale@gmail.com +mark.thayer@etrade.com +markbodak@yahoo.com +markcorley@gmail.com +markgryn@gmail.com +markharms234@hotmail.com +markk@monarchexcess.com +markus.flade@gmx.de +markwatson48@hotmail.com +markwillis76@yahoo.com +marsue00@gmail.com +marsue00@yahoo.com +martin.duffell@flydba.com +martin@ljungqvist.se +marvin.hates.hotmail@gmail.com +marvin523@houston.rr.com +marvin_selga@hotmail.com +maryb@sentania.net +maryka@pobox.com +maskaggs@comcast.net +massoomi@cox.net +matos_marcello@yahoo.com +matt.inzeo@gmail.com +mattberner@hotmail.com +mattbigos@earthlink.net +mattfreeman@alumni.brown.edu +matthemberger@yahoo.com +matthew.beals@hardrockers.sdsmt.edu +matthew.d.hemberger@gsk.com +matthew.duffey@thomson.com +matthew.lai@law.columbia.edu +mattlai78@hotmail.com +mattlai@gmail.com +mattlai@stanfordalumni.org +mattlai@yahoo.com +mattregan15@gmail.com +mattregan1@juno.com +mattregan1@yahoo.com +matts@mbm-idt.com +mattswanwick@everestkc.net +mattywork@hotmail.com +maureen.sanderson@utb.edu +maxseraj@hotmail.com +maxwellwa@aol.com +maxwellwa@gmail.com +mayjackson@nc.rr.com +maylene@nc.rr.com +may_chris01@hotmail.com +mbarker@hcps.us +mbatum@yahoo.com +mbown@hotmail.com +mbrauer@elknet.net +mbrenns@yahoo.com +mbrisnehan@weltonstreet.com +mbware@bellsouth.net +mb_ware@hotmail.com +mcaiazzo99@yahoo.com +mcastle@cox.net +mccarthyef@msn.com +mcdorman@scn.org +mcginniw@marist.com +mcgu0122@umn.edu +mchristian@kvie.org +mckay01@sbcglobal.net +mckennam123@hotmail.com +mckenzie_james@hotmail.com +mckenzjm@indiana.edu +mclamb6@hotmail.com +mcoughlin@hrsrh.on.ca +mctriguy@yahoo.com +mdaniel@peerlessmfg.com +mdavila@vmware.com +mdc801@gmail.com +mdd1314@hotmail.com +mddennis@iupui.edu +mdelese@stevens.edu +mdfr33@aol.com +mdixon@biosite.com +mdraegerpdx@gmail.com +megalotis@hotmail.com +meganeflaherty@yahoo.com +melissagirly@gmail.com +meowelk@yahoo.com +mesagsxbkr1@yahoo.com +mesagsxbkr@gmail.com +mesagsxbkr@hotmail.com +mfadorick@verizon.net +mflcpa@aol.com +mfosterwa@yahoo.com +mgay17@cox.net +mhalasy@yahoo.com +mhipp@ucla.edu +mhuebsch@rogers.com +mibe@jamak.com +michael.bakker@wachovia.com +michael.benton@erau.edu +michael.benton@us.army.mil +michael.coburn7@yahoo.com +michael.reedell@siemens.com +michael.riley@cs-americas.com +michael.schwing@ssa.gov +michael.shannon@patmedia.net +michael.w.caiazzo@citi.com +michael.williams@itg.com +michael.woodford@cgi.com +michaelamullins@hotmail.com +michaelcshale@gmail.com +michaele@biology.usu.edu +michelenezimarvin@houston.rr.com +michellelpaul@aol.com +mickeyedlin@hotmail.com +mickeyedlin@yahoo.com +midsole@gmail.com +mikaelcars@hotmail.com +mike.mullins@ars.usda.gov +mike.sanchez@comcast.net +mike@dennisnews.com +mike@discomfortzone.com +mike@reedell.com +mikeblagden@gmail.com +miked@lexingtonbrd.com +mikedahlhauser@mail.com +mikegee20@hotmail.com +mikehedman@yahoo.com +mikelaurich@sbcglobal.net +mikellardizabal@yahoo.com +mikemckeejr@cox.net +mikeromesser@gmail.com +miketass@comcast.net +mikey007@post.cz +mike_platzke@yahoo.com +mike_shannon@triathlete.com +mike_skaggs@agilent.com +milesmookie@bellsouth.net +milkywaye@gmail.com +misa7262003@yahoo.com +missingmarblez@aol.com +mitchmw2@hotmail.com +mitchtdc@aol.com +mjasoncarol@bellsouth.net +mjayshapiro@gmail.com +mjbeals@iupui.edu +mjfeeney@hotmail.com +mjlin@iupui.edu +mjmaggi@gmail.com +mjmusolf@yahoo.com +mjpdc@aol.com +mjuric@protech-dmfg.com +mkilfoil@jfkilfoil.com +mkirby@insightbb.com +mkirby@kimball.com +mlbdenver@gmail.com +mleader.mba2001@ivey.ca +mleader13@yahoo.ca +mleader@gmail.com +mlemmon@mindspring.com +mlkhoof@sbcglobal.net +mlm539@psu.edu +mmamales@utahbroadband.com +mmarreco@gmail.com +mmarvin@tamlp.com +mmckinney88994@roadrunner.com +mmfred@roadrunner.com +mml2111@columbia.edu +mmmei@aol.com +mmorris@hawaiiantel.net +mmrocker13@yahoo.com +mmuurisepp@hotmail.com +mmuurisepp@simpad.com +mmuurisepp@triad.rr.com +mnavarro@navarro.com +mojoe@mho.com +mollybeedan@yahoo.com +montanir79@hotmail.com +montyman007@hotmail.com +mosesc@rogers.com +motorhead9876@yahoo.com +mpahnke@mail.utexas.edu +mpc82@aol.com +mr.heatmiser@gmail.com +mrao01@cox.net +mrbyerle@admmail.uwaterloo.ca +mrknuckle@austin.rr.com +mrqr@triathlete.com +mrsamishrakebattle@gmail.com +mrthibodeau@yahoo.com +ms6681@att.com +msb5014@psu.edu +mschraad@mac.com +mschwing@hotmail.com +msellon@gmail.com +msjsss@yahoo.com +msmith1638@gmail.com +mspinkky@aol.com +mspmadz@mac.com +msunderwd@yahoo.com +mtcnaa@aol.com +mtianco@gmail.com +mtianco@yahoo.com +mtnbums@centurytel.net +mtodd615@yahoo.com +mtuck@cox.net +mulderp@hotmail.com +muskrad@comcast.net +muskrad@gmail.com +musky48in@gmail.com +mwbaize@yahoo.com +myudizky@austin.rr.com +myunghcho@gmail.com +m_bechtol@yahoo.com +m_sherrick@msn.com +n2orbit@gmail.com +naconfer@aol.com +namssob@namssob.com +nathan.fallowfield@au.abnamro.com +nathanwallacemsvu@hotmail.com +nbohn@gmx.de +nbohn@princeton.edu +ncharleston@gmail.com +ncharleston@mccannonline.com +ncharleston@yahoo.com +nealhe@cox.net +nealhe@gmail.com +nebmot@mac.com +neilgmiller@hotmail.com +neilsimon@gmail.com +ner1021@ecu.edu +nery7d@mizzou.edu +neuschwander@alum.dartmouth.org +neverbent@gmail.com +newbzizbald@aol.com +newbznewbz5522@yahool.com +newman.noggs@gmail.com +nick@nickmathers.com +nickmathers2@hotmail.com +nicolas.christin@laposte.net +nicolas.logan@gmail.com +niels.knutson@gmail.com +niels.knutson@mail.house.gov +nielsen_derek@hotmail.com +niels_knutson@yahoo.com +nikki@nutritionmechanics.com +nikkireed82@hotmail.com +nikkireedrdld@gmail.com +niklas.bohn@gmail.com +nikolaikim@mac.com +nippycrisp@gmail.com +nkb@gmx.de +nmcculloch@stthomas.edu +nmorales@qwest.net +nmsimon@jonesday.com +noahsbackup@hotmail.com +nogborn@indiana.edu +norton@vineyard.net +nstanziola@netscape.net +nwtool@pcpros.net +o317@yahoo.com +odonneld@gmail.com +oglesby_mark@hotmail.com +ohtrigeeks@verizon.net +oliver.doggie@gmail.com +omnihenry@excite.com +oneononefitness@sbcglobal.net +one_lap@hotmail.com +ostomyathlete@hotmail.com +outfitting@bx3.com +owen_meany@rocketmail.com +ox1@comcast.net +oyajiben@cox.net +p.tilbrook@telstra.com +pastryward@yahoo.com +patcrannell@yahoo.com +patrick.oh@ucsf.edu +patrickdshaver@hotmail.com +patrickoh@mac.com +patrickoh@yahoo.com +patrick_myers@rsh.net +patrox1@msn.com +paul.schon@gmail.com +paul.waye@ordina.nl +paulchiropractic@aol.com +pauldjesse@gmail.com +paulfdunn@yahoo.com +paulfernandez@yahoo.com +paulhietala@yahoo.com +pauljfernandez@gmail.com +paulm@expectek.com +pbarnes@bx3.com +pberlin691@aol.com +pbrichardson@earthlink.net +pbskaggs@nas.com +pdh@tasmanorient.co.nz +pedergraham@yahoo.com +peelee1973@hotmail.com +per.jorgen.walstrom@bouvet.no +perezcor2002@yahoo.com +pericson@campnet.utah.edu +pernst6000@aol.com +pete@ukscuba.com +peter@sub17.com +peter@ukscuba.com +peterfirth3@gmail.com +peterg3@pbgast.com +petersen.tom@gmail.com +petersen02@gmail.com +peterson02@gmail.com +pgoldberger@adelphia.net +phan@star-capital.com +phil.barnes@gmail.com +philippians44@charter.net +phobetor42@hotmail.com +pjacross@comcast.net +pjnowlan@sympatico.ca +pjtoft@hotmail.com +pjwalstrom@gmail.com +pkardosh@hotmail.com +pkkcmason@comcast.net +pkwching@yahoo.com +plclark@buffalo.edu +pmalokas@hotmail.com +pmccall777@gmail.com +pmccall777@yahoo.com +pocolocoman@gmail.com +poh@acsr.ucsf.edu +poh@php.ucsf.edu +poh@usfca.edu +poob@msn.com +porrickjr@yahoo.com +porterbratten@gmail.com +ppierobon@gmail.com +ppierobon@hotmail.com +prajna101@hotmail.com +proverbs30@hotmail.com +pr_de_jong@hotmail.com +pschmidt@tilfordlaw.com +pschon@equuscs-isv.com +pschon@equuscs.com +pshanso@yahoo.com +psssst2u@gmail.com +pstriathlon2007@gmail.com +pstriathlon@gmail.com +pt.miettinen@kolumbus.fi +pulsatingstar2003@yahoo.com +putuunder2@yahoo.com +pvanmeter@charter.net +pvmspa@yahoo.com +pwaye@insinger.com +pww@grummanbutkus.com +qtip1049@yahoo.com +quagmire001@hotmail.com +quigley_bp@hotmail.com +r.k@engineer.com +r.stan1@yahoo.com +racerx9966@gmail.com +rachelsayrachel@gmail.com +rachelsayrachel@yahoo.com +rachelsross@hotmail.com +racing@playbookforlife.com +rafaeldonnay@yahoo.com +randyfeatherston@sbcglobal.net +randyholloway@sbcglobal.net +ranga8527@hotmail.com +rarnold@unvlt.com +rasm@sunlite.ca +raysworking@yahoo.com +rcarter@hcm2.com +rcnst6@aol.com +rdracer1@hotmail.com +rdrvctr@aol.com +reho@geneseo.edu +remnfa@yahoo.com +reneej1a@mailcity.com +reppost@hotmail.com +research.joe@gmail.com +re_butler@hotmail.com +rgaisser@hpinstitute.com +rgallegos@ch.cablemas.com +rgiebelhausen@yahoo.com +rgordon9876@yahoo.com +rgr195@earthlink.net +rhevelo@gmail.com +rhodeshg@hotmail.com +rhyspencer@yahoo.com +ricetommy@yahoo.com +rich@fit2tri.com +richard@richard-armstrong.net +richard@richardbladon.com +richard@transition1.co.uk +richardr@triathlete.com +richw1316@aol.com +rick.ashburn@richardashburn.com +rileygreene@msn.com +rischaard@hotmail.com +rjensen3566@aol.com +rjgug@cox.net +rmalinow22@yahoo.com +rmcgrath2@indy.rr.com +rmcnary@kyyouth.org +roadandtrisports@speakeasy.net +rob.allen@cgi.com +rob.mcnamara@auspost.com.au +rob.parkhill@gmail.com +rob2681@yahoo.com +roballen99@gmail.com +robdick2003@yahoo.com +robert.brady@mbda-us.com +robert.lee@fmr.com +robert.shultz@philips.com +robert@bnrg.com +robertbrady1159@hotmail.com +robertdi8@hotmail.com +roberto_a_gallegos@hotmail.com +robertp@cityofws.org +roberttx@gmail.com +robert_a_riley@yahoo.com +robert_castaldi@yahoo.com +robmw2@yahoo.com +robw0124@hotmail.com +robwood141@mac.com +rob_peiffer@hotmail.com +rockasm82@hotmail.com +rocketopia@yahoo.com +rockfordtri@protech-dmfg.com +rockhead_44@hotmail.com +rogers.zach@gmail.com +rogueclimber@yahoo.com +romanmica@hotmail.com +ron.teed@gmail.com +ronald_dooley@excite.com +ronrris@austin.rr.com +ron_coleman@tempe.gov +roperrk@earthlink.net +rorris@staktek.com +ross_strader@hotmail.com +rourinho@comcast.net +rp@indegomedia.com +rqarnold@comcas.net +rrfr@sbcglobal.net +rrobinson@dgso.org +rroeder1@zoominternet.net +rrwomack@charter.net +rscheung@yahoo.com +rscheungrab@randomhouse.com +rshultz@rochester.rr.com +rskissel@comcast.net +rsoibel@hotmail.com +rsum716@aol.com +rundle88@hotmail.com +rundru@yahoo.com +runinmn@yahoo.com +runmuch@gmail.com +runningmanrick@yahoo.com +runpuddrun@gmail.com +runswim01@hotmail.com +russell.cox@ntlworld.com +rvanmeir@nc.rr.com +rvigeant@comcast.net +ryan.yowell@bankofamerica.com +ryan.yowell@sungard.com +ryan5283@gmail.com +ryle54@comcast.net +rzellers@naicir.com +rzisk1@hotmail.com +r_tourinho@hotmail.com +s.binzer@insightbb.com +s.sutphen@hotmail.com +sailnfast@yahoo.com +sales@mmakbenton.net +sales@savarace.com +samba_de_orfeu@yahoo.com.mx +sanderc1@seattleu.edu +sara@theconlins.com +sarahkaczor@gmail.com +sarahpalmertoo@gmail.com +saroehrborn@yahoo.com +savarace@gmail.com +savoie_d@denison.edu +sb-2228@tampabay.rr.com +sbadog@hotmail.com +sbinzer@gdms.com +sbohlig@rogers.com +sbrmjm@comcast.net +scd1616@yahoo.com +scduncan@gmail.com +schmittb3b5@yahoo.com +schonstl@sbcglobal.net +schwabe@gmail.com +schwingding@gmail.com +scomosr@jenscoinc.com +scomosr@yahoo.com +scot.barnette@jetblue.com +scott.colvin@netaspx.com +scott.haraburda@globalcrossing.com +scott.herrick@iese.net +scott.loong@gmail.com +scottacolvin@hotmail.com +scottandtobi11@comcast.net +scottb@frontline-realestate.com +scottb@sentania.net +scottbowe@northwesternmutual.com +scottgo18@gmail.com +scottgo18@yahoo.com +scotthetrick@comcast.net +scottmatney@yahoo.com +scottspees@hotmail.com +scottwlayton@earthlink.net +scstuart@bigfoot.com +sdeboer@amfam.com +sdoherty@nycap.rr.com +sdurrwachter@prg.com +seandrea@comcast.net +sean_slanger@bcbsmt.com +seattletk@hotmail.com +secorcompany@aol.com +secorholdings@aol.com +seejay@interchange.ubc.ca +sergio_escutia@prodigy.net.mx +sethm2@mac.com +sf.nolan@gmaikl.com +sf.nolan@gmail.com +sfdan2006@yahoo.com +sgauthie@kcc.com +sgramann@hotmail.com +shaledog@hotmail.com +shaned@corsairmemory.com +shanetw@yahoo.com +shannonkent@gmail.com +shannonpworthen@hotmail.com +shark71@gmail.com +shawley@camber.com +shawn.deboer@gmail.com +shawn@systemsports.net +shawn@wetri.net +shawnfrack@yahoo.com +shea.grob@gmail.com +shempler@sis-sf.com +shmacleo@staff.ednet.ns.ca +sierrachallenge@yahoo.com +sigerson@charter.net +signmeup@nickbrown.ca +signu459@hotmail.com +silvie1072@yahoo.com +simon.minshull@aol.com +simon.ree@gmail.com +simoncompany@hotmail.com +simon__carter@hotmail.com +sindre73@online.no +sitfrisco@yahoo.com +sjenkins@umassd.edu +sjudice@triathlete.com +skallsen@lljohns.com +skid777@hotmail.com +skigirl40@mindspring.com +skoontz1@carolina.rr.com +slidecontrol@hotmail.com +slideroseland@hotmail.com +slowman@slowtwitch.com +slowtriathlete@gmail.com +slowtwitch@strader.org +slowtwitch@wizgird.com +slu_bills@yahoo.com +smartasscoach@clix.pt +smb2003@msn.com +smiller1@snet.net +smorgan@teknarus.com +smoze2@comcast.net +smtovey@doctors.net.uk +smtovey@doctors.org.uk +snav@bellsouth.net +snjjamison@sbcglobal.net +soenke_koerber@scotiacapital.com +soinwi@yahoo.com +solymosi@telus.net +soontofu@mac.com +soper2000@rogers.com +sorel_ops@hotmail.com +souzchef@comcast.net +sowhatnow5@hotmail.com +soyasoya@gmail.com +spacemoonman1971@yahoo.com +spalmer2@maine.rr.com +spector36@yahoo.com +sperry@cinci.rr.com +sperry_card@yahoo.com +sploolaf@yahoo.com +spmcgrew@phila.k12.pa.us +sports@battles.cc +squid917@nc.rr.com +srdunn@earthlink.net +srlandry@hotmail.com +srogers@nascar.com +srplunkett@cox.net +srs@hogefenton.com +ssloat@hotmail.com +ssmiddy@yahoo.com +stacyftaylor@yahoo.com +stacyoseland@hotmail.com +stageracer@gmail.com +stallion1031@yahoo.com +starkbl@gmail.com +steelbicycle@gmail.com +steep_h20@yahoo.ca +stefan.reinke@gmail.com +stefbates@hotmail.com +stefmoreau@shaw.ca +stephan.m.boianoff@boeing.com +stephane_oddos@yahoo.fr +stephanjoe@gmail.com +stephen.ake@myfloridalegal.com +stephen.h.kukta@sprint.com +stephenake@hotmail.com +stephencann@gmail.com +stephencann@hotmail.com +stephen_simmerman@yahoo.com +steve.cramer@onebox.com +steve.cramer@rhi.com +steve.perkins@perxnet.com +steve@guerrillamultisport.com +steve@littlegiantengineering.com +steve@perxnet.com +stevebs2003@cox.net +stevefluet@gmail.com +stevekoci@cox.net +stevenazarian@gmail.com +steveperx@gmail.com +steveperx@yahoo.com +steves6@cox.net +stevevaughn585@hotmail.com +steve_uccello@yahoo.com +stewart.a.pratt@gmail.com +stewartj76@gmail.com +stikitoad@hotmail.com +stlemming@gmail.com +stockpickerkid@yahoo.com +stpatterson@comcast.net +strategicprofessional@yahoo.com +strirun@aol.com +strukljv@vcu.edu +stsnd@yahoo.com +stuart@otag.co.uk +stuckey_bowler@yahoo.com +st_42@msn.com +subs@competitiverunner.com +sueb37@hotmail.com +sumar@onlinehome.de +sunnyshergill@hotmail.com +sunrisetbird@hotmail.com +supaman4992@yahoo.com +supreme_ff_owner@yahoo.com +surfnmat@aol.com +susan.marston@hp.com +susanherself@netzero.com +susanherself@netzero.net +sutherlands@saic.com +sweetpatty@nc.rr.com +swellco5@yahoo.com +swinseattle@hotmail.com +swmnh01@yahoo.com +swtyphoon@yahoo.com +sydnrusty@excite.com +szekula@sympatico.ca +t.breidthardt@web.de +t.breidthardt@yahoo.com +t.r.morris@comcast.net +tai@taigraphx.com +taku@ureach.com +tanderson@nilfisk-advance.com +tanguay.jeff@gmail.com +tarynwalker@houston.rr.com +tazrun@juno.com +tbro@bellacor.com +tbrophwg@yahoo.com +tbrower@uberprojects.org +tburgum@yahoo.com +tcarrier@mail.com +tdavis4339@hotmail.com +team@mmakbenton.net +teambridges@cox.net +teamtetra2003@yahoo.com +teastwick@gmail.com +teepeecreek@gmail.com +tellmikey@gmail.cz +temples@bundigi.com +tere@roxcompany.com +terramar@sbcglobal.net +terrencelee@yahoo.com +terrencetlee@gmail.com +terrencetlee@yahoo.com +texaswilmots@verizon.net +tffort@comcast.net +tffort@gmail.com +tfgordon@shaw.ca +tfort@comcast.net +tgarner@ikon.com +tgarv@hpipi.com +tgordon@mapleridge.ca +tg_espy@yahoo.com +thanninen@comcast.net +theanhalts@cox.net +theanhalts@yahoo.com +thebicyclecafe@yahoo.com +thephytoman@gmail.com +therevjoe@ecmbia.org +theriaultderek@hotmail.com +the_leader@hotmail.com +thibautr@gmail.com +thibodrj@airproducts.com +thomas.fort@comcast.net +thomas.petersen@yahoo.com +thomasvoyten@hotmail.com +thomasvoyten@yahoo.com +thomps@triathlete.com +thomsond@gmail.com +thp3@duke.edu +threetimesasgood@yahoo.com +thuddy@sbcglobal.net +thuebner@rcn.com +tidriver@comcast.net +tim-mech@excite.com +tim.barnaby@comcast.net +tim@stockman.biz +timbhudson@aol.com +timco2004@yahoo.com +timkrone@mac.com +timmy3000rocks@hotmail.com +timote@aol.com +timothy.morris@novaquest.com +timothy.parillo@barclaysglobal.com +timothyparillo@yahoo.com +tims@fertilebeltrami.k12.mn.us +timvanepps@gmail.com +tim_kingston@hotmail.com +tjohnson@purina.com +tjsmit2@gmail.com +tjstockert@mchsi.com +tkmillerfsu@earthlink.net +tlantz@calpoly.edu +tlessek@cinci.rr.com +tmdarlin@iupui.edu +tmrutherford@yahoo.com.au +tmrutledge@sympatico.ca +tneuschw@ucsd.edu +tobin@maxkuney.com +tobinsn@libbey.com +tocopherol@gmail.com +todd-geddes.s@neu.edu +todd.anthes@gmail.com +todd.dole@gmail.com +todd.hoopman@utsouthwestern.edu +todd.proulx@citigroup.com +todd_darlington@hotmail.com +todd_e_pearson@hotmail.com +togrady@kerrycoco.ie +tom.fenn@marsh.com +tom.petersen@duke.edu +tom.petersen@yahoo.com +tom.petersen@yale.edu +tom@bundigi.com +tom@recovox.net +tomgallag@hotmail.com +tomhiga@hotmail.com +tomkamin@yahoo.com +tomliby@yahoo.com +tommobarker@btopenworld.com +tommypetersen@gmail.com +tommypetersen@hotmail.com +tomrinkavage@yahoo.com +tomwork@msn.com +tonicgoup@gmail.com +tony.chan@intel.com +tonybrutsche@yahoo.com +tonyschan@cox.net +toofewbikes@yahoo.com +toryviper@yahoo.com +townwagon58@yahoo.com +tp.financial@yahoo.com +tp.research@gmail.com +tp247@email.med.yale.edu +tpcello7@gmail.com +tpcello7@yahoo.com +tpetersen02@gmail.com +tpeterson02@gmail.com +tpotenza@spfldcol.edu +tproulx@maine.rr.com +tpweyland@aol.com +tracertheracer@hotmail.com +traceysund@aol.com +tracyrobertsonfrack@yahoo.com +training@ukscuba.com +traumaadam@hotmail.com +travis@campmor.com +travisd@campmor.com +trcaw@wideopenwest.com +trevor.casper@marlinenergy.net +trey_stolz@yahoo.com +tri4jay@hotmail.com +tri4jay@yahoo.com +triathlon06@yahoo.com +triathltb@msn.com +tribabe@gmail.com +tribato@hotmail.com +tribent@online.no +tricat77@gmail.com +tricia.callahan@wku.edu +tricutcher@buckeye-express.com +tricyclist@gmail.com +tridennisr@aol.com +tridocgi@hotmail.com +tridru@gmail.com +triedntrue@charter.net +triforlife7@hotmail.com +trigeezer@gmail.com +trigirl214@yahoo.com +trigirl3@ufl.edu +triguy76@gmail.com +triguywillie@hotmail.com +trihanrahan@yahoo.com +trihard@nc.rr.com +trikellyk@yahoo.com +trikpark@roadrunner.com +trimanium88@triathlete.com +trimix-1@comcast.net +tripower2000@gmail.com +tripower2000@msn.com +trirocket1@aol.com +trirocket1@yahoo.com +trirooster@bellsouth.net +trisax62@yahoo.com +triscooter@verizon.net +tristuff@sherimcnabb.com +triwakefan@aol.com +tri_2005@hotmail.com +tri_ath@hotmail.com +tri_ox@hotmail.com +tri_team@hotmail.com +trouble@netreach.net +trvfsub2@yahoo.com +try2tri@cox.net +tryemdad@hotmail.com +tryguy3@gmail.com +tscanlon@ascentvp.com +tsilcyc03@yahoo.com +tsweet@oakville.ca +ttowns2@us.ibm.com +tuckermatthew@mac.com +tvissering@psu.edu +tvoyten@ovsla.com +twcollins@tds.net +twellby@hotmail.com +two_ut_vols@yahoo.com +twtemple@gmail.com +twtemple@mac.com +twtemple@pacbell.net +twtemple@yahoo.com +typer0207@aol.com +tyrod@bellsouth.net +t_gromit@yahoo.com +ultra58@yahoo.com +unclenutz@gmail.com +unreale@aol.com +usphsfnp@yahoo.com +val.allen@sympatico.ca +varbuckle2003@yahoo.com +vbezaire@gmail.com +velobunny@aol.com +velodemon@yahoo.com +vida2000@rocketmail.com +vince_matteo@yahoo.com +viningjc@hotmail.com +vital805@aol.com +vog@google.com +vrosetta@gmail.com +v_rosetta@yahoo.com +w220sd@hotmail.com +wadeabrown@gmail.com +wadeabrown@yahoo.com +walksimply@yahoo.com +walstrom@hotmail.com +wangjulian@hotmail.com +wattjunky@comcast.net +wayne.mcleod@fmr.com +waynedustin@gmail.com +wbarn@atlanticbb.net +wclifford@orcabayfoods.com +wdast@sbcglobal.net +weddingreport@gmail.com +weilenmann@gmx.ch +wendilucas@mail2why.com +wendy.lopez@utoronto.ca +wenlucas@email.unc.edu +westkilgore1814@hotmail.com +weswalker2000@yahoo.com +wetri@charter.net +wgw5000@psu.edu +william.battle@rich.frb.org +william.latimer@fhr.com +william.ronco@gmail.com +william@shustoke.com +williamallred@hotmail.com +williams.michael@gmail.com +willmcg4132@yahoo.com +wilthompson@excite.com +wilyamamoto@yahoo.com +wkfleck@yahoo.com +wmine@fma.fujitsu.com +wogstl@gmail.com +wogstl@yahoo.com +wp2883@googlemail.com +wskr39@comcast.net +wtownsle@remc11.k12.mi.us +wvines@comcast.net +wvines@gmail.com +wwaskes@gmail.com +wwduey@yahoo.com +wyllie@dilex.net +xcduluth@yahoo.com +xp@ufl.edu +xthebreezexx@yahoo.com +yakfshr1@yahoo.com +yancey_j@bellsouth.net +yank038@aol.com +yenki20@hotmail.com +yogatkd@yahoo.com +youngwill@gmail.com +ytimewell33@yahoo.com +zach.alpern@gmail.com +zachary.callahan@wku.edu +zane@balancingweights.com +zbarnett@gmail.com +zdreja@cogeco.ca +zev_barnett@coface-usa.com +zripp3@gmail.com diff --git a/slowtwitch.com/wikiconfig/wikiconfig.php b/slowtwitch.com/wikiconfig/wikiconfig.php new file mode 100644 index 0000000..da2ef40 --- /dev/null +++ b/slowtwitch.com/wikiconfig/wikiconfig.php @@ -0,0 +1,16 @@ + \ No newline at end of file