diff --git a/ede-bug-tools/ede-bug-report/BugImage.h b/ede-bug-tools/ede-bug-report/BugImage.h new file mode 100644 index 0000000..933e9d3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/BugImage.h @@ -0,0 +1,387 @@ +#ifndef __BUGIMAGE_H__ +#define __BUGIMAGE_H__ + +#include +static unsigned char idata_bug[] = +{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255, +255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0, +255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255, +255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255, +255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0, +255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255, +255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255, +255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0, +255,255,255,0,255,255,255,0,255,255,255,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,61,30,13, +1,61,30,13,38,255,254,254,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30, +13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,62,32,14,0,77,45,23,0,93,60, +34,0,107,75,48,0,110,78,50,0,96,64,37,0,82,49,27,0,65,34,16,0,59,29,13,0,61,30, +13,0,61,30,13,0,61,30,13,0,61,31,14,0,67,35,16,0,78,46,24,0,67,35,17,0,59,29, +13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,61,30,13,87,61,30,13,17,61,30,13,0,61,30,13,0,61,30, +13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,62,32, +14,0,77,45,23,0,93,60,34,0,107,75,48,0,110,78,50,0,96,64,37,0,82,49,27,0,65,34, +16,0,59,29,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,31,14,0,67,35,16,0,78,46, +24,0,67,35,17,0,59,29,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61,30, +13,0,61,30,13,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,63,32,14,75,61,31,13, +114,43,18,7,0,45,19,7,0,45,19,7,0,45,19,7,0,43,19,7,0,57,28,11,0,62,31,14,0,61, +30,13,0,61,30,13,0,62,32,14,0,77,45,23,0,93,60,34,0,107,75,48,0,110,78,50,0,96, +64,37,0,82,49,27,0,65,34,16,0,59,29,13,0,61,30,13,0,61,30,13,0,61,30,13,0,61, +31,14,0,67,35,16,0,78,46,24,0,67,35,17,0,55,26,11,0,57,27,11,0,57,27,11,0,58, +28,12,0,58,28,12,0,61,30,13,2,62,31,14,3,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +71,40,20,19,75,43,22,221,80,47,24,41,80,48,25,0,80,48,25,0,80,48,26,0,76,45,23, +0,61,30,13,0,61,30,13,0,61,30,13,0,61,30,13,0,62,32,14,0,77,45,23,0,93,60,34, +24,107,75,48,68,110,78,50,76,96,64,37,36,82,49,27,4,65,34,16,0,59,29,13,0,61, +30,13,0,61,30,13,0,61,30,13,0,61,31,14,0,65,35,16,0,80,47,25,0,75,43,22,0,40, +17,6,0,42,18,6,0,42,18,6,0,39,16,6,0,36,14,4,0,55,26,11,102,59,29,13,13,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,77,45,23,181,92,59,34,143,90,58, +33,0,88,58,33,0,92,60,34,0,81,48,25,0,59,28,12,0,61,30,13,0,61,30,13,0,54,25, +10,0,61,30,13,76,76,44,23,196,91,58,33,241,102,70,42,255,104,72,45,255,94,61, +36,249,81,48,25,215,65,34,16,114,61,29,13,10,61,30,13,0,59,29,13,0,61,30,13,0, +61,31,14,0,65,35,16,0,77,45,23,0,86,54,30,0,87,55,31,0,86,54,30,0,86,54,30,0, +78,46,24,0,62,32,14,118,37,15,5,92,29,10,3,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,43,20,7,60,84,54,30,195,57,23,9,0,61,19,7,0,65,30,13,0,69, +38,18,0,61,30,13,0,61,30,13,0,58,28,12,0,100,66,38,162,73,40,19,255,61,30,13, +255,80,47,25,255,90,57,33,255,91,58,33,255,84,52,28,255,73,41,20,255,62,31,14, +255,62,31,14,215,62,31,14,24,65,34,16,0,61,30,13,0,61,31,14,0,65,35,16,0,77,45, +23,0,86,54,30,0,91,58,33,0,88,56,32,0,88,56,32,0,86,53,29,140,57,29,13,201,29, +10,3,8,34,13,4,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,36,15,5, +12,78,48,25,212,67,29,13,53,86,37,18,0,82,42,21,0,69,38,18,0,59,29,13,0,62,31, +14,11,51,23,9,109,87,55,30,239,143,112,81,255,147,116,85,255,85,52,28,255,77, +45,24,255,77,44,23,255,73,40,20,255,63,32,14,255,55,25,10,255,45,18,6,255,58, +32,15,135,83,53,31,34,57,26,10,0,61,31,14,0,65,35,16,0,77,45,23,0,86,54,30,0, +96,63,37,0,96,63,37,0,96,64,37,80,78,47,25,255,33,13,4,84,34,13,4,0,34,13,4,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,76,45,23,165, +93,61,35,240,94,64,37,99,83,52,28,0,68,35,16,0,57,26,11,25,61,30,13,194,62,31, +14,255,47,21,8,255,47,21,8,255,81,49,25,255,126,93,62,255,134,102,72,255,84,51, +27,255,42,18,7,255,43,20,8,255,76,48,27,255,78,57,40,255,81,66,55,255,84,70,59, +231,64,37,20,67,59,28,12,0,65,35,16,0,77,45,23,0,86,54,30,0,97,64,38,0,101,69, +42,4,94,62,36,209,28,10,3,150,29,11,3,22,40,18,6,0,40,18,6,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,45,21,8,26,54,28,12,163,83,51, +27,206,80,47,25,177,77,47,26,84,67,38,20,214,55,25,10,255,61,30,13,255,62,31, +14,255,62,31,14,255,54,25,10,255,49,22,9,255,51,23,9,255,46,21,8,255,34,19,10, +255,51,35,22,255,67,51,37,255,68,55,43,255,75,64,53,255,85,75,68,255,88,78,70, +246,68,41,24,75,65,34,15,0,77,45,23,0,86,54,30,15,96,64,38,113,100,68,41,187,67, +38,18,200,12,3,0,63,37,16,5,1,36,15,5,0,53,25,10,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,37,17,6,5,12,3,0,83,34,15,5,52,46,24,10, +114,104,83,65,243,169,161,160,255,58,31,16,255,45,18,7,255,47,20,7,255,54,24,10, +255,59,29,12,255,62,31,14,255,62,31,14,255,59,29,13,255,36,19,10,255,40,26,16, +255,50,36,24,255,62,47,34,255,70,57,45,255,78,66,56,255,88,80,73,255,88,77,68, +245,53,29,14,166,70,43,22,196,86,53,29,196,87,55,31,205,82,49,27,187,29,11,3, +109,40,19,7,15,45,22,8,0,53,26,11,0,62,31,14,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,42,22,9,0,7,8,3,56,0,0,0,110,170,48,1,136,175, +50,1,214,160,141,125,255,216,214,216,255,170,150,131,255,142,116,94,255,102,76, +55,255,68,40,22,255,59,29,12,255,61,30,13,255,58,28,12,255,31,15,6,255,33,20, +10,255,45,30,18,255,55,40,27,255,64,50,37,255,73,60,48,255,80,71,63,255,73,55, +40,255,147,75,41,255,99,36,14,93,47,27,12,11,46,22,9,20,26,10,3,67,22,8,2,79, +47,23,9,0,45,21,8,0,49,22,9,0,58,28,12,37,62,31,14,33,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,61,30,13,8,62,31,14,8,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,80,33,10,0,107,41,9,0,188,65,7,133,255,101,9,255,255, +103,6,255,190,60,0,255,172,149,125,255,255,254,254,255,255,254,254,255,207,197, +190,255,104,79,60,255,61,32,16,255,61,29,13,255,58,28,12,255,24,10,3,255,24,13, +6,255,39,24,13,255,49,34,22,255,58,43,31,255,65,54,43,255,62,45,33,255,180, +112,75,255,237,132,94,254,168,43,13,163,0,2,0,60,0,0,0,103,4,0,0,119,37,16,5,39, +50,25,10,0,47,23,9,0,34,13,4,0,45,19,7,102,47,20,8,39,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,61,30,13,62,57,27,11,170,53,24, +10,122,61,32,14,49,97,64,38,32,111,80,51,4,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,121,49,13,0,255,110,16,56,255,123,23,249,251,125,27,255,250, +119,22,255,255,110,10,255,162,48,0,255,166,148,126,255,255,254,254,255,254,254, +254,255,167,148,131,255,76,49,31,255,59,28,12,255,59,29,13,255,21,7,1,255,15,6, +2,255,31,18,9,255,43,28,16,255,46,36,24,255,55,47,37,255,185,130,103,255,235, +144,114,255,219,98,67,255,213,62,21,255,120,28,7,149,21,8,2,19,42,19,7,9,57,30, +13,0,85,54,30,0,95,62,36,0,81,48,26,122,51,24,10,156,255,254,254,0,255,254,254, +0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,31,11, +3,13,28,9,3,77,61,32,15,171,88,56,32,221,99,68,41,145,107,76,48,120,97,64,38, +186,81,49,26,160,61,32,16,109,73,33,13,95,245,127,38,206,255,146,48,255,252,143, +48,255,250,135,38,255,251,127,28,255,253,117,13,255,163,57,1,255,147,113,83, +255,227,225,223,255,238,236,238,255,129,104,85,255,61,32,16,255,59,28,12,255,21, +6,1,255,4,0,0,255,18,11,5,255,24,26,21,255,88,75,64,255,192,141,118,255,227, +109,77,255,215,81,50,255,217,83,43,255,214,73,28,255,215,66,23,231,123,40,14,47, +61,38,19,26,91,59,33,61,101,69,43,73,97,64,38,129,77,45,24,242,42,18,7,102,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,22,7,2,2,29,11,3,58,10,2,0,94,42,20,8, +95,67,39,19,133,71,41,20,147,49,24,10,108,155,89,48,205,254,179,112,255,255, +166,83,255,252,157,70,255,251,146,55,255,250,139,42,255,252,136,33,255,255,128, +7,255,209,76,0,255,142,58,11,255,157,128,99,255,165,153,139,255,92,67,47,255, +57,27,11,255,7,4,1,255,5,5,5,255,70,56,50,255,159,111,90,255,211,124,94,255, +222,82,50,255,215,71,43,255,226,87,48,255,224,83,37,255,220,89,41,255,224,85,36, +255,157,55,21,247,62,36,18,211,83,50,27,237,90,57,32,253,78,47,24,218,19,5,1, +123,21,6,1,36,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,36,15,5,33,24,9,2,68,22,8,2,57,21,9,2,63,33,8,1,52,237,137,65,201,255, +182,112,255,255,174,98,255,252,165,85,255,251,151,61,255,255,142,45,255,255,139, +35,255,255,129,10,255,255,122,0,255,252,98,0,255,207,54,0,255,144,42,6,255,69, +32,14,255,21,12,4,255,55,12,2,255,153,64,35,255,215,113,78,255,228,91,56,255, +220,66,36,255,214,58,28,255,211,60,25,255,151,42,14,255,186,64,26,255,227,94,45, +255,224,99,48,255,224,93,41,245,112,40,14,54,34,16,6,29,37,17,6,69,24,9,2,96,10, +2,0,84,29,11,3,14,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,34,20,9,1,0,10,7,34,101,27,2,142,254, +127,29,255,255,156,61,255,253,163,77,255,252,159,74,255,253,148,56,255,232,122, +37,255,217,102,21,255,251,112,4,255,253,111,0,255,249,106,0,255,249,92,0,255, +247,68,0,255,194,35,0,255,100,8,0,255,210,32,1,255,228,49,9,255,225,63,30,255, +216,53,19,255,215,49,14,255,220,50,17,255,133,27,7,255,0,0,0,255,28,4,0,255,197, +71,30,255,229,101,49,255,235,106,49,255,128,44,14,159,0,0,0,95,0,0,0,120,10,2, +0,105,34,14,4,11,34,13,4,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +224,77,7,146,254,122,22,255,252,143,42,255,252,149,54,255,254,148,52,255,236, +128,40,255,115,53,24,255,36,15,8,255,145,44,0,255,255,99,0,255,248,96,0,255,244, +89,0,255,238,70,0,255,231,46,0,255,196,23,0,255,220,33,0,255,219,40,1,255,219, +46,4,255,215,43,7,255,210,39,9,255,214,39,11,255,94,12,3,255,0,0,0,255,0,0,0, +255,131,37,11,255,231,93,42,255,230,102,46,255,198,81,31,210,45,12,3,36,10,5,1, +50,29,11,3,31,46,23,8,0,45,21,8,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,253,85,3,196,252,113,14,255,252,128,26,255,252,132,31,255,255,133,30, +255,219,104,23,255,61,25,12,255,0,2,1,255,83,16,0,255,255,82,0,255,246,81,0,255, +242,80,0,255,237,67,0,255,226,43,0,255,191,23,0,255,217,34,0,255,220,43,2,255, +218,44,4,255,212,35,5,255,206,29,6,255,210,30,8,255,132,18,4,255,0,0,0,255,0,0, +0,255,135,36,10,255,229,86,35,255,226,96,42,255,227,100,42,249,140,52,17,36, +69,22,7,0,26,12,3,0,40,22,9,0,40,21,8,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +114,43,11,88,245,81,0,248,254,102,3,255,252,110,9,255,252,113,12,255,253,111,11, +255,249,102,6,255,114,33,1,255,24,2,0,255,148,35,0,255,253,71,0,255,243,68,0, +255,240,72,0,255,236,63,0,255,224,41,0,255,190,23,0,255,215,34,0,255,219,42,2, +255,217,40,4,255,209,29,4,255,203,23,4,255,202,25,6,255,202,33,9,255,120,19,4, +255,130,28,7,255,210,64,23,255,222,81,32,255,226,96,42,255,231,106,48,255,132, +50,16,99,120,42,13,0,100,36,11,0,91,34,11,0,92,33,10,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,95,62,37,1,69, +48,29,125,128,48,12,234,252,80,0,255,252,90,0,255,252,93,0,255,253,94,0,255, +253,92,0,255,255,88,0,255,250,80,0,255,230,66,0,255,247,66,0,255,243,59,0,255, +239,61,0,255,237,67,0,255,233,60,0,255,222,38,0,255,188,23,1,255,213,33,0,255, +217,41,2,255,214,36,3,255,207,26,3,255,201,21,4,255,201,25,6,255,205,34,9,255, +214,45,14,255,219,57,20,255,217,68,25,255,221,82,33,255,227,98,42,255,237,113, +51,255,137,59,23,217,104,40,13,18,124,50,17,0,127,50,18,0,121,61,29,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,104,73,45,10,105,73,46,80, +94,64,39,193,88,51,24,164,210,66,2,91,252,88,4,255,251,92,1,255,252,87,0,255, +251,82,0,255,250,79,0,255,249,76,0,255,249,72,0,255,250,67,0,255,243,57,0,255, +238,52,0,255,236,56,0,255,234,63,0,255,231,56,0,255,220,36,0,255,186,23,1,255, +210,32,1,255,216,39,2,255,211,32,3,255,204,23,3,255,200,20,4,255,201,26,6,255, +204,34,10,255,207,44,14,255,211,55,19,255,217,68,25,255,222,83,33,255,227,100, +44,255,241,118,54,255,160,71,29,251,58,36,18,187,86,53,30,7,100,67,41,0,105,76, +48,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,62,31,14,8,73,40,20,51,86,54,30,137,95,63,37,168,102,70,42,213,98,66, +39,254,73,43,22,170,19,8,2,46,130,31,1,145,255,123,40,255,250,94,7,255,249,77, +0,255,247,72,0,255,246,68,0,255,245,65,0,255,243,60,0,255,241,55,0,255,238,50, +0,255,234,48,0,255,233,51,0,255,231,55,0,255,227,48,0,255,217,31,0,255,184,23, +1,255,208,30,1,255,214,36,3,255,209,28,3,255,202,19,3,255,200,20,4,255,202,27, +7,255,205,35,10,255,208,45,14,255,212,57,20,255,217,70,27,255,223,86,35,255, +229,103,45,255,242,121,56,255,172,72,26,202,50,27,12,209,91,58,33,179,100,68,42, +5,106,75,47,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,55,27,11,73,50,23,9,150,57,28,12,196,51,26,11,175,40,18,6,134,39,18,6,155, +26,10,3,129,10,2,0,90,24,11,3,57,182,71,22,121,251,116,42,255,246,86,9,255,244, +65,0,255,241,59,0,255,239,55,0,255,238,53,0,255,237,50,0,255,236,48,0,255,233, +45,0,255,230,42,0,255,228,42,0,255,225,42,0,255,222,37,0,255,213,27,0,255,183, +22,1,255,206,28,1,255,212,33,3,255,206,25,3,255,200,18,3,255,200,21,5,255,203, +29,7,255,206,38,11,255,209,47,15,255,214,60,21,255,218,74,28,255,224,90,37,255, +230,107,48,255,244,125,59,255,174,73,26,210,7,1,0,104,75,46,23,222,104,72,44, +195,106,75,47,53,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,49,22,9,9,15,3,0,8,26,9,3,6,28,10,3,2,24,8,2,35,22,7,2,50,31,12,4,37, +28,15,6,7,255,254,254,0,251,131,67,88,236,85,24,255,239,68,4,255,236,53,0,255, +233,48,0,255,233,46,0,255,233,45,0,255,232,44,0,255,231,43,0,255,229,40,0,255, +226,38,0,255,223,35,0,255,221,32,0,255,217,29,0,255,209,23,0,255,180,21,1,255, +203,25,1,255,210,30,4,255,204,22,4,255,199,18,4,255,200,24,6,255,203,31,8,255, +207,40,12,255,210,50,17,255,214,63,22,255,220,77,30,255,226,93,39,255,232,111, +50,255,247,129,61,255,162,68,24,211,0,0,0,116,17,6,1,116,82,50,27,223,104,72, +45,255,100,68,41,128,90,57,32,61,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,233,69,17,71,227,61,7,255,230,51,1, +255,227,39,0,255,227,39,0,255,228,41,0,255,228,40,0,255,227,40,0,255,226,38,0, +255,224,36,0,255,221,33,0,255,219,30,0,255,216,27,0,255,213,25,0,255,206,20,0, +255,178,19,2,255,200,23,2,255,208,27,5,255,203,22,5,255,202,22,5,255,207,28,7, +255,207,35,10,255,207,44,14,255,212,55,19,255,216,68,24,255,221,82,33,255,227, +98,42,255,233,116,54,255,247,132,62,255,138,53,18,200,0,0,0,118,0,0,0,96,12,2, +0,101,49,25,10,151,65,37,18,154,75,44,22,196,75,43,22,178,64,33,15,43,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,214,26,0,33,220,43,0,246, +221,43,0,255,220,32,0,255,222,35,0,255,223,35,0,255,223,35,0,255,222,34,0,255, +221,32,0,255,219,31,0,255,217,28,0,255,215,26,0,255,211,24,0,255,210,21,0,255, +203,17,0,255,174,16,1,255,196,19,2,255,205,25,6,255,208,27,7,255,200,25,6,255, +179,24,6,255,199,36,10,255,210,49,16,255,214,59,21,255,218,73,27,255,224,88,36, +255,230,104,46,255,236,122,57,255,243,129,60,255,103,32,9,186,0,0,0,110,0,0,0, +64,17,5,1,39,12,2,0,79,7,1,0,88,21,6,1,78,33,12,4,148,42,18,6,155,58,28,12,111, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,210,26,0,1,214,35,0,202,218,42, +1,255,216,30,0,255,217,30,0,255,217,30,0,255,221,29,0,255,224,29,0,255,222,28, +0,255,215,26,0,255,213,24,0,255,210,22,0,255,208,20,0,255,206,18,0,255,199,14, +0,255,169,13,1,255,191,15,3,255,207,25,7,255,191,26,7,255,76,6,1,255,10,2,0, +255,128,28,8,255,218,55,19,255,216,65,24,255,221,79,31,255,226,95,40,255,233, +112,51,255,240,129,62,255,235,118,52,255,75,17,3,170,0,0,0,97,0,0,0,45,4,0,0,2, +36,16,5,1,42,19,7,8,34,15,5,3,255,254,254,0,21,5,1,2,46,21,8,12,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,212,29,1,157,215,38,1,255,211, +28,0,255,212,26,0,255,216,26,0,255,192,26,1,255,130,25,4,255,161,21,1,255,213, +22,0,255,209,21,0,255,206,19,0,255,203,17,0,255,202,15,1,255,196,12,1,255,165, +10,1,255,188,14,3,255,210,26,7,255,118,13,2,255,0,3,0,255,51,22,8,255,124,40, +16,255,218,60,21,255,218,72,27,255,223,86,35,255,229,102,45,255,235,119,56,255, +245,136,66,255,208,94,37,244,39,3,0,150,4,0,0,84,0,0,0,32,4,0,0,1,22,7,1,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,171,21,2,80,212,33,2,255,208,26, +1,255,208,21,0,255,206,23,1,255,104,32,11,255,46,25,10,255,29,15,5,255,142,14, +1,255,210,18,0,255,202,16,1,255,200,14,1,255,199,13,2,255,194,12,1,255,163,9, +0,255,188,16,3,255,209,26,7,255,130,18,4,255,40,21,7,255,90,44,21,255,153,59, +27,255,221,66,24,255,221,80,32,255,226,94,40,255,232,110,50,255,238,128,62,255, +249,135,64,255,149,53,17,217,4,0,0,129,7,0,0,70,0,0,0,21,12,3,0,0,15,4,0,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,109,13,2,8,192,22,2,224,204,21, +1,255,203,18,1,255,200,20,1,255,100,32,12,255,57,27,10,255,26,16,5,255,82,10, +2,255,205,15,1,255,199,13,2,255,197,13,2,255,197,14,3,255,194,14,2,255,162,10, +1,255,191,20,5,255,205,30,8,255,192,35,10,255,116,39,16,255,134,59,29,255,199, +67,27,255,221,75,29,255,224,89,37,255,230,104,46,255,236,120,56,255,242,136,67, +255,236,119,52,254,86,21,5,184,7,0,0,108,4,0,0,53,0,0,0,10,4,0,0,0,0,0,0,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,141,11,1,133,197, +16,2,255,196,17,2,255,202,16,1,255,170,20,4,255,94,24,8,255,88,16,4,255,157,12, +2,255,200,14,2,255,196,15,3,255,197,17,3,255,199,20,4,255,193,18,3,255,159,10, +1,255,192,25,6,255,204,36,10,255,210,44,14,255,211,52,18,255,213,62,22,255, +220,72,27,255,222,85,34,255,228,99,42,255,233,114,53,255,238,129,62,255,249,137, +65,255,180,77,28,232,19,0,0,146,19,2,0,84,4,0,0,33,4,0,0,2,4,0,0,0,4,0,0,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,102,7,0,37,170,13, +2,240,196,16,3,255,194,16,3,255,199,15,3,255,196,15,3,255,200,16,3,255,202,16, +3,255,197,18,4,255,199,20,4,255,200,22,5,255,201,26,7,255,192,21,5,255,155,10, +1,255,192,28,7,255,207,43,13,255,210,52,17,255,214,61,22,255,218,70,27,255, +221,82,33,255,227,95,40,255,232,109,49,255,236,124,59,255,242,132,63,255,235, +115,49,254,87,23,6,187,15,0,0,115,22,4,0,58,7,0,0,14,4,0,0,0,4,0,0,0,4,0,0,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,94,6,0,0,103, +7,1,139,191,18,4,255,194,20,4,255,196,20,4,255,198,21,5,255,198,22,5,255,199, +23,5,255,200,24,6,255,201,26,6,255,202,29,8,255,204,32,9,255,193,25,6,255,154, +12,1,255,195,35,9,255,210,52,17,255,214,62,22,255,217,71,27,255,221,81,33,255, +225,93,39,255,230,107,48,255,236,120,56,255,239,129,61,255,246,122,53,255,151, +54,18,220,12,0,0,139,26,6,1,82,29,6,1,30,4,0,0,2,4,0,0,0,4,0,0,0,4,0,0,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,115,8,0,0,81,4,0, +36,124,12,2,204,199,24,6,255,195,25,6,255,198,27,7,255,200,28,7,255,200,30,8, +255,202,31,8,255,203,33,9,255,204,36,10,255,207,41,13,255,196,32,8,255,158,15,2, +255,200,42,13,255,214,61,22,255,218,73,27,255,221,82,33,255,225,93,40,255,230, +106,47,255,234,117,55,255,238,124,57,255,244,116,48,255,188,70,24,238,37,3,0, +162,17,1,0,106,40,11,2,52,28,3,0,9,10,2,0,0,12,3,0,0,12,3,0,0,12,3,0,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,112,7,1,0,110,7,1,0,49, +2,0,89,140,18,4,222,202,31,8,255,196,31,8,255,200,34,9,255,202,37,11,255,204, +39,11,255,205,42,13,255,207,46,14,255,209,51,17,255,197,38,10,255,157,15,2,255, +200,44,13,255,215,69,25,255,222,85,34,255,226,95,41,255,230,105,47,255,233,113, +51,255,234,112,48,255,239,101,37,255,199,66,20,243,57,8,1,174,7,0,0,121,29,8,1, +74,47,10,1,22,12,0,0,0,7,3,0,0,10,3,0,0,10,3,0,0,10,3,0,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,113,9,1,0,116,9,1,0,97,8,1,19, +31,2,0,126,145,23,5,223,203,37,10,255,200,38,11,255,200,41,13,255,204,46,14, +255,207,51,17,255,210,56,19,255,212,60,21,255,196,41,11,255,155,15,2,255,200,46, +12,255,217,77,30,255,225,95,40,255,227,100,42,255,229,101,42,255,232,98,37,255, +237,89,29,255,192,57,15,241,65,10,2,180,4,0,0,130,19,4,0,91,47,12,2,40,33,3,0,3, +7,4,0,0,10,4,0,0,10,4,0,0,10,4,0,0,10,4,0,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,114,11,2,0,114,11,2,0,118,12,2,0,81,7,1,40,12, +1,0,131,117,19,4,200,192,38,11,252,202,41,12,255,200,44,13,255,203,50,16,255, +207,58,20,255,210,62,22,255,193,39,11,255,154,17,2,255,204,50,13,255,217,74,26, +255,221,81,30,255,224,81,27,255,233,84,27,255,229,79,23,255,161,45,11,226,47,6, +1,171,7,0,0,132,15,2,0,99,42,12,2,52,34,5,0,9,0,1,0,0,10,4,0,0,10,4,0,0,10,4, +0,0,10,4,0,0,10,4,0,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,115,13,2,0,115,13,2,0,115,13,2,0,119,14,3,0,78,8,1,49,0,0,0,123,59,7, +1,165,145,25,6,222,186,36,9,252,202,43,11,255,203,46,13,255,205,51,14,255,187, +35,8,255,149,17,3,255,211,51,13,255,221,66,19,255,228,71,20,255,222,70,19,255, +184,55,14,238,99,22,5,197,22,1,0,154,10,0,0,128,15,1,0,100,39,11,1,55,29,6,0,12, +4,0,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,115,13,2,0,115,13,2,0,115, +13,2,0,115,13,2,0,116,16,3,0,77,10,1,42,10,0,0,112,0,0,0,137,61,8,1,169,120,21, +5,208,149,29,7,228,175,40,10,242,177,36,9,249,154,25,5,249,188,50,13,244,170, +50,14,232,144,39,10,220,91,19,4,195,29,2,0,162,10,0,0,137,7,0,0,118,17,3,0,93, +43,12,1,49,34,6,0,10,4,0,0,0,7,1,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2, +0,0,10,2,0,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +115,13,2,0,115,13,2,0,115,13,2,0,115,13,2,0,113,15,3,0,100,15,3,0,85,14,3,25,42, +5,0,90,0,0,0,127,0,0,0,136,12,0,0,143,31,3,0,154,47,7,1,162,53,8,1,163,37,4,0, +159,22,1,0,154,12,0,0,148,12,0,0,138,10,0,0,124,10,1,0,107,28,8,1,79,43,11,2,38, +37,6,0,6,12,1,0,0,7,2,0,0,7,1,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0, +10,2,0,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,115, +13,2,0,115,13,2,0,115,13,2,0,115,13,2,0,113,15,3,0,96,14,3,0,97,17,3,0,95,18,4, +2,68,12,2,40,40,6,1,86,12,1,0,112,0,0,0,120,0,0,0,123,0,0,0,123,0,0,0,123,4,0, +0,121,7,0,0,115,15,3,0,102,31,7,0,79,45,10,1,47,40,9,1,18,21,2,0,1,15,3,0,0, +15,3,0,0,7,2,0,0,7,1,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,115,13,2,0, +115,13,2,0,115,13,2,0,115,13,2,0,113,15,3,0,96,14,3,0,95,16,3,0,94,18,4,0,86,18, +4,0,83,15,3,0,75,12,3,18,64,12,3,43,50,13,3,61,49,14,3,69,43,12,2,69,33,7,1, +60,45,10,1,46,49,8,1,28,47,7,0,11,33,2,0,1,7,2,0,0,7,2,0,0,17,3,0,0,15,3,0,0,7, +2,0,0,7,1,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,115,13,2,0,115,13,2,0, +115,13,2,0,115,13,2,0,113,15,3,0,96,14,3,0,95,16,3,0,94,18,4,0,84,17,4,0,80,13, +3,0,83,7,2,0,90,12,5,0,100,34,18,0,141,89,53,0,103,47,22,0,21,3,0,1,28,3,0,0, +26,0,0,0,10,0,0,0,4,0,0,0,7,3,0,0,10,2,0,0,17,3,0,0,15,3,0,0,7,2,0,0,7,1,0,0, +10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,10,2,0,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255, +254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0, +255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254,254,0,255,254, +254,0}; + +static Fl_RGB_Image image_bug(idata_bug, 48, 48, 4, 0); + +#endif diff --git a/ede-bug-tools/ede-bug-report/Bugzilla.cpp b/ede-bug-tools/ede-bug-report/Bugzilla.cpp new file mode 100644 index 0000000..d9d54ce --- /dev/null +++ b/ede-bug-tools/ede-bug-report/Bugzilla.cpp @@ -0,0 +1,165 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#include +#include +#include +#include +#include + +#include "Bugzilla.h" + +EDELIB_NS_USING(String) + +/* must be static; don't ask me why */ +static struct xmlrpc_clientparms gparms; +static struct xmlrpc_curl_xportparms gparms_curl; + +struct BugzillaData { + xmlrpc_env xenv; + xmlrpc_client *xcli; + String url; +}; + +BugzillaData *bugzilla_new(const char *u) { + BugzillaData *data = new BugzillaData; + + xmlrpc_env_init(&data->xenv); + xmlrpc_client_setup_global_const(&data->xenv); + data->url = u; + + /* + * to allow https connections; curl by default refuse connections without valid certificate + * (at least docs says that ;)) + */ + gparms_curl.no_ssl_verifypeer = 1; + gparms_curl.no_ssl_verifyhost = 1; + + /* only curl transport is supported */ + gparms.transport = "curl"; + gparms.transportparmsP = &gparms_curl; + + xmlrpc_client_create(&data->xenv, XMLRPC_CLIENT_NO_FLAGS, "ede-bug-report", "0.1", &gparms, sizeof(gparms), &data->xcli); + if(data->xenv.fault_occurred) { + E_WARNING(E_STRLOC ": Unable to init xmlrpc client data (%s)\n", data->xenv.fault_string); + delete data; + data = NULL; + } + + return data; +} + +void bugzilla_free(BugzillaData *data) { + if(data == NULL) + return; + + xmlrpc_client_destroy(data->xcli); + xmlrpc_env_clean(&data->xenv); + + delete data; +} + +char *bugzilla_get_version(BugzillaData *data) { + E_ASSERT(data != NULL); + + xmlrpc_value *result; + xmlrpc_client_call2f(&data->xenv, data->xcli, data->url.c_str(), "Bugzilla.version", &result, "()"); + + if(data->xenv.fault_occurred) { + E_WARNING(E_STRLOC ": Unable to call xmlrpc function (%s)\n", data->xenv.fault_string); + return ""; + } + + /* this value will be malloc()-ated by xmlrpc_decompose_value() and should be freeed by user */ + char *ret; + + xmlrpc_decompose_value(&data->xenv, result, "{s:s,*}", "version", &ret); + xmlrpc_DECREF(result); + + return ret; +} + +int bugzilla_login(BugzillaData *data, const char *user, const char *passwd) { + E_ASSERT(data != NULL); + + xmlrpc_value *result; + int remember = 0; /* remember login data */ + int id = -1; /* bugzilla user id */ + + xmlrpc_client_call2f(&data->xenv, data->xcli, data->url.c_str(), "User.login", &result, + "({s:s,s:s,s:b})", + "login", user, + "password", passwd, + "remember", remember); + + if(data->xenv.fault_occurred) { + E_WARNING(E_STRLOC ": Unable to perform login function (%s)\n", data->xenv.fault_string); + return id; + } + + xmlrpc_decompose_value(&data->xenv, result, "{s:i,*}", "id", &id); + xmlrpc_DECREF(result); + + return id; +} + +void bugzilla_logout(BugzillaData *data) { + E_ASSERT(data != NULL); + + xmlrpc_value *result; + xmlrpc_client_call2f(&data->xenv, data->xcli, data->url.c_str(), "User.logout", &result, "()"); + + if(data->xenv.fault_occurred) { + E_WARNING(E_STRLOC ": Unable to call xmlrpc function (%s)\n", data->xenv.fault_string); + return; + } + + xmlrpc_DECREF(result); +} + +int bugzilla_submit_bug(BugzillaData *data, const char *product, + const char *component, + const char *summary, + const char *version, + const char *description, + const char *op_sys, + const char *platform, + const char *priority, + const char *severity) +{ + E_ASSERT(data != NULL); + + int bug_id = -1; + xmlrpc_value *result; + + xmlrpc_client_call2f(&data->xenv, data->xcli, data->url.c_str(), "Bug.create", &result, + "({s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s})", + "product", product, + "component", component, + "summary", summary, + "version", version, + "description", description, + "op_sys", op_sys, + "platform", platform, + "priority", priority, + "severity", severity); + + if(data->xenv.fault_occurred) { + E_WARNING(E_STRLOC ": Unable to perform submit function (%s)\n", data->xenv.fault_string); + return bug_id; + } + + xmlrpc_decompose_value(&data->xenv, result, "{s:i,*}", "id", &bug_id); + xmlrpc_DECREF(result); + + return bug_id; +} diff --git a/ede-bug-tools/ede-bug-report/Bugzilla.h b/ede-bug-tools/ede-bug-report/Bugzilla.h new file mode 100644 index 0000000..28e1183 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/Bugzilla.h @@ -0,0 +1,38 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#ifndef __BUGZILLA_H__ +#define __BUGZILLA_H__ + +struct BugzillaData; + +BugzillaData *bugzilla_new(const char *url); +void bugzilla_free(BugzillaData *data); + +/* return bugzilla version or empty string if fails; returned value must be free()-ed */ +char *bugzilla_get_version(BugzillaData *data); + +/* return user id or -1 if fails */ +int bugzilla_login(BugzillaData *data, const char *user, const char *passwd); +void bugzilla_logout(BugzillaData *data); + +/* return bug id or -1 if fails */ +int bugzilla_submit_bug(BugzillaData *data, const char *product, + const char *component, + const char *summary, + const char *version, + const char *description, + const char *op_sys, + const char *platform, + const char *priority, + const char *severity); +#endif diff --git a/ede-bug-tools/ede-bug-report/BugzillaSender.cpp b/ede-bug-tools/ede-bug-report/BugzillaSender.cpp new file mode 100644 index 0000000..ecf65c3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/BugzillaSender.cpp @@ -0,0 +1,301 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#include +#include +#include +#include + +/* used from local xmlrpc-c source */ +#include + +#include +#include +#include + +#include +#include +#include + +#include "PulseProgress.h" +#include "BugzillaSender.h" +#include "Bugzilla.h" + +#define EDE_BUGZILLA_XMLRPC_URL "http://bugs.equinox-project.org/xmlrpc.cgi" + +/* must match to existing user */ +#define EDE_BUGZILLA_USER "ede-bugs@lists.sourceforge.net" +#define EDE_BUGZILLA_PASS "edebugs2709" + +#define PROGRESS_STEP_REFRESH 0.06 + +/* message length without '\n' */ +#define REPORT_STR_LEN 1024 + +EDELIB_NS_USING(alert) +EDELIB_NS_USING(message) +EDELIB_NS_USING(String) + +/* for easier passing it to the thread */ +struct BugContent { + const char *bug_title; + const char *bug_content; +}; + +static Fl_Double_Window *win; +static PulseProgress *progress; +static BugzillaData *bdata; +static bool data_submitted; + +/* we use only one additional thread */ +static int report_pipe[2]; +static pthread_mutex_t runner_mutex; + +/* to prevent sending data; shared between threads */ +static bool cancel_sending; + +static void write_string(int fd, const char *str) { + int len = strlen(str); + + if(len > REPORT_STR_LEN) + len = REPORT_STR_LEN; + + ::write(fd, str, len); + ::write(fd, "\n", 1); +} + +/* these are messages prepended with 'FAILED' so we knows how error was emited */ +static void write_string_fail(int fd, const char *str) { + int len = strlen(str); + + if(len > REPORT_STR_LEN) { + /* our max message size sans 'FAILED' header */ + len = REPORT_STR_LEN - 6; + } + + ::write(fd, "FAILED", 6); + ::write(fd, str, len); + ::write(fd, "\n", 1); +} + +static int read_string(int fd, String& ret) { + char c; + char buf[REPORT_STR_LEN]; + int i, nc; + + memset(buf, 0, sizeof(buf)); + + i = 0; + nc = ::read(fd, &c, 1); + while(nc > 0 && c != '\n' && i < REPORT_STR_LEN) { + buf[i] = c; + i = i + nc; + nc = ::read(fd, &c, 1); + } + + buf[i] = '\0'; + + ret = buf; + return i; +} + +static void cancel_cb(Fl_Widget*, void*) { + /* + * XXX: we must not use win->hide() here, mostly due sucky xmlrpc-c design. When window + * is going to be closed, but we still have pending RPC connections, we will get assertion from + * xmlrpc-c. To prevent that, we will change cancel_state and hope thread will catch it before + * bugzilla_submit_bug() is called. If it was called, we can't do anything about it, because data + * is already send to Bugzilla so we can only log out from it. + * + * Alternative (and crude) solution would be to comment assertion check xmlrpc_curl_transport.c (977) + * and leave cleaning stuff to the kernel. + */ + pthread_mutex_lock(&runner_mutex); + cancel_sending = true; + pthread_mutex_unlock(&runner_mutex); +} + +static void progress_timeout(void*) { + progress->step(); + Fl::repeat_timeout(PROGRESS_STEP_REFRESH, progress_timeout); +} + +static void clear_timeouts(void) { + Fl::remove_timeout(progress_timeout); +} + +static void report_pipe_cb(int fd, void *) { + String s; + if(read_string(report_pipe[0], s) <= 0) + return; + + /* check if the message started with 'FAILED' and see it as error */ + if(strncmp(s.c_str(), "FAILED", 6) == 0) { + win->hide(); + + const char *str = s.c_str(); + str += 6; /* do not show our header */ + + alert(str); + } + + progress->copy_label(s.c_str()); + + /* marked as completed successfully */ + if(s == "DONE") { + win->hide(); + message(_("The report was sent successfully. Thank you for your contribution")); + + /* the only case when data was submitted correctly */ + data_submitted = true; + return; + } + + /* marked as canceled */ + if(s == "CANCELED") + win->hide(); +} + +static void* thread_worker(void *d) { + int ret; + BugContent *data = (BugContent*)d; + bool should_cancel; + + ret = bugzilla_login(bdata, EDE_BUGZILLA_USER, EDE_BUGZILLA_PASS); + if(ret == -1) { + write_string_fail(report_pipe[1], _("Unable to properly login. Probably the host is temporarily down or your are not connected to the internet")); + goto done; + } + + /* wait some time if user decided to press 'Cancel' */ + sleep(1); + + pthread_mutex_lock(&runner_mutex); + should_cancel = cancel_sending; + pthread_mutex_unlock(&runner_mutex); + + if(should_cancel) { + write_string(report_pipe[1], "CANCELED"); + goto done; + } + + write_string(report_pipe[1], _("Submitting the report...")); + ret = bugzilla_submit_bug(bdata, + "ede", + "general", + data->bug_title, + "unspecified", + data->bug_content, + "All", + "All", + "P5", + "normal"); + + if(ret == -1) { + write_string_fail(report_pipe[1], _("Unable to properly submit the data. Please try again")); + goto done; + } + + write_string(report_pipe[1], _("Logging out...")); + bugzilla_logout(bdata); + + write_string(report_pipe[1], "DONE"); + +done: + delete data; + pthread_exit(NULL); + + /* shutup compiler */ + return NULL; +} + +static void perform_send(const char *title, const char *content) { + pthread_t thread; + + /* + * Must be allocated since this function could quit before thread was created + * of before thread could acceess the arguments. Freeing is done in that thread. + */ + BugContent *c = new BugContent; + c->bug_title = title; + c->bug_content = content; + + /* Create joinable thread. Some implementations prefer this explicitly was set. */ + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + int rc = pthread_create(&thread, &attr, thread_worker, (void*)c); + if(rc) { + alert(_("Unable to create additional thread")); + /* close everything */ + win->hide(); + } + + pthread_attr_destroy(&attr); +} + +bool bugzilla_send_with_progress(const char *title, const char *content) { + data_submitted = false; + cancel_sending = false; + + bdata = bugzilla_new(EDE_BUGZILLA_XMLRPC_URL); + if(!bdata) { + alert(_("Unable to initialize bugzilla interface!")); + return false; + } + + if(pipe(report_pipe) != 0) { + alert(_("Unable to initialize communication pipe")); + return false; + } + + /* prepare mutex */ + pthread_mutex_init(&runner_mutex, NULL); + + /* register our callback on pipe */ + Fl::add_fd(report_pipe[0], FL_READ, report_pipe_cb); + + win = new Fl_Double_Window(275, 90, _("Sending report data")); + win->begin(); + progress = new PulseProgress(10, 20, 255, 25, _("Sending report...")); + progress->selection_color((Fl_Color)137); + + Fl_Button *cancel = new Fl_Button(175, 55, 90, 25, _("&Cancel")); + cancel->callback(cancel_cb); + win->end(); + + win->set_modal(); + win->show(); + + progress->label(_("Preparing data...")); + Fl::add_timeout(PROGRESS_STEP_REFRESH, progress_timeout); + + perform_send(title, content); + + while(win->shown()) + Fl::wait(); + + /* clear pipe callback */ + Fl::remove_fd(report_pipe[0]); + clear_timeouts(); + + pthread_mutex_destroy(&runner_mutex); + + close(report_pipe[0]); + close(report_pipe[1]); + + bugzilla_free(bdata); + + /* true if we completed all stages */ + return data_submitted; +} diff --git a/ede-bug-tools/ede-bug-report/BugzillaSender.h b/ede-bug-tools/ede-bug-report/BugzillaSender.h new file mode 100644 index 0000000..4be75e3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/BugzillaSender.h @@ -0,0 +1,18 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#ifndef __BUGZILLASENDER_H__ +#define __BUGZILLASENDER_H__ + +bool bugzilla_send_with_progress(const char *title, const char *content); + +#endif diff --git a/ede-bug-tools/ede-bug-report/Jamfile b/ede-bug-tools/ede-bug-report/Jamfile new file mode 100644 index 0000000..f8b6227 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/Jamfile @@ -0,0 +1,120 @@ +# +# $Id$ +# +# Part of Equinox Desktop Environment (EDE). +# Copyright (c) 2009 EDE Authors. +# +# This program is licensed under terms of the +# GNU General Public License version 2 or newer. +# See COPYING for details. + +SubDir TOP ede-bug-report ; + +# needed paths +XMLRPC_C_SRC_PATH = [ FDirName $(TOP) ede-bug-report xmlrpc-c ] ; +XMLRPC_C_TOP = $(XMLRPC_C_SRC_PATH) ; +XMLRPC_C_LIB_DIR = [ FDirName $(XMLRPC_C_SRC_PATH) lib ] ; + +XMLRPC_C_FLAGS = + -I$(XMLRPC_C_SRC_PATH) + -I [ FDirName $(XMLRPC_C_SRC_PATH) include ] + -I [ FDirName $(XMLRPC_C_SRC_PATH) deps util include ] + -I [ FDirName $(XMLRPC_C_SRC_PATH) deps expat xmlparse ] + -I [ FDirName $(XMLRPC_C_SRC_PATH) deps expat xmltok ] ; + +# ede-bug-report related builds +SOURCE = Bugzilla.cpp BugzillaSender.cpp PulseProgress.cpp ede-bug-report.cpp ; +BINARY = ede-bug-report ; + +ObjectC++Flags $(SOURCE) : $(WNO_LONG_LONG) $(XMLRPC_C_FLAGS) $(CURL_CFLAGS) ; +EdeProgram $(BINARY) : $(SOURCE) ; +TranslationStrings locale : $(SOURCE) ; + +# link against xmlrpc-c libraries +LinkAgainst $(BINARY) : -L$(XMLRPC_C_LIB_DIR) + -lxmlrpc_local + -lcurl_transport_local + -lxmlrpc_util_local + -lxmlrpc_obj_local + -lxmlparse_local + -lxmltok_local + $(CURL_LIBS) + $(PTHREAD_CFLAGS) + $(PTHREAD_LIBS) ; + +# xmlrpc-c related builds +rule XmlrpcLibrary { + local lib = [ FDirName $(XMLRPC_C_LIB_DIR) $(<) ] ; + + # compile it with OPTIMFLAGS got from top Jamconfig + ObjectCcFlags $(>) : $(XMLRPC_C_FLAGS) $(OPTIMFLAGS) ; + StaticLibrary $(lib) : $(>) ; + + # make sure libraries are build first + LocalDepends $(BINARY) : $(lib:S=$(SUFLIB)) ; +} + +SEARCH_SOURCE += [ FDirName $(XMLRPC_C_SRC_PATH) src ] ; +SEARCH_SOURCE += [ FDirName $(XMLRPC_C_SRC_PATH) deps util ] ; +SEARCH_SOURCE += [ FDirName $(XMLRPC_C_SRC_PATH) deps libutil ] ; +SEARCH_SOURCE += [ FDirName $(XMLRPC_C_SRC_PATH) deps curl-transport ] ; +SEARCH_SOURCE += [ FDirName $(XMLRPC_C_SRC_PATH) deps expat xmlparse ] ; +SEARCH_SOURCE += [ FDirName $(XMLRPC_C_SRC_PATH) deps expat xmltok ] ; + +XMLRPC_C_SRC = + double.c + parse_value.c + resource.c + trace.c + version.c + xmlrpc_data.c + xmlrpc_datetime.c + xmlrpc_string.c + xmlrpc_array.c + xmlrpc_struct.c + xmlrpc_build.c + xmlrpc_decompose.c + xmlrpc_parse.c + xmlrpc_serialize.c + xmlrpc_base64.c + xmlrpc_authcookie.c + xmlrpc_client.c + xmlrpc_client_global.c + xmlrpc_expat.c + xmlrpc_server_info.c ; + +ObjectCcFlags $(XMLRPC_C_SRC) : -DMUST_BUILD_CURL_CLIENT ; + +CURL_TRANSPORT_SRC = + xmlrpc_curl_transport.c + curltransaction.c + curlmulti.c + lock_pthread.c ; + +UTIL_SRC = + casprintf.c + cmdline_parser.c + getoptx.c + string_parser.c + stripcaseeq.c ; + +LIBUTIL_SRC = + asprintf.c + error.c + make_printable.c + memblock.c + select.c + sleep.c + time.c + utf8.c ; + +XMLPARSE_SRC = xmlparse.c ; + +XMLTOK_SRC = xmltok.c xmlrole.c ; + +XmlrpcLibrary libxmlrpc_local : $(XMLRPC_C_SRC) ; +XmlrpcLibrary libxmlrpc_obj_local : $(UTIL_SRC) ; +XmlrpcLibrary libxmlrpc_util_local : $(LIBUTIL_SRC) ; +XmlrpcLibrary libxmlparse_local : $(XMLPARSE_SRC) ; +XmlrpcLibrary libxmltok_local : $(XMLTOK_SRC) ; +XmlrpcLibrary libcurl_transport_local : $(CURL_TRANSPORT_SRC) ; diff --git a/ede-bug-tools/ede-bug-report/PulseProgress.cpp b/ede-bug-tools/ede-bug-report/PulseProgress.cpp new file mode 100644 index 0000000..7dc09bb --- /dev/null +++ b/ede-bug-tools/ede-bug-report/PulseProgress.cpp @@ -0,0 +1,93 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#include +#include + +#include + +#include +#include "PulseProgress.h" + +PulseProgress::PulseProgress(int x, int y, int w, int h, const char *l) : + Fl_Widget(x, y, w, h, l), cprogress(0), blen(40), slen(5) +{ + box(FL_DOWN_BOX); + color(FL_BACKGROUND_COLOR, (Fl_Color)146); + /* show it at the beginning */ + cprogress += blen; +} + +void PulseProgress::draw(void) { + int bx, by, bw, bh; + int xoff, yoff, woff, hoff; + + bx = Fl::box_dx(box()); + by = Fl::box_dy(box()); + bw = Fl::box_dw(box()); + bh = Fl::box_dh(box()); + + xoff = x() + bx; + yoff = y() + by; + woff = w() - bw; + hoff = h() - bh; + + draw_box(box(), x(), y(), w(), h(), color()); + + fl_clip(xoff, yoff, woff, hoff); + Fl_Color c = fl_color(); + fl_color(color2()); + + if(cprogress >= woff) { + /* reverse it */ + cprogress = -cprogress; + } else if(cprogress == -blen) { + /* start again after reverse */ + cprogress = blen; + } + + if(cprogress > 0) + fl_rectf(xoff - blen + cprogress, yoff, blen, hoff); + else + fl_rectf(xoff - blen - cprogress, yoff, blen, hoff); + + fl_color(c); + fl_pop_clip(); + + draw_label(x() + bx, y() + by, w() - bw, h() - bh); +} + +void PulseProgress::step(void) { + cprogress += slen; + redraw(); +} + +#if 0 +static PulseProgress *pp; + +void cb(void *) { + pp->step(); + Fl::repeat_timeout(0.06, cb); +} + +int main() { + Fl_Double_Window *win = new Fl_Double_Window(300, 300); + win->begin(); + pp = new PulseProgress(10, 10, 200, 25, "Sending report..."); + win->end(); + + win->show(); + + Fl::add_timeout(0.06, cb); + return Fl::run(); +} +#endif diff --git a/ede-bug-tools/ede-bug-report/PulseProgress.h b/ede-bug-tools/ede-bug-report/PulseProgress.h new file mode 100644 index 0000000..8c6a1f7 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/PulseProgress.h @@ -0,0 +1,42 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#ifndef __PULSEPROGRESS_H__ +#define __PULSEPROGRESS_H__ + +#include + +class PulseProgress : public Fl_Widget { +private: + int cprogress; /* current progress */ + int blen; /* bar length */ + int slen; /* step length */ + +protected: + void draw(void); + +public: + PulseProgress(int x, int y, int w, int h, const char *l = 0); + + void bar_len(int l) { blen = l; } + int bar_len(void) { return blen; } + + void step_len(int l) { slen = l; } + int step_len(void) { return slen; } + + void step(void); + + void restart(void) { cprogress = 0; } +}; + +#endif + diff --git a/ede-bug-tools/ede-bug-report/asynch/Bugzilla.cpp b/ede-bug-tools/ede-bug-report/asynch/Bugzilla.cpp new file mode 100644 index 0000000..37c12d7 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/asynch/Bugzilla.cpp @@ -0,0 +1,208 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#include +#include +#include +#include +#include + +#include "Bugzilla.h" + +EDELIB_NS_USING(String) + +#define CLIENT_NAME "ede-bug-report" +#define CLIENT_VERSION "0.1" + +/* must be static; don't ask me why */ +static struct xmlrpc_clientparms gparms; + +struct BugzillaData { + xmlrpc_env xenv; + xmlrpc_client *xcli; + String url; + + IdResponseCallback id_response_cb; + VersionResponseCallback version_response_cb; + void *cb_data; +}; + +static void _logout_response_handler(const char *url, const char *method, + xmlrpc_value *val, void *user_data, xmlrpc_env *faultp, xmlrpc_value *result) +{ + /* do nothing */ +} + +static void _version_response_handler(const char *url, const char *method, + xmlrpc_value *val, void *user_data, xmlrpc_env *faultp, xmlrpc_value *result) +{ + BugzillaData *data = (BugzillaData *)user_data; + + if(faultp->fault_occurred) { + if(data->version_response_cb) { + /* do callback with error */ + (*data->version_response_cb)(NULL, data->cb_data, faultp->fault_occurred, faultp->fault_string); + } + return; + } + + char *tmp; + xmlrpc_decompose_value(&data->xenv, result, "{s:s,*}", "version", &tmp); + + if(data->version_response_cb) { + /* do callback with values */ + (*data->version_response_cb)(tmp, data->cb_data, faultp->fault_occurred, faultp->fault_string); + } + + /* xmlrpc_decompose_value() allocates returned string value */ + free(tmp); +} + +static void _id_response_handler(const char *url, const char *method, + xmlrpc_value *val, void *user_data, xmlrpc_env *faultp, xmlrpc_value *result) +{ + BugzillaData *data = (BugzillaData *)user_data; + + if(faultp->fault_occurred) { + if(data->id_response_cb) { + /* do callback with error */ + (*data->id_response_cb)(-1, data->cb_data, faultp->fault_occurred, faultp->fault_string); + } + return; + } + + int id; + xmlrpc_decompose_value(&data->xenv, result, "{s:i,*}", "id", &id); + + if(data->id_response_cb) { + /* do callback with values */ + (*data->id_response_cb)(id, data->cb_data, faultp->fault_occurred, faultp->fault_string); + } +} + +BugzillaData *bugzilla_new(const char *u) { + BugzillaData *data = new BugzillaData; + + xmlrpc_env_init(&data->xenv); + xmlrpc_client_setup_global_const(&data->xenv); + data->url = u; + + /* only cURL transport is supported */ + gparms.transport = "curl"; + + xmlrpc_client_create(&data->xenv, XMLRPC_CLIENT_NO_FLAGS, CLIENT_NAME, CLIENT_VERSION, + &gparms, sizeof(gparms), &data->xcli); + + if(data->xenv.fault_occurred) { + E_WARNING(E_STRLOC ": Unable to init xmlrpc client data (%s)\n", data->xenv.fault_string); + delete data; + data = NULL; + } + + /* nullify callback stuff */ + data->id_response_cb = NULL; + data->version_response_cb = NULL; + data->cb_data = NULL; + + return data; +} + +void bugzilla_free(BugzillaData *data) { + if(data == NULL) + return; + + xmlrpc_client_destroy(data->xcli); + xmlrpc_env_clean(&data->xenv); + + delete data; +} + +void bugzilla_set_id_response_callback(BugzillaData *data, IdResponseCallback cb) { + E_ASSERT(data != NULL); + data->id_response_cb = cb; +} + +void bugzilla_set_version_response_callback(BugzillaData *data, VersionResponseCallback cb) { + E_ASSERT(data != NULL); + data->version_response_cb = cb; +} + +void bugzilla_set_callback_data(BugzillaData *data, void *param) { + E_ASSERT(data != NULL); + data->cb_data = param; +} + +void bugzilla_event_loop_finish_timeout(BugzillaData *data, unsigned long ms) { + E_ASSERT(data != NULL); + xmlrpc_client_event_loop_finish_timeout(data->xcli, ms); +} + +void bugzilla_event_loop_finish(BugzillaData *data) { + E_ASSERT(data != NULL); + xmlrpc_client_event_loop_finish(data->xcli); +} + +void bugzilla_get_version(BugzillaData *data) { + E_ASSERT(data != NULL); + + xmlrpc_client_start_rpcf(&data->xenv, data->xcli, data->url.c_str(), + "Bugzilla.version", + _version_response_handler, data, "()"); +} + +void bugzilla_login(BugzillaData *data, const char *user, const char *passwd) { + E_ASSERT(data != NULL); + + const int remember = 0; /* remember login data */ + + xmlrpc_client_start_rpcf(&data->xenv, data->xcli, data->url.c_str(), + "User.login", + _id_response_handler, data, + "({s:s,s:s,s:b})", + "login", user, + "password", passwd, + "remember", remember); +} + +void bugzilla_logout(BugzillaData *data) { + E_ASSERT(data != NULL); + + xmlrpc_client_start_rpcf(&data->xenv, data->xcli, data->url.c_str(), + "User.logout", _logout_response_handler, NULL, "()"); +} + +void bugzilla_submit_bug(BugzillaData *data, const char *product, + const char *component, + const char *summary, + const char *version, + const char *description, + const char *op_sys, + const char *platform, + const char *priority, + const char *severity) +{ + E_ASSERT(data != NULL); + + xmlrpc_client_start_rpcf(&data->xenv, data->xcli, data->url.c_str(), + "Bug.create", + _id_response_handler, data, + "({s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s})", + "product", product, + "component", component, + "summary", summary, + "version", version, + "description", description, + "op_sys", op_sys, + "platform", platform, + "priority", priority, + "severity", severity); +} diff --git a/ede-bug-tools/ede-bug-report/asynch/Bugzilla.h b/ede-bug-tools/ede-bug-report/asynch/Bugzilla.h new file mode 100644 index 0000000..c0c1611 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/asynch/Bugzilla.h @@ -0,0 +1,70 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#ifndef __BUGZILLA_H__ +#define __BUGZILLA_H__ + +/* + * This is asynchronous Bugzilla interface (xmlrpc calls to Bugzilla installation). This means + * that all calls will be processed without blocking and all results will be reported via callbacks. + * + * To keep things simple, we have two type of callbacks, IdResponseCallback and VersionResponseCallback. + * VersionResponseCallback will be called when request is sent via bugzilla_get_version() and + * IdResponseCallback when bugzilla_login() and bugzilla_submit_bug(). In first case, we will get + * user ID or -1 (and set errnum > 0 and err != NULL) if user does not exists or something was wrong + * with the connection. bugzilla_submit_bug() behaves the same, except it returns bug ID if bug was + * created successfully. + * + * Callbacks are sev bia bugzilla_set_id_response_callback() and bugzilla_set_version_response_callback() + * and data passed to the callback is done via bugzilla_set_callback_data(). + * + * The reason why IdResponseCallback was used for both bugzilla_login() and bugzilla_submit_bug() + * is because both mark returned values as 'id' and to not clutter things with callbacks types such + * as BugIdResponseCallback or LoginIdResponse-bla-bla... you get it :) + */ + +struct BugzillaData; + +typedef void (*IdResponseCallback)(int, void *data, int errnum, const char *err); +typedef void (*VersionResponseCallback)(const char *, void *data, int errnum, const char *err); + +BugzillaData *bugzilla_new(const char *url); +void bugzilla_free(BugzillaData *data); + +/* callbacks when response arrives */ +void bugzilla_set_id_response_callback(BugzillaData *data, IdResponseCallback cb); +void bugzilla_set_version_response_callback(BugzillaData *data, VersionResponseCallback cb); + +/* data sent to callbacks */ +void bugzilla_set_callback_data(BugzillaData *data, void *param); + +void bugzilla_event_loop_finish_timeout(BugzillaData *data, unsigned long ms); +void bugzilla_event_loop_finish(BugzillaData *data); + +/* get bugzilla version; VersionResponseCallback will be called */ +void bugzilla_get_version(BugzillaData *data); + +/* login to bugzilla instance; IdResponseCallback will be called */ +void bugzilla_login(BugzillaData *data, const char *user, const char *passwd); +void bugzilla_logout(BugzillaData *data); + +/* submit bug (must be logged); retuned bug id will be reported via IdResponseCallback */ +void bugzilla_submit_bug(BugzillaData *data, const char *product, + const char *component, + const char *summary, + const char *version, + const char *description, + const char *op_sys, + const char *platform, + const char *priority, + const char *severity); +#endif diff --git a/ede-bug-tools/ede-bug-report/asynch/BugzillaSender.cpp b/ede-bug-tools/ede-bug-report/asynch/BugzillaSender.cpp new file mode 100644 index 0000000..f6676db --- /dev/null +++ b/ede-bug-tools/ede-bug-report/asynch/BugzillaSender.cpp @@ -0,0 +1,177 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#include + +#include +#include +#include + +#include +#include + +#include "PulseProgress.h" +#include "BugzillaSender.h" +#include "Bugzilla.h" + +#define EDE_BUGZILLA_URL "http://bugs.equinox-project.org" +#define EDE_BUGZILLA_XMLRPC_URL "http://bugs.equinox-project.org/xmlrpc.cgi" + +/* must match to existing user */ +#define EDE_BUGZILLA_USER "ede-bugs@lists.sourceforge.net" +#define EDE_BUGZILLA_PASS "edebugs2709" + +#define PROGRESS_STEP_REFRESH 0.06 + +EDELIB_NS_USING(alert) + +enum { + STATE_NEXT = 1, + STATE_LOGIN, + STATE_LOGOUT, + STATE_DONE +}; + +struct ResponseParams { + int working_state; + const char *bug_title; + const char *bug_content; +}; + +static Fl_Double_Window *win; +static PulseProgress *progress; +static BugzillaData *bdata; + +static void xmlrpc_request_timeout(void*) { + bugzilla_event_loop_finish_timeout(bdata, 20); + + /* repeat this function so all pending RPC requests are processed */ + Fl::repeat_timeout(0.5, xmlrpc_request_timeout); +} + +static void progress_timeout(void*) { + progress->step(); + Fl::repeat_timeout(PROGRESS_STEP_REFRESH, progress_timeout); +} + +static void clear_timeouts(void) { + Fl::remove_timeout(xmlrpc_request_timeout); + Fl::remove_timeout(progress_timeout); +} + +static void cancel_cb(Fl_Widget*, void*) { + win->hide(); +} + +static void _id_response_cb(int id, void *data, int errnum, const char *err) { + if(errnum) { + alert(_("Received bad response: (%i) : %s"), errnum, err); + /* close dialog */ + cancel_cb(0, 0); + return; + } + + ResponseParams *rparams = (ResponseParams*) data; + + if(rparams->working_state == STATE_LOGIN) { + progress->label("Done. Submitting the data..."); + printf("logged in as id: %i\n", id); + + /* must match EDE Bugzilla server options */ + bugzilla_submit_bug(bdata, + "ede", + "general", + rparams->bug_title, + "unspecified", + rparams->bug_content, + "All", + "All", + "P5", + "normal"); + + rparams->working_state += STATE_NEXT; + return; + } + + if(rparams->working_state == STATE_LOGOUT) { + progress->label("Data sent successfully :). Clearing..."); + puts("XXX"); + + bugzilla_logout(bdata); + rparams->working_state += STATE_NEXT; + return; + } +} + +bool bugzilla_send_with_progress(const char *title, const char *content) { + /* used to simplify passing multiple data to the response callback */ + ResponseParams rparams; + + /* + * we maintain state so knows what we done, since our Bugzilla interface + * supports only one callback for ID's + */ + rparams.working_state = STATE_LOGIN; + + rparams.bug_title = title; + rparams.bug_content = content; + + bdata = bugzilla_new(EDE_BUGZILLA_XMLRPC_URL); + if(!bdata) { + alert(_("Unable to initialize bugzilla interface!")); + return false; + } + + /* set callback and data */ + bugzilla_set_id_response_callback(bdata, _id_response_cb); + bugzilla_set_callback_data(bdata, &rparams); + + win = new Fl_Double_Window(275, 90, _("Sending report data")); + win->begin(); + progress = new PulseProgress(10, 20, 255, 25, _("Sending report...")); + progress->selection_color((Fl_Color)137); + + Fl_Button *cancel = new Fl_Button(175, 55, 90, 25, _("&Cancel")); + cancel->callback(cancel_cb); + win->end(); + + win->set_modal(); + win->show(); + + /* + * try to login; rest of the actions are done in _id_response_cb() due async stuff + * and since events are chained (you can't submit report until get logged in) + */ + progress->label("Logging in..."); + bugzilla_login(bdata, EDE_BUGZILLA_USER, EDE_BUGZILLA_PASS); + + /* timer for processing RPC requests */ + Fl::add_timeout(0.5, xmlrpc_request_timeout); + Fl::add_timeout(PROGRESS_STEP_REFRESH, progress_timeout); + + while(win->shown()) + Fl::wait(); + + /* + * make sure the timeout functions are removed because FLTK shares them between loops + * (or: as long as any loop is running, timeout callbacks will be triggered) + */ + clear_timeouts(); + + /* process all pending requests */ + bugzilla_event_loop_finish(bdata); + bugzilla_free(bdata); + bdata = NULL; + + /* true if we completed all stages */ + return (rparams.working_state == STATE_DONE); +} diff --git a/ede-bug-tools/ede-bug-report/asynch/BugzillaSender.h b/ede-bug-tools/ede-bug-report/asynch/BugzillaSender.h new file mode 100644 index 0000000..4be75e3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/asynch/BugzillaSender.h @@ -0,0 +1,18 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#ifndef __BUGZILLASENDER_H__ +#define __BUGZILLASENDER_H__ + +bool bugzilla_send_with_progress(const char *title, const char *content); + +#endif diff --git a/ede-bug-tools/ede-bug-report/ede-bug-report.cpp b/ede-bug-tools/ede-bug-report/ede-bug-report.cpp new file mode 100644 index 0000000..4bec0de --- /dev/null +++ b/ede-bug-tools/ede-bug-report/ede-bug-report.cpp @@ -0,0 +1,181 @@ +/* + * $Id$ + * + * ede-bug-report, a tool to report bugs on EDE bugzilla instance + * Part of Equinox Desktop Environment (EDE). + * Copyright (c) 2009 EDE Authors. + * + * This program is licensed under terms of the + * GNU General Public License version 2 or newer. + * See COPYING for details. + */ + +#ifndef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "BugzillaSender.h" + +#include "BugImage.h" +#include "icons/bug.xpm" + +EDELIB_NS_USING(String) +EDELIB_NS_USING(Regex) +EDELIB_NS_USING(alert) +EDELIB_NS_USING(message) +EDELIB_NS_USING(RX_CASELESS) + +static Fl_Input *bug_title_input; +static Fl_Input *email_input; +static Fl_Text_Buffer *text_buf; + +/* check if string has spaces */ +static bool empty_entry(const char *en) { + if(!en) + return true; + + for(const char *p = en; *p; p++) { + if(*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') + return false; + } + + return true; +} + +static bool valid_email(const char *e) { + Regex r; + + /* regex stolen from http://www.regular-expressions.info/email.html */ + if(!r.compile("\\b[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b", RX_CASELESS)) { + E_WARNING(E_STRLOC ": Unable to properly compile regex pattern"); + return false; + } + + return (r.match(e) > 0); +} + +static void close_cb(Fl_Widget*, void *w) { + edelib::Window *win = (edelib::Window *)w; + win->hide(); +} + +static void send_cb(Fl_Widget*, void *w) { + const char *txt; + String title, content; + + if(empty_entry(bug_title_input->value())) { + alert(_("Report title is missing")); + return; + } + + if(empty_entry(email_input->value())) { + alert(_("Email address is missing")); + return; + } + + txt = text_buf->text(); + if(empty_entry(txt)) { + alert(_("Detail problem description is missing")); + free((void *) txt); + return; + } + + if(!valid_email(email_input->value())) { + alert(_("Email address is invalid. Please use the valid email address")); + return; + } + + /* + * construct a subject header, so we knows it came from report tool + * BRT - Bug Report Tool + */ + title = "[BRT] "; + title += bug_title_input->value(); + + /* reserve space for our content */ + content.reserve(text_buf->length() + 128); + + /* construct content with some header data */ + content += "This issue was reported via EDE Bug Report Tool (BRT).\n\n"; + content += "Reporter:\n"; + content += email_input->value(); + content += "\n\n"; + content += "Detail description:\n"; + content += txt; + + free((void *) txt); + + if(bugzilla_send_with_progress(title.c_str(), content.c_str())) + close_cb(0, w); +} + +int main(int argc, char** argv) { + /* in case if debugger output was given */ + const char *gdb_output = NULL; + + if(argc == 3 && ((strcmp(argv[1], "--gdb-dump") == 0) || (strcmp(argv[1], "-g") == 0))) + gdb_output = argv[2]; + + edelib::Window *win = new edelib::Window(480, 365, _("EDE Bug Reporting Tool")); + win->begin(); + Fl_Box *image_box = new Fl_Box(10, 10, 60, 59); + image_box->image(image_bug); + + Fl_Box *title_box = new Fl_Box(80, 10, 390, 30, _("EDE Bug Reporting Tool")); + title_box->labelfont(1); + title_box->labelsize(14); + title_box->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + + Fl_Box *description_box = new Fl_Box(80, 45, 390, 95, _("To help us to improve the future EDE versions, please describe the problem with much details as possible.\n\nNote: valid email address is required, so developers could contact you for more informations if necessary.")); + description_box->align(133|FL_ALIGN_INSIDE); + + bug_title_input = new Fl_Input(10, 165, 225, 25, _("Short and descriptive title:")); + bug_title_input->align(FL_ALIGN_TOP_LEFT); + + email_input = new Fl_Input(240, 165, 230, 25, _("Your email address:")); + email_input->align(FL_ALIGN_TOP_LEFT); + + Fl_Text_Editor* te = new Fl_Text_Editor(10, 215, 460, 105, _("Detail description of the problem:")); + te->align(FL_ALIGN_TOP_LEFT); + /* wrap length of the text */ + te->wrap_mode(1, 80); + + text_buf = new Fl_Text_Buffer(); + te->buffer(text_buf); + + if(gdb_output) { + if(text_buf->appendfile(gdb_output) == 0) { + text_buf->insert(0, "\nCollected data:\n"); + text_buf->insert(0, "(please write additional comments here, removing this line)\n\n"); + } else + E_WARNING(E_STRLOC ": Unable to read '%s' as debugger output. Continuing...\n"); + } + + Fl_Button *send = new Fl_Button(285, 330, 90, 25, _("&Send")); + send->callback(send_cb, win); + + Fl_Button *close = new Fl_Button(380, 330, 90, 25, _("&Close")); + close->callback(close_cb, win); + + win->window_icon(bug_xpm); + /* win->show(argc, argv); */ + win->show(); + return Fl::run(); +} diff --git a/ede-bug-tools/ede-bug-report/fl/ede-bug-report.fl b/ede-bug-tools/ede-bug-report/fl/ede-bug-report.fl new file mode 100644 index 0000000..470eac5 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/fl/ede-bug-report.fl @@ -0,0 +1,45 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0108 +header_name {.h} +code_name {.cxx} +Function {} {open +} { + Fl_Window {} { + label {EDE Bug Reporting Tool} open + xywh {369 205 480 365} type Double visible + } { + Fl_Box {} {selected + image {../icons/bug.png} xywh {10 10 60 59} + } + Fl_Box {} { + label {EDE Bug Reporting Tool} + xywh {80 10 390 30} labelfont 1 labelsize 14 align 20 + } + Fl_Box {} { + label {To help us to improve the future EDE versions, please describe the problem with much details as possible. + +Note: valid email address is required, so developers could contact you for more informations if necessary.} + xywh {80 45 390 95} align 149 + } + Fl_Input {} { + label {Short and descriptive title:} + xywh {10 165 225 25} align 5 + } + Fl_Input {} { + label {Your email address:} + xywh {240 165 230 25} align 5 + } + Fl_Text_Editor {} { + label {Detail description of the problem:} + xywh {10 215 460 105} align 5 + } + Fl_Button {} { + label {&Send} + xywh {285 330 90 25} + } + Fl_Button {} { + label {&Cancel} + xywh {380 330 90 25} + } + } +} diff --git a/ede-bug-tools/ede-bug-report/fl/status-dialog.fl b/ede-bug-tools/ede-bug-report/fl/status-dialog.fl new file mode 100644 index 0000000..9f2393b --- /dev/null +++ b/ede-bug-tools/ede-bug-report/fl/status-dialog.fl @@ -0,0 +1,19 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0108 +header_name {.h} +code_name {.cxx} +Function {} {open +} { + Fl_Window {} {open + xywh {389 409 275 90} type Double visible + } { + Fl_Progress {} { + label {Sending report...} selected + xywh {10 20 255 25} selection_color 137 + } + Fl_Button {} { + label {&Cancel} + xywh {175 55 90 25} + } + } +} diff --git a/ede-bug-tools/ede-bug-report/icons/bug.png b/ede-bug-tools/ede-bug-report/icons/bug.png new file mode 100644 index 0000000..524bee4 Binary files /dev/null and b/ede-bug-tools/ede-bug-report/icons/bug.png differ diff --git a/ede-bug-tools/ede-bug-report/icons/bug.xpm b/ede-bug-tools/ede-bug-report/icons/bug.xpm new file mode 100644 index 0000000..58b6eaa --- /dev/null +++ b/ede-bug-tools/ede-bug-report/icons/bug.xpm @@ -0,0 +1,216 @@ +/* XPM */ +static char * bug_xpm[] = { +"22 22 191 2", +" c None", +". c #4C2C16", +"+ c #5D3C23", +"@ c #5E3D23", +"# c #41200E", +"$ c #59331B", +"% c #3C1E0D", +"& c #52311A", +"* c #59371F", +"= c #402310", +"- c #3C2313", +"; c #483220", +"> c #5F3A20", +", c #674D3A", +"' c #412B20", +") c #33170A", +"! c #3C1D0C", +"~ c #2C170B", +"{ c #36281C", +"] c #4E433C", +"^ c #4A3E35", +"/ c #593B21", +"( c #2D1909", +"_ c #CD3502", +": c #D97D3F", +"< c #D4CDBE", +"[ c #958577", +"} c #391E10", +"| c #230E05", +"1 c #17130C", +"2 c #2C2D25", +"3 c #835037", +"4 c #A43818", +"5 c #160802", +"6 c #593B1F", +"7 c #BA6D2B", +"8 c #FFBD3C", +"9 c #FB6B07", +"0 c #DD8D46", +"a c #D6C1B0", +"b c #574636", +"c c #0A0300", +"d c #140C07", +"e c #6D341E", +"f c #E34E24", +"g c #FD511E", +"h c #593720", +"i c #E3A968", +"j c #FFD582", +"k c #EB8D30", +"l c #F56600", +"m c #DB5600", +"n c #8F391D", +"o c #480701", +"p c #BB330E", +"q c #E83C16", +"r c #9A2209", +"s c #B95227", +"t c #E25F2E", +"u c #321A0E", +"v c #070401", +"w c #FF8F1A", +"x c #FFA434", +"y c #5D3014", +"z c #9C3201", +"A c #FF5F00", +"B c #F42600", +"C c #DD1500", +"D c #FC3704", +"E c #DA2106", +"F c #2C0000", +"G c #521E0A", +"H c #FF7030", +"I c #C02F00", +"J c #FF6900", +"K c #FF6D04", +"L c #9E3200", +"M c #BB2500", +"N c #F94B00", +"O c #E53700", +"P c #BD1600", +"Q c #DC2903", +"R c #CF1505", +"S c #A71607", +"T c #AE2E0F", +"U c #FE7635", +"V c #A1491D", +"W c #5D432B", +"X c #141513", +"Y c #A24608", +"Z c #FF6209", +"` c #F94500", +" . c #FF4300", +".. c #FD3500", +"+. c #F33D00", +"@. c #D92800", +"#. c #AD1101", +"$. c #D42003", +"%. c #C10E04", +"&. c #DC270C", +"*. c #E33F16", +"=. c #FD7B38", +"-. c #88401B", +";. c #F94206", +">. c #E82A00", +",. c #EA2D00", +"'. c #E32600", +"). c #E02400", +"!. c #D21300", +"~. c #B21602", +"{. c #E31C04", +"]. c #D81607", +"^. c #D12B0C", +"/. c #D44318", +"(. c #FF8B44", +"_. c #793516", +":. c #100B09", +"<. c #6D4B2F", +"[. c #DD2300", +"}. c #E01F00", +"|. c #EC2100", +"1. c #E81D00", +"2. c #DB1800", +"3. c #C51000", +"4. c #BF1603", +"5. c #C31305", +"6. c #861003", +"7. c #D2300F", +"8. c #E35321", +"9. c #FF9046", +"0. c #662D14", +"a. c #1D0D03", +"b. c #D71B00", +"c. c #CB1C02", +"d. c #581806", +"e. c #A71101", +"f. c #DD1000", +"g. c #B90301", +"h. c #BA0A00", +"i. c #710A03", +"j. c #39190B", +"k. c #D44117", +"l. c #F66F32", +"m. c #F8823D", +"n. c #41190B", +"o. c #B70D01", +"p. c #CA1503", +"q. c #431408", +"r. c #830A02", +"s. c #D60C02", +"t. c #B70C03", +"u. c #B00A01", +"v. c #C8280D", +"w. c #B63C18", +"x. c #E25725", +"y. c #FF8C44", +"z. c #BD5B27", +"A. c #C81304", +"B. c #D21404", +"C. c #CF1A07", +"D. c #B81304", +"E. c #9C0B02", +"F. c #E13E17", +"G. c #E25322", +"H. c #F67B3A", +"I. c #F27937", +"J. c #561E0A", +"K. c #7C1002", +"L. c #CB2108", +"M. c #D82A0C", +"N. c #DA3611", +"O. c #BF2A0E", +"P. c #A71102", +"Q. c #EB5F27", +"R. c #F57131", +"S. c #F26C2D", +"T. c #78270D", +"U. c #611104", +"V. c #AF240A", +"W. c #DF3D13", +"X. c #E33910", +"Y. c #D42909", +"Z. c #F25B21", +"`. c #CD4918", +" + c #661905", +".+ c #3B0600", +"++ c #5C1004", +"@+ c #650E03", +"#+ c #6B1203", +"$+ c #691B06", +"%+ c #2D0400", +" ", +" ", +" ", +" . + @ # ", +" $ % & * = - ; > ", +" - , ' ) ! ~ { ] ^ / ( ", +" _ : < [ } | 1 2 3 4 ", +" 5 6 7 8 9 0 a b c d e f g h ", +" i j k l m n o p q r s t u v ", +" w x y z A B C D E F G H ", +" I J K L M N O P Q R S T U V ", +" W X Y Z ` ...+.@.#.$.%.&.*.=.-. ", +" ;.>.,.'.).!.~.{.].^./.(._.:.<. ", +" [.}.|.1.2.3.4.5.6.7.8.9.0. a. ", +" b.c.d.e.f.g.h.i.j.k.l.m.n. ", +" o.p.q.r.s.t.u.v.w.x.y.z. ", +" A.B.R C.D.E.F.G.H.I.J. ", +" K.L.M.N.O.P.Q.R.S.T. ", +" U.V.W.X.Y.Z.`. + ", +" .+++@+#+$+%+ ", +" ", +" "}; diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/README b/ede-bug-tools/ede-bug-report/xmlrpc-c/README new file mode 100644 index 0000000..a963004 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/README @@ -0,0 +1,3 @@ +This directory contains customized xmlrpc-c (http://xmlrpc-c.sourceforge.net) +library suitable only for EDE usage. Besides that, some things are removed because +they are not used (abyss server and C++ wrapper). diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlmulti.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlmulti.c new file mode 100644 index 0000000..526a4db --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlmulti.c @@ -0,0 +1,311 @@ +/*============================================================================= + curlMulti +=============================================================================== + This is an extension to Curl's CURLM object. The extensions are: + + 1) It has a lock so multiple threads can use it simultaneously. + + 2) Its "select" file descriptor vectors are self-contained. CURLM + requires the user to maintain them separately. +=============================================================================*/ + +#include "xmlrpc_config.h" + +#include +#if !MSVCRT +#include +#endif + +#include +#include +#include +#include + +#include "mallocvar.h" +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/string_int.h" + +#include "curlversion.h" +#include "lock.h" +#include "lock_pthread.h" + +#include "curlmulti.h" + + + +static void +interpretCurlMultiError(const char ** const descriptionP, + CURLMcode const code) { + +#if HAVE_CURL_STRERROR + *descriptionP = strdup(curl_multi_strerror(code)); +#else + xmlrpc_asprintf(descriptionP, "Curl error code (CURLMcode) %d", code); +#endif +} + + + +struct curlMulti { + CURLM * curlMultiP; + lock * lockP; + /* Hold this lock while accessing or using *curlMultiP. You're + using the multi manager whenever you're calling a Curl + library multi manager function. + */ + /* The following file descriptor sets are an integral part of the + CURLM object; Our curlMulti_fdset() routine binds them to the + CURLM object, and said object expects us to use them in a very + specific way, including doing a select() on them. It is very, + very messy. + */ + fd_set readFdSet; + fd_set writeFdSet; + fd_set exceptFdSet; +}; + + + +curlMulti * +curlMulti_create(void) { + + curlMulti * retval; + curlMulti * curlMultiP; + + MALLOCVAR(curlMultiP); + + if (curlMultiP == NULL) + retval = NULL; + else { + curlMultiP->lockP = curlLock_create_pthread(); + + if (curlMultiP->lockP == NULL) + retval = NULL; + else { + curlMultiP->curlMultiP = curl_multi_init(); + if (curlMultiP->curlMultiP == NULL) + retval = NULL; + else + retval = curlMultiP; + + if (retval == NULL) + curlMultiP->lockP->destroy(curlMultiP->lockP); + } + if (retval == NULL) + free(curlMultiP); + } + return retval; +} + + + +void +curlMulti_destroy(curlMulti * const curlMultiP) { + + curl_multi_cleanup(curlMultiP->curlMultiP); + + curlMultiP->lockP->destroy(curlMultiP->lockP); + + free(curlMultiP); +} + + + +void +curlMulti_perform(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + bool * const immediateWorkToDoP, + int * const runningHandlesP) { +/*---------------------------------------------------------------------------- + Do whatever work is ready to be done under the control of multi + manager 'curlMultiP'. E.g. if HTTP response data has recently arrived + from the network, process it as an HTTP response. + + Iff this results in some work being finished from our point of view, + return *immediateWorkToDoP. (Caller can query the multi manager for + messages and find out what it is). + + Return as *runningHandlesP the number of Curl easy handles under the + multi manager's control that are still running -- yet to finish. +-----------------------------------------------------------------------------*/ + CURLMcode rc; + + curlMultiP->lockP->acquire(curlMultiP->lockP); + + rc = curl_multi_perform(curlMultiP->curlMultiP, runningHandlesP); + + curlMultiP->lockP->release(curlMultiP->lockP); + + if (rc == CURLM_CALL_MULTI_PERFORM) { + *immediateWorkToDoP = true; + } else { + *immediateWorkToDoP = false; + + if (rc != CURLM_OK) { + const char * reason; + interpretCurlMultiError(&reason, rc); + xmlrpc_faultf(envP, "Impossible failure of curl_multi_perform(): " + "%s", reason); + xmlrpc_strfree(reason); + } + } +} + + + +void +curlMulti_addHandle(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + CURL * const curlSessionP) { + + CURLMcode rc; + + curlMultiP->lockP->acquire(curlMultiP->lockP); + + rc = curl_multi_add_handle(curlMultiP->curlMultiP, curlSessionP); + + curlMultiP->lockP->release(curlMultiP->lockP); + + if (rc != CURLM_OK) { + const char * reason; + interpretCurlMultiError(&reason, rc); + xmlrpc_faultf(envP, "Could not add Curl session to the " + "curl multi manager. curl_multi_add_handle() " + "failed: %s", reason); + xmlrpc_strfree(reason); + } +} + + +void +curlMulti_removeHandle(curlMulti * const curlMultiP, + CURL * const curlSessionP) { + + curlMultiP->lockP->acquire(curlMultiP->lockP); + + curl_multi_remove_handle(curlMultiP->curlMultiP, curlSessionP); + + curlMultiP->lockP->release(curlMultiP->lockP); +} + + + +void +curlMulti_getMessage(curlMulti * const curlMultiP, + bool * const endOfMessagesP, + CURLMsg * const curlMsgP) { +/*---------------------------------------------------------------------------- + Get the next message from the queue of things the Curl multi manager + wants to say to us. + + Return the message as *curlMsgP. + + Iff there are no messages in the queue, return *endOfMessagesP == true. +-----------------------------------------------------------------------------*/ + int remainingMsgCount; + CURLMsg * privateCurlMsgP; + /* Note that this is a pointer into the multi manager's memory, + so we have to use it under lock. + */ + + curlMultiP->lockP->acquire(curlMultiP->lockP); + + privateCurlMsgP = curl_multi_info_read(curlMultiP->curlMultiP, + &remainingMsgCount); + + if (privateCurlMsgP == NULL) + *endOfMessagesP = true; + else { + *endOfMessagesP = false; + *curlMsgP = *privateCurlMsgP; + } + curlMultiP->lockP->release(curlMultiP->lockP); +} + + + +void +curlMulti_fdset(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + fd_set * const readFdSetP, + fd_set * const writeFdSetP, + fd_set * const exceptFdSetP, + int * const maxFdP) { +/*---------------------------------------------------------------------------- + Set the CURLM object's file descriptor sets to those in the + curlMulti object, update those file descriptor sets with the + current needs of the multi manager, and return the resulting values + of the file descriptor sets. + + This is a bizarre operation, but is necessary because of the nonmodular + way in which the Curl multi interface works with respect to waiting + for work with select(). +-----------------------------------------------------------------------------*/ + CURLMcode rc; + + curlMultiP->lockP->acquire(curlMultiP->lockP); + + /* curl_multi_fdset() doesn't _set_ the fdsets. It adds to existing + ones (so you can easily do a select() on other fds and Curl + fds at the same time). So we have to clear first: + */ + FD_ZERO(&curlMultiP->readFdSet); + FD_ZERO(&curlMultiP->writeFdSet); + FD_ZERO(&curlMultiP->exceptFdSet); + + /* WARNING: curl_multi_fdset() doesn't just update the fdsets pointed + to by its arguments. It makes the CURLM object remember those + pointers and refer back to them later! In fact, curl_multi_perform + expects its caller to have done a select() on those masks. No, + really. The man page even admits it. + + Inspection of the Libcurl code in March 2007 indicates that + this isn't actually true -- curl_multi_fdset() updates your + fdset and doesn't remember the pointer at all. I.e. it's just + what you would expect. The man pages still says it's as + described above. My guess is that Libcurl was fixed at some + time and the man page not updated. In any case, we have to + work with old Libcurl if at all possible, so we still maintain + these fdsets as if they belong to the CURLM object. + */ + + rc = curl_multi_fdset(curlMultiP->curlMultiP, + &curlMultiP->readFdSet, + &curlMultiP->writeFdSet, + &curlMultiP->exceptFdSet, + maxFdP); + + *readFdSetP = curlMultiP->readFdSet; + *writeFdSetP = curlMultiP->writeFdSet; + *exceptFdSetP = curlMultiP->exceptFdSet; + + curlMultiP->lockP->release(curlMultiP->lockP); + + if (rc != CURLM_OK) { + const char * reason; + interpretCurlMultiError(&reason, rc); + xmlrpc_faultf(envP, "Impossible failure of curl_multi_fdset(): %s", + reason); + xmlrpc_strfree(reason); + } +} + + + +void +curlMulti_updateFdSet(curlMulti * const curlMultiP, + fd_set const readFdSet, + fd_set const writeFdSet, + fd_set const exceptFdSet) { +/*---------------------------------------------------------------------------- + curl_multi_perform() expects the file descriptor sets, which were bound + to the CURLM object via a prior curlMulti_fdset(), to contain the results + of a recent select(). This subroutine provides you a way to supply those. +-----------------------------------------------------------------------------*/ + curlMultiP->readFdSet = readFdSet; + curlMultiP->writeFdSet = writeFdSet; + curlMultiP->exceptFdSet = exceptFdSet; +} + + + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlmulti.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlmulti.h new file mode 100644 index 0000000..265ed0c --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlmulti.h @@ -0,0 +1,51 @@ +#ifndef CURLMULTI_H_INCLUDED +#define CURLMULTI_H_INCLUDED + +#include "bool.h" +#include "xmlrpc-c/util.h" + +#include "curltransaction.h" + +typedef struct curlMulti curlMulti; + +curlMulti * +curlMulti_create(void); + +void +curlMulti_destroy(curlMulti * const curlMultiP); + +void +curlMulti_perform(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + bool * const immediateWorkToDoP, + int * const runningHandlesP); + +void +curlMulti_addHandle(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + CURL * const curlSessionP); + +void +curlMulti_removeHandle(curlMulti * const curlMultiP, + CURL * const curlSessionP); + +void +curlMulti_getMessage(curlMulti * const curlMultiP, + bool * const endOfMessagesP, + CURLMsg * const curlMsgP); + +void +curlMulti_fdset(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + fd_set * const readFdSetP, + fd_set * const writeFdSetP, + fd_set * const exceptFdSetP, + int * const maxFdP); + +void +curlMulti_updateFdSet(curlMulti * const curlMultiP, + fd_set const readFdSet, + fd_set const writeFdSet, + fd_set const exceptFdSet); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curltransaction.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curltransaction.c new file mode 100644 index 0000000..630f318 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curltransaction.c @@ -0,0 +1,621 @@ +/*============================================================================= + curlTransaction +=============================================================================*/ + +#include +#include +#include + +#include "mallocvar.h" + +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/client.h" +#include "xmlrpc-c/client_int.h" +#include "version.h" + +#include +#include +#include + +#include "curlversion.h" + +#include "curltransaction.h" + + +struct curlTransaction { + /* This is all stuff that really ought to be in a Curl object, but + the Curl library is a little too simple for that. So we build + a layer on top of Curl, and define this "transaction," as an + object subordinate to a Curl "session." A Curl session has + zero or one transactions in progress. The Curl session + "private data" is a pointer to the CurlTransaction object for + the current transaction. + */ + CURL * curlSessionP; + /* Handle for the Curl session that hosts this transaction. + Note that only one transaction at a time can use a particular + Curl session, so this had better not be a session that some other + transaction is using simultaneously. + */ + curlt_finishFn * finish; + curlt_progressFn * progress; + void * userContextP; + /* Meaningful to our client; opaque to us */ + CURLcode result; + /* Result of the transaction (succeeded, TCP connect failed, etc.). + A properly executed HTTP transaction (request & response) counts + as a successful transaction. When 'result' show success, + curl_easy_get_info() tells you whether the transaction succeeded + at the HTTP level. + */ + char curlError[CURL_ERROR_SIZE]; + /* Error message from Curl */ + struct curl_slist * headerList; + /* The HTTP headers for the transaction */ + const char * serverUrl; /* malloc'ed - belongs to this object */ +}; + + + +static void +addHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP, + const char * const headerText) { + + struct curl_slist * newHeaderList; + newHeaderList = curl_slist_append(*headerListP, headerText); + if (newHeaderList == NULL) + xmlrpc_faultf(envP, + "Could not add header '%s'. " + "curl_slist_append() failed.", headerText); + else + *headerListP = newHeaderList; +} + + + +static void +addContentTypeHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP) { + + addHeader(envP, headerListP, "Content-Type: text/xml"); +} + + + +static void +addUserAgentHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP, + const char * const userAgent) { + + if (userAgent) { + /* Note: Curl has a CURLOPT_USERAGENT option that does some of this + work. We prefer to be totally in control, though, so we build + the header explicitly. + */ + + curl_version_info_data * const curlInfoP = + curl_version_info(CURLVERSION_NOW); + char curlVersion[32]; + const char * userAgentHeader; + + snprintf(curlVersion, sizeof(curlVersion), "%u.%u.%u", + (curlInfoP->version_num >> 16) && 0xff, + (curlInfoP->version_num >> 8) && 0xff, + (curlInfoP->version_num >> 0) && 0xff + ); + + xmlrpc_asprintf(&userAgentHeader, + "User-Agent: %s Xmlrpc-c/%s Curl/%s", + userAgent, XMLRPC_C_VERSION, curlVersion); + + if (userAgentHeader == xmlrpc_strsol) + xmlrpc_faultf(envP, "Couldn't allocate memory for " + "User-Agent header"); + else { + addHeader(envP, headerListP, userAgentHeader); + + xmlrpc_strfree(userAgentHeader); + } + } +} + + + +static void +addAuthorizationHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP, + const char * const hdrValue) { + + const char * authorizationHeader; + + xmlrpc_asprintf(&authorizationHeader, "Authorization: %s", hdrValue); + + if (authorizationHeader == xmlrpc_strsol) + xmlrpc_faultf(envP, "Couldn't allocate memory for " + "Authorization header"); + else { + addHeader(envP, headerListP, authorizationHeader); + + xmlrpc_strfree(authorizationHeader); + } +} + + + +static void +createCurlHeaderList(xmlrpc_env * const envP, + const char * const authHdrValue, + const char * const userAgent, + struct curl_slist ** const headerListP) { + + struct curl_slist * headerList; + + headerList = NULL; /* initial value - empty list */ + + addContentTypeHeader(envP, &headerList); + if (!envP->fault_occurred) { + addUserAgentHeader(envP, &headerList, userAgent); + if (!envP->fault_occurred) { + if (authHdrValue) + addAuthorizationHeader(envP, &headerList, authHdrValue); + } + } + if (envP->fault_occurred) + curl_slist_free_all(headerList); + else + *headerListP = headerList; +} + + + +static size_t +collect(void * const ptr, + size_t const size, + size_t const nmemb, + FILE * const stream) { +/*---------------------------------------------------------------------------- + This is a Curl output function. Curl calls this to deliver the + HTTP response body to the Curl client. Curl thinks it's writing to + a POSIX stream. +-----------------------------------------------------------------------------*/ + xmlrpc_mem_block * const responseXmlP = (xmlrpc_mem_block *) stream; + char * const buffer = ptr; + size_t const length = nmemb * size; + + size_t retval; + xmlrpc_env env; + + xmlrpc_env_init(&env); + xmlrpc_mem_block_append(&env, responseXmlP, buffer, length); + if (env.fault_occurred) + retval = (size_t)-1; + else + /* Really? Shouldn't it be like fread() and return 'nmemb'? */ + retval = length; + + return retval; +} + + + +static int +curlProgress(void * const contextP, + double const dltotal ATTR_UNUSED, + double const dlnow ATTR_UNUSED, + double const ultotal ATTR_UNUSED, + double const ulnow ATTR_UNUSED) { +/*---------------------------------------------------------------------------- + This is a Curl "progress function." It's something various Curl + functions call every so often, including whenever something gets + interrupted by the process receiving, and catching, a signal. + There are two purposes of a Curl progress function: 1) lets us log + the progress of a long-running transaction such as a big download, + e.g. by displaying a progress bar somewhere. In Xmlrpc-c, we don't + implement this purpose. 2) allows us to tell the Curl function, + via our return code, that calls it that we don't want to wait + anymore for the operation to complete. + + In Curl versions before March 2007, we get called once per second + and signals have no effect. In current Curl, we usually get called + immediately after a signal gets caught while Curl is waiting to + receive a response from the server. But Curl doesn't properly + synchronize with signals, so it may miss one and then we don't get + called until the next scheduled one-per-second call. + + All we do is tell Caller it's time to give up if the transport's + client says it is via his "interrupt" flag. + + This function is not as important as it once was. This module used + to use curl_easy_perform(), which can be interrupted only via this + progress function. But because of the above-mentioned failure of + Curl to properly synchronize signals (and Bryan's failure to get + Curl developers to accept code to fix it), we now use the Curl + "multi" facility instead and do our own pselect(). But + This function still normally gets called by curl_multi_perform(), + which the transport tries to call even when the user has requested + interruption, because we don't trust our ability to abort a running + Curl transaction. curl_multi_perform() reliably winds up a Curl + transaction when this function tells it to. +-----------------------------------------------------------------------------*/ + curlTransaction * const curlTransactionP = contextP; + + bool abort; + + /* We require anyone setting us up as the Curl progress function to + supply a progress function: + */ + assert(curlTransactionP); + assert(curlTransactionP->progress); + + curlTransactionP->progress(curlTransactionP->userContextP, &abort); + + return abort; +} + + + +static void +setupAuth(xmlrpc_env * const envP ATTR_UNUSED, + CURL * const curlSessionP, + const xmlrpc_server_info * const serverInfoP, + const char ** const authHdrValueP) { +/*---------------------------------------------------------------------------- + Set the options in the Curl session 'curlSessionP' to set up the HTTP + authentication described by *serverInfoP. + + But we have an odd special function for backward compatibility, because + this code dates to a time when libcurl did not have the ability to + handle authentication, but we provided such function nonetheless by + building our own Authorization: header. But we did this only for + HTTP basic authentication. + + So the special function is this: if libcurl is too old to have + authorization options and *serverInfoP allows basic authentication, + return as *basicAuthHdrParamP an appropriate parameter for the + Authorization: Basic: HTTP header. Otherwise, return + *basicAuthHdrParamP == NULL. +-----------------------------------------------------------------------------*/ + if (serverInfoP->allowedAuth.basic) { + CURLcode rc; + rc = curl_easy_setopt(curlSessionP, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + + if (rc == CURLE_OK) + *authHdrValueP = NULL; + else { + *authHdrValueP = strdup(serverInfoP->basicAuthHdrValue); + if (*authHdrValueP == NULL) + xmlrpc_faultf(envP, "Unable to allocate memory for basic " + "authentication header"); + } + } else + *authHdrValueP = NULL; + + /* We don't worry if libcurl is too old for these other kinds of + authentication; they're only defined as _allowed_ + authentication methods, for when client and server are capable + of using it, and unlike with basic authentication, we have no + historical commitment to consider an old libcurl as capable of + doing these. + */ + + if (serverInfoP->userNamePw) + curl_easy_setopt(curlSessionP, CURLOPT_USERPWD, + serverInfoP->userNamePw); + + if (serverInfoP->allowedAuth.digest) + curl_easy_setopt( + curlSessionP, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); + if (serverInfoP->allowedAuth.gssnegotiate) + curl_easy_setopt( + curlSessionP, CURLOPT_HTTPAUTH, CURLAUTH_GSSNEGOTIATE); + if (serverInfoP->allowedAuth.ntlm) + curl_easy_setopt( + curlSessionP, CURLOPT_HTTPAUTH, CURLAUTH_NTLM); +} + + +static void +setCurlTimeout(CURL * const curlSessionP ATTR_UNUSED, + unsigned int const timeout ATTR_UNUSED) { + +#if HAVE_CURL_NOSIGNAL + unsigned int const timeoutMs = (timeout + 999)/1000; + + curl_easy_setopt(curlSessionP, CURLOPT_NOSIGNAL, 1); + + assert((long)timeoutMs == (int)timeoutMs); + /* Calling requirement */ + curl_easy_setopt(curlSessionP, CURLOPT_TIMEOUT, (long)timeoutMs); +#else + abort(); +#endif +} + + + +static void +assertConstantsMatch(void) { +/*---------------------------------------------------------------------------- + There are some constants that we define as part of the Xmlrpc-c + interface that are identical to constants in the Curl interface to + make curl option setting work. This function asserts such + formally. +-----------------------------------------------------------------------------*/ + assert(XMLRPC_SSLVERSION_DEFAULT == CURL_SSLVERSION_DEFAULT); + assert(XMLRPC_SSLVERSION_TLSv1 == CURL_SSLVERSION_TLSv1); + assert(XMLRPC_SSLVERSION_SSLv2 == CURL_SSLVERSION_SSLv2); + assert(XMLRPC_SSLVERSION_SSLv3 == CURL_SSLVERSION_SSLv3); +} + + + +static void +setupCurlSession(xmlrpc_env * const envP, + curlTransaction * const curlTransactionP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block * const responseXmlP, + const xmlrpc_server_info * const serverInfoP, + const char * const userAgent, + const struct curlSetup * const curlSetupP) { +/*---------------------------------------------------------------------------- + Set up the Curl session for the transaction *curlTransactionP so that + a subsequent curl_easy_perform() would perform said transaction. + + The data curl_easy_perform() would send for that transaction would + be the contents of *callXmlP; the data curl_easy_perform() gets back + would go into *responseXmlP. + + *serverInfoP tells what sort of authentication to set up. This is + an embarassment, as the xmlrpc_server_info type is part of the + Xmlrpc-c interface. Some day, we need to replace this with a type + (probably identical) not tied to Xmlrpc-c. +-----------------------------------------------------------------------------*/ + CURL * const curlSessionP = curlTransactionP->curlSessionP; + + assertConstantsMatch(); + + /* A Curl session is serial -- it processes zero or one transaction + at a time. We use the "private" attribute of the Curl session to + indicate which transaction it is presently processing. This is + important when the transaction finishes, because libcurl will just + tell us that something finished on a particular session, not that + a particular transaction finished. + */ + curl_easy_setopt(curlSessionP, CURLOPT_PRIVATE, curlTransactionP); + + curl_easy_setopt(curlSessionP, CURLOPT_POST, 1); + curl_easy_setopt(curlSessionP, CURLOPT_URL, curlTransactionP->serverUrl); + + XMLRPC_MEMBLOCK_APPEND(char, envP, callXmlP, "\0", 1); + if (!envP->fault_occurred) { + curl_easy_setopt(curlSessionP, CURLOPT_POSTFIELDS, + XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP)); + curl_easy_setopt(curlSessionP, CURLOPT_WRITEFUNCTION, collect); + curl_easy_setopt(curlSessionP, CURLOPT_FILE, responseXmlP); + curl_easy_setopt(curlSessionP, CURLOPT_HEADER, 0); + curl_easy_setopt(curlSessionP, CURLOPT_ERRORBUFFER, + curlTransactionP->curlError); + if (curlTransactionP->progress) { + curl_easy_setopt(curlSessionP, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curlSessionP, CURLOPT_PROGRESSFUNCTION, + curlProgress); + curl_easy_setopt(curlSessionP, CURLOPT_PROGRESSDATA, + curlTransactionP); + } else + curl_easy_setopt(curlSessionP, CURLOPT_NOPROGRESS, 1); + + curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYPEER, + curlSetupP->sslVerifyPeer); + curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYHOST, + curlSetupP->sslVerifyHost ? 2 : 0); + + if (curlSetupP->networkInterface) + curl_easy_setopt(curlSessionP, CURLOPT_INTERFACE, + curlSetupP->networkInterface); + if (curlSetupP->sslCert) + curl_easy_setopt(curlSessionP, CURLOPT_SSLCERT, + curlSetupP->sslCert); + if (curlSetupP->sslCertType) + curl_easy_setopt(curlSessionP, CURLOPT_SSLCERTTYPE, + curlSetupP->sslCertType); + if (curlSetupP->sslCertPasswd) + curl_easy_setopt(curlSessionP, CURLOPT_SSLCERTPASSWD, + curlSetupP->sslCertPasswd); + if (curlSetupP->sslKey) + curl_easy_setopt(curlSessionP, CURLOPT_SSLKEY, + curlSetupP->sslKey); + if (curlSetupP->sslKeyType) + curl_easy_setopt(curlSessionP, CURLOPT_SSLKEYTYPE, + curlSetupP->sslKeyType); + if (curlSetupP->sslKeyPasswd) + curl_easy_setopt(curlSessionP, CURLOPT_SSLKEYPASSWD, + curlSetupP->sslKeyPasswd); + if (curlSetupP->sslEngine) + curl_easy_setopt(curlSessionP, CURLOPT_SSLENGINE, + curlSetupP->sslEngine); + if (curlSetupP->sslEngineDefault) + /* 3rd argument seems to be required by some Curl */ + curl_easy_setopt(curlSessionP, CURLOPT_SSLENGINE_DEFAULT, 1l); + if (curlSetupP->sslVersion != XMLRPC_SSLVERSION_DEFAULT) + curl_easy_setopt(curlSessionP, CURLOPT_SSLVERSION, + curlSetupP->sslVersion); + if (curlSetupP->caInfo) + curl_easy_setopt(curlSessionP, CURLOPT_CAINFO, + curlSetupP->caInfo); + if (curlSetupP->caPath) + curl_easy_setopt(curlSessionP, CURLOPT_CAPATH, + curlSetupP->caPath); + if (curlSetupP->randomFile) + curl_easy_setopt(curlSessionP, CURLOPT_RANDOM_FILE, + curlSetupP->randomFile); + if (curlSetupP->egdSocket) + curl_easy_setopt(curlSessionP, CURLOPT_EGDSOCKET, + curlSetupP->egdSocket); + if (curlSetupP->sslCipherList) + curl_easy_setopt(curlSessionP, CURLOPT_SSL_CIPHER_LIST, + curlSetupP->sslCipherList); + + if (curlSetupP->timeout) + setCurlTimeout(curlSessionP, curlSetupP->timeout); + + { + const char * authHdrValue; + /* NULL means we don't have to construct an explicit + Authorization: header. non-null means we have to + construct one with this as its value. + */ + + setupAuth(envP, curlSessionP, serverInfoP, &authHdrValue); + if (!envP->fault_occurred) { + struct curl_slist * headerList; + createCurlHeaderList(envP, authHdrValue, userAgent, + &headerList); + if (!envP->fault_occurred) { + curl_easy_setopt( + curlSessionP, CURLOPT_HTTPHEADER, headerList); + curlTransactionP->headerList = headerList; + } + if (authHdrValue) + xmlrpc_strfree(authHdrValue); + } + } + } +} + + + +void +curlTransaction_create(xmlrpc_env * const envP, + CURL * const curlSessionP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block * const responseXmlP, + const char * const userAgent, + const struct curlSetup * const curlSetupStuffP, + void * const userContextP, + curlt_finishFn * const finish, + curlt_progressFn * const progress, + curlTransaction ** const curlTransactionPP) { + + curlTransaction * curlTransactionP; + + MALLOCVAR(curlTransactionP); + if (curlTransactionP == NULL) + xmlrpc_faultf(envP, "No memory to create Curl transaction."); + else { + curlTransactionP->finish = finish; + curlTransactionP->curlSessionP = curlSessionP; + curlTransactionP->userContextP = userContextP; + curlTransactionP->progress = progress; + + curlTransactionP->serverUrl = strdup(serverP->serverUrl); + if (curlTransactionP->serverUrl == NULL) + xmlrpc_faultf(envP, "Out of memory to store server URL."); + else { + setupCurlSession(envP, curlTransactionP, + callXmlP, responseXmlP, + serverP, userAgent, + curlSetupStuffP); + + if (envP->fault_occurred) + xmlrpc_strfree(curlTransactionP->serverUrl); + } + if (envP->fault_occurred) + free(curlTransactionP); + } + *curlTransactionPP = curlTransactionP; +} + + + +void +curlTransaction_destroy(curlTransaction * const curlTransactionP) { + + curl_slist_free_all(curlTransactionP->headerList); + xmlrpc_strfree(curlTransactionP->serverUrl); + + free(curlTransactionP); +} + + + +static void +interpretCurlEasyError(const char ** const descriptionP, + CURLcode const code) { + +#if HAVE_CURL_STRERROR + *descriptionP = strdup(curl_easy_strerror(code)); +#else + xmlrpc_asprintf(descriptionP, "Curl error code (CURLcode) %d", code); +#endif +} + + + +void +curlTransaction_getError(curlTransaction * const curlTransactionP, + xmlrpc_env * const envP) { + + if (curlTransactionP->result != CURLE_OK) { + /* We've seen Curl just return a null string for an explanation + (e.g. when TCP connect() fails because IP address doesn't exist). + */ + const char * explanation; + + if (strlen(curlTransactionP->curlError) == 0) + interpretCurlEasyError(&explanation, curlTransactionP->result); + else + xmlrpc_asprintf(&explanation, "%s", curlTransactionP->curlError); + + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_NETWORK_ERROR, "libcurl failed to execute the " + "HTTP POST transaction. %s", explanation); + + xmlrpc_strfree(explanation); + } else { + CURLcode res; + long http_result; + + res = curl_easy_getinfo(curlTransactionP->curlSessionP, + CURLINFO_HTTP_CODE, &http_result); + + if (res != CURLE_OK) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INTERNAL_ERROR, + "Curl performed the HTTP POST request, but was " + "unable to say what the HTTP result code was. " + "curl_easy_getinfo(CURLINFO_HTTP_CODE) says: %s", + curlTransactionP->curlError); + else { + if (http_result != 200) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_NETWORK_ERROR, + "HTTP response code is %ld, not 200", + http_result); + } + } +} + + + +void +curlTransaction_finish(xmlrpc_env * const envP, + curlTransaction * const curlTransactionP, + CURLcode const result) { + + curlTransactionP->result = result; + + if (curlTransactionP->finish) + curlTransactionP->finish(envP, curlTransactionP->userContextP); +} + + + +CURL * +curlTransaction_curlSession(curlTransaction * const curlTransactionP) { + + return curlTransactionP->curlSessionP; + +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curltransaction.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curltransaction.h new file mode 100644 index 0000000..c1ab5ce --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curltransaction.h @@ -0,0 +1,106 @@ +#ifndef CURLTRANSACTION_H_INCLUDED +#define CURLTRANSACTION_H_INCLUDED + +#include "bool.h" +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/client.h" +#include + +typedef struct curlTransaction curlTransaction; + +typedef void curlt_finishFn(xmlrpc_env * const, void * const); +typedef void curlt_progressFn(void * const, bool * const); + +struct curlSetup { + + /* This is all client transport properties that are implemented as + simple Curl session properties (i.e. the transport basically just + passes them through to Curl without looking at them). + + People occasionally want to replace all this with something where + the Xmlrpc-c user simply does the curl_easy_setopt() call and this + code need not know about all these options. Unfortunately, that's + a significant modularity violation. Either the Xmlrpc-c user + controls the Curl object or he doesn't. If he does, then he + shouldn't use libxmlrpc_client -- he should just copy some of this + code into his own program. If he doesn't, then he should never see + the Curl library. + + Speaking of modularity: the only reason this is a separate struct + is to make the code easier to manage. Ideally, the fact that these + particular properties of the transport are implemented by simple + Curl session setup would be known only at the lowest level code + that does that setup. + */ + + const char * networkInterface; + /* This identifies the network interface on the local side to + use for the session. It is an ASCIIZ string in the form + that the Curl recognizes for setting its CURLOPT_INTERFACE + option (also the --interface option of the Curl program). + E.g. "9.1.72.189" or "giraffe-data.com" or "eth0". + + It isn't necessarily valid, but it does have a terminating NUL. + + NULL means we have no preference. + */ + bool sslVerifyPeer; + /* In an SSL connection, we should authenticate the server's SSL + certificate -- refuse to talk to him if it isn't authentic. + This is equivalent to Curl's CURLOPT_SSL_VERIFY_PEER option. + */ + bool sslVerifyHost; + /* In an SSL connection, we should verify that the server's + certificate (independently of whether the certificate is + authentic) indicates the host name that is in the URL we + are using for the server. + */ + + const char * sslCert; + const char * sslCertType; + const char * sslCertPasswd; + const char * sslKey; + const char * sslKeyType; + const char * sslKeyPasswd; + const char * sslEngine; + bool sslEngineDefault; + unsigned int sslVersion; + const char * caInfo; + const char * caPath; + const char * randomFile; + const char * egdSocket; + const char * sslCipherList; + unsigned int timeout; + /* 0 = no Curl timeout. This is in milliseconds. */ +}; + + +void +curlTransaction_create(xmlrpc_env * const envP, + CURL * const curlSessionP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block * const responseXmlP, + const char * const userAgent, + const struct curlSetup * const curlSetupStuffP, + void * const userContextP, + curlt_finishFn * const finish, + curlt_progressFn * const progress, + curlTransaction ** const curlTransactionPP); + +void +curlTransaction_destroy(curlTransaction * const curlTransactionP); + +void +curlTransaction_finish(xmlrpc_env * const envP, + curlTransaction * const curlTransactionP, + CURLcode const result); + +void +curlTransaction_getError(curlTransaction * const curlTransactionP, + xmlrpc_env * const envP); + +CURL * +curlTransaction_curlSession(curlTransaction * const curlTransactionP); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlversion.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlversion.h new file mode 100644 index 0000000..71c5a68 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/curlversion.h @@ -0,0 +1,20 @@ +#ifndef CURLVERSION_H_INCLUDED +#define CURLVERSION_H_INCLUDED + +#define CMAJOR LIBCURL_VERSION_MAJOR +#define CMINOR LIBCURL_VERSION_MINOR +#if CMAJOR > 7 || (CMAJOR == 7 && CMINOR >= 10) + #define HAVE_CURL_NOSIGNAL 1 +#else + #define HAVE_CURL_NOSIGNAL 0 +#endif +#if CMAJOR > 7 || (CMAJOR == 7 && CMINOR >= 12) + #define HAVE_CURL_STRERROR 1 +#else + #define HAVE_CURL_STRERROR 0 +#endif + +#undef CMAJOR +#undef CMINOR + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock.h new file mode 100644 index 0000000..bb7ce42 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock.h @@ -0,0 +1,24 @@ +#ifndef CURL_LOCK_H_INCLUDED +#define CURL_LOCK_H_INCLUDED + +#include + +typedef struct lock lock; + +typedef void lockAcquireFn(lock *); +typedef void lockReleaseFn(lock *); +typedef void lockDestroyFn(lock *); + +struct lock { + /* To finish the job of making an abstract lock class that can use locks + other than pthread mutexes, we need to replace 'theLock' with a + "void * implementationP" and make curlLock_create_pthread() malloc + the mutex. + */ + pthread_mutex_t theLock; + lockAcquireFn * acquire; + lockReleaseFn * release; + lockDestroyFn * destroy; +}; + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock_pthread.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock_pthread.c new file mode 100644 index 0000000..24b029e --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock_pthread.c @@ -0,0 +1,49 @@ +#include + +#include "mallocvar.h" +#include "pthreadx.h" + +#include "lock.h" + +#include "lock_pthread.h" + +static lockAcquireFn acquire; + +static void +acquire(struct lock * const lockP) { + pthread_mutex_lock(&lockP->theLock); +} + + + +static lockReleaseFn release; + +static void +release(struct lock * const lockP) { + pthread_mutex_unlock(&lockP->theLock); +} + + + +static lockDestroyFn destroy; + +static void +destroy(struct lock * const lockP) { + pthread_mutex_destroy(&lockP->theLock); + free(lockP); +} + + + +struct lock * +curlLock_create_pthread(void) { + struct lock * lockP; + MALLOCVAR(lockP); + if (lockP) { + pthread_mutex_init(&lockP->theLock, NULL); + lockP->acquire = &acquire; + lockP->release = &release; + lockP->destroy = &destroy; + } + return lockP; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock_pthread.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock_pthread.h new file mode 100644 index 0000000..49ffa51 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/lock_pthread.h @@ -0,0 +1,9 @@ +#ifndef CURL_LOCK_PTHREAD_H_INCLUDED +#define CURL_LOCK_PTHREAD_H_INCLUDED + +#include "lock.h" + +lock * +curlLock_create_pthread(void); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/xmlrpc_curl_transport.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/xmlrpc_curl_transport.c new file mode 100644 index 0000000..526381d --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/curl-transport/xmlrpc_curl_transport.c @@ -0,0 +1,1419 @@ +/*============================================================================= + xmlrpc_curl_transport +=============================================================================== + Curl-based client transport for Xmlrpc-c + + By Bryan Henderson 04.12.10. + + Contributed to the public domain by its author. +=============================================================================*/ + +/*---------------------------------------------------------------------------- + Curl global variables: + + Curl maintains some minor information in process-global variables. + One must call curl_global_init() to initialize them before calling + any other Curl library function. This is not state information -- + it is constants. They just aren't the kind of constants that the + library loader knows how to set, so there has to be this explicit + call to set them up. The matching function curl_global_cleanup() + returns resources these use (to wit, the constants live in + malloc'ed storage and curl_global_cleanup() frees the storage). + + So our setup_global_const transport operation calls + curl_global_init() and our teardown_global_const calls + curl_global_cleanup(). + + The Curl library is supposed to maintain a reference count for the + global constants so that multiple modules using the library and + independently calling curl_global_init() and curl_global_cleanup() + are not a problem. But today, it just keeps a flag "I have been + initialized" and the first call to curl_global_cleanup() destroys + the constants for everybody. Therefore, the user of the Xmlrpc-c + Curl client XML transport must make sure not to call + teardownGlobalConstants until everything else in his program is + done using the Curl library. + + Note that curl_global_init() is not threadsafe (with or without the + reference count), therefore our setup_global_const is not, and must + be called when no other thread in the process is running. + Typically, one calls it right at the beginning of the program. + + There are actually two other classes of global variables in the + Curl library, which we are ignoring: debug options and custom + memory allocator function identities. Our code never changes these + global variables from default. If something else in the user's + program does, User is responsible for making sure it doesn't + interfere with our use of the library. + + Note that when we say what the Curl library does, we're also + talking about various other libraries Curl uses internally, and in + fact much of what we're saying about global variables springs from + such subordinate libraries as OpenSSL and Winsock. +-----------------------------------------------------------------------------*/ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include +#include +#if !MSVCRT +#include +#endif +#include + +#ifdef WIN32 +#include "curllink.h" +#endif + +#include "bool.h" +#include "girmath.h" +#include "mallocvar.h" +#include "linklist.h" +#include "girstring.h" +#include "pthreadx.h" + +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/select_int.h" +#include "xmlrpc-c/client_int.h" +#include "xmlrpc-c/transport.h" +#include "xmlrpc-c/time_int.h" + +#include +#include +#include +#include + +#include "lock.h" +#include "lock_pthread.h" +#include "curltransaction.h" +#include "curlmulti.h" +#include "curlversion.h" + +#if MSVCRT +#if defined(_DEBUG) +# include +# define new DEBUG_NEW +# define malloc(size) _malloc_dbg( size, _NORMAL_BLOCK, __FILE__, __LINE__) +# undef THIS_FILE + static char THIS_FILE[] = __FILE__; +#endif +#endif + + +typedef struct rpc rpc; + + + +static int +timeDiffMillisec(xmlrpc_timespec const minuend, + xmlrpc_timespec const subtractor) { + + unsigned int const million = 1000000; + + return (minuend.tv_sec - subtractor.tv_sec) * 1000 + + (minuend.tv_nsec - subtractor.tv_nsec + million/2) / million; +} + + + +static bool +timeIsAfter(xmlrpc_timespec const comparator, + xmlrpc_timespec const comparand) { + + if (comparator.tv_sec > comparand.tv_sec) + return true; + else if (comparator.tv_sec < comparand.tv_sec) + return false; + else { + /* Seconds are equal */ + if (comparator.tv_nsec > comparand.tv_nsec) + return true; + else + return false; + } +} + + + +static void +addMilliseconds(xmlrpc_timespec const addend, + unsigned int const adder, + xmlrpc_timespec * const sumP) { + + unsigned int const million = 1000000; + unsigned int const billion = 1000000000; + + xmlrpc_timespec sum; + + sum.tv_sec = addend.tv_sec + adder / 1000; + sum.tv_nsec = addend.tv_nsec + (adder % 1000) * million; + + if ((uint32_t)sum.tv_nsec >= billion) { + sum.tv_sec += 1; + sum.tv_nsec -= billion; + } + *sumP = sum; +} + + + +struct xmlrpc_client_transport { + CURL * syncCurlSessionP; + /* Handle for a Curl library session object that we use for + all synchronous RPCs. An async RPC has one of its own, + and consequently does not share things such as persistent + connections and cookies with any other RPC. + */ + lock * syncCurlSessionLockP; + /* Hold this lock while accessing or using *syncCurlSessionP. + You're using the session from the time you set any + attributes in it or start a transaction with it until any + transaction has finished and you've lost interest in any + attributes of the session. + */ + curlMulti * syncCurlMultiP; + /* The Curl multi manager that this transport uses to execute + Curl transactions for RPCs requested via the synchronous + interface. The fact that there is never more than one such + transaction going at a time might make you wonder why a + "multi" manager is needed. The reason is that it is the only + interface in libcurl that gives us the flexibility to execute + the transaction with proper interruptibility. The only Curl + transaction ever attached to this multi manager is + 'syncCurlSessionP'. + + This is constant (the handle, not the object). + */ + curlMulti * asyncCurlMultiP; + /* The Curl multi manager that this transport uses to execute + Curl transactions for RPCs requested via the asynchronous + interface. Note that there may be multiple such Curl transactions + simultaneously and one can't wait for a particular one to finish; + the collection of asynchronous RPCs are an indivisible mass. + + This is constant (the handle, not the object). + */ + const char * userAgent; + /* Prefix for the User-Agent HTTP header, reflecting facilities + outside of Xmlrpc-c. The actual User-Agent header consists + of this prefix plus information about Xmlrpc-c. NULL means + none. + + This is constant. + */ + struct curlSetup curlSetupStuff; + /* This is constant */ + int * interruptP; + /* Pointer to a value that user sets to nonzero to indicate he wants + the transport to give up on whatever it is doing and return ASAP. + + NULL means none -- transport never gives up. + */ +}; + + + +struct rpc { + struct xmlrpc_client_transport * transportP; + /* The client XML transport that transports this RPC */ + curlTransaction * curlTransactionP; + /* The object which does the HTTP transaction, with no knowledge + of XML-RPC or Xmlrpc-c. + */ + CURL * curlSessionP; + /* The Curl session to use for the Curl transaction to perform + the RPC. + */ + xmlrpc_mem_block * responseXmlP; + /* Where the response XML for this RPC should go or has gone. */ + xmlrpc_transport_asynch_complete complete; + /* Routine to call to complete the RPC after it is complete HTTP-wise. + NULL if none. + */ + struct xmlrpc_call_info * callInfoP; + /* User's identifier for this RPC */ +}; + + +static void +lockSyncCurlSession(struct xmlrpc_client_transport * const transportP) { + transportP->syncCurlSessionLockP->acquire( + transportP->syncCurlSessionLockP); +} + + + +static void +unlockSyncCurlSession(struct xmlrpc_client_transport * const transportP) { + transportP->syncCurlSessionLockP->release( + transportP->syncCurlSessionLockP); +} + + + +static void +initWindowsStuff(xmlrpc_env * const envP ATTR_UNUSED) { + +#if defined (WIN32) + /* This is CRITICAL so that cURL-Win32 works properly! */ + + /* So this commenter says, but I wonder why. libcurl should do the + required WSAStartup() itself, and it looks to me like it does. + -Bryan 06.01.01 + */ + WORD wVersionRequested; + WSADATA wsaData; + int err; + wVersionRequested = MAKEWORD(1, 1); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INTERNAL_ERROR, + "Winsock startup failed. WSAStartup returned rc %d", err); + else { + if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INTERNAL_ERROR, "Winsock reported that " + "it does not implement the requested version 1.1."); + } + if (envP->fault_occurred) + WSACleanup(); + } +#endif +} + + + +static void +termWindowsStuff(void) { + +#if defined (WIN32) + WSACleanup(); +#endif +} + + + +static bool +curlHasNosignal(void) { + + bool retval; + +#if HAVE_CURL_NOSIGNAL + curl_version_info_data * const curlInfoP = + curl_version_info(CURLVERSION_NOW); + + retval = (curlInfoP->version_num >= 0x070A00); /* 7.10.0 */ +#else + retval = false; +#endif + return retval; +} + + + +static xmlrpc_timespec +pselectTimeout(xmlrpc_timeoutType const timeoutType, + xmlrpc_timespec const timeoutDt) { +/*---------------------------------------------------------------------------- + Return the value that should be used in the select() call to wait for + there to be work for the Curl multi manager to do, given that the user + wants to timeout according to 'timeoutType' and 'timeoutDt'. +-----------------------------------------------------------------------------*/ + unsigned int const million = 1000000; + unsigned int selectTimeoutMillisec; + xmlrpc_timespec retval; + + selectTimeoutMillisec = 0; /* quiet compiler warning */ + + /* We assume there is work to do at least every 3 seconds, because + the Curl multi manager often has retries and other scheduled work + that doesn't involve file handles on which we can select(). + */ + switch (timeoutType) { + case timeout_no: + selectTimeoutMillisec = 3000; + break; + case timeout_yes: { + xmlrpc_timespec nowTime; + int timeLeft; + + xmlrpc_gettimeofday(&nowTime); + timeLeft = timeDiffMillisec(timeoutDt, nowTime); + + selectTimeoutMillisec = MIN(3000, MAX(0, timeLeft)); + } break; + } + retval.tv_sec = selectTimeoutMillisec / 1000; + retval.tv_nsec = (uint32_t)((selectTimeoutMillisec % 1000) * million); + + return retval; +} + + + +static void +processCurlMessages(xmlrpc_env * const envP, + curlMulti * const curlMultiP) { + + bool endOfMessages; + + endOfMessages = false; /* initial assumption */ + + while (!endOfMessages && !envP->fault_occurred) { + CURLMsg curlMsg; + + curlMulti_getMessage(curlMultiP, &endOfMessages, &curlMsg); + + if (!endOfMessages) { + if (curlMsg.msg == CURLMSG_DONE) { + curlTransaction * curlTransactionP; + + curl_easy_getinfo(curlMsg.easy_handle, CURLINFO_PRIVATE, + &curlTransactionP); + + curlTransaction_finish(envP, + curlTransactionP, curlMsg.data.result); + } + } + } +} + + + +static void +waitForWork(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + xmlrpc_timeoutType const timeoutType, + xmlrpc_timespec const deadline, + sigset_t * const sigmaskP) { +/*---------------------------------------------------------------------------- + Wait for the Curl multi manager to have work to do, time to run out, + or a signal to be received (and caught), whichever comes first. + + Update the Curl multi manager's file descriptor sets to indicate what + work we found for it to do. + + Wait under signal mask *sigmaskP. The point of this is that Caller + can make sure that arrival of a signal of a certain class + interrupts our wait, even if the signal arrives shortly before we + begin waiting. Caller blocks that signal class, then checks + whether a signal of that class has already been received. If not, + he calls us with *sigmaskP indicating that class NOT blocked. + Thus, if a signal of that class arrived any time after Caller + checked, we will return immediately or when the signal arrives, + whichever is sooner. Note that we can provide this service only + because pselect() has the same atomic unblock/wait feature. + + If sigmaskP is NULL, wait under whatever the current signal mask + is. +-----------------------------------------------------------------------------*/ + fd_set readFdSet; + fd_set writeFdSet; + fd_set exceptFdSet; + int maxFd; + + curlMulti_fdset(envP, curlMultiP, + &readFdSet, &writeFdSet, &exceptFdSet, &maxFd); + if (!envP->fault_occurred) { + if (maxFd == -1) { + /* There are no Curl file descriptors on which to wait. + So either there's work to do right now or all transactions + are already complete. + */ + } else { + xmlrpc_timespec const pselectTimeoutArg = + pselectTimeout(timeoutType, deadline); + + int rc; + + rc = xmlrpc_pselect(maxFd+1, &readFdSet, &writeFdSet, &exceptFdSet, + &pselectTimeoutArg, sigmaskP); + + if (rc < 0 && errno != EINTR) + xmlrpc_faultf(envP, "Impossible failure of pselect() " + "with errno %d (%s)", + errno, strerror(errno)); + else { + /* Believe it or not, the Curl multi manager needs the + results of our pselect(). So hand them over: + */ + curlMulti_updateFdSet(curlMultiP, + readFdSet, writeFdSet, exceptFdSet); + } + } + } +} + + + +static void +waitForWorkInt(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + xmlrpc_timeoutType const timeoutType, + xmlrpc_timespec const deadline, + int * const interruptP) { +/*---------------------------------------------------------------------------- + Same as waitForWork(), except we guarantee to return if a signal handler + sets or has set *interruptP, whereas waitForWork() can miss a signal + that happens before or just after it starts. + + We mess with global state -- the signal mask -- so we might mess up + a multithreaded program. Therefore, don't call this if + waitForWork() will suffice. +-----------------------------------------------------------------------------*/ + sigset_t callerBlockSet; +#ifdef WIN32 + waitForWork(envP, curlMultiP, timeoutType, deadline, &callerBlockSet); +#else + sigset_t allSignals; + + assert(interruptP != NULL); + + sigfillset(&allSignals); + + sigprocmask(SIG_BLOCK, &allSignals, &callerBlockSet); + + if (*interruptP == 0) + waitForWork(envP, curlMultiP, timeoutType, deadline, &callerBlockSet); + + sigprocmask(SIG_SETMASK, &callerBlockSet, NULL); +#endif +} + + + +static void +doCurlWork(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + bool * const transStillRunningP) { +/*---------------------------------------------------------------------------- + Do whatever work is ready to be done by the Curl multi manager + identified by 'curlMultiP'. This typically is transferring data on + an HTTP connection because the server is ready. + + For each transaction for which the multi manager finishes all the + required work, complete the transaction by calling its + "finish" routine. + + Return *transStillRunningP false if this work completes all of the + manager's transactions so that there is no reason to call us ever + again. +-----------------------------------------------------------------------------*/ + bool immediateWorkToDo; + int runningHandles; + + immediateWorkToDo = true; /* initial assumption */ + + while (immediateWorkToDo && !envP->fault_occurred) { + curlMulti_perform(envP, curlMultiP, + &immediateWorkToDo, &runningHandles); + } + + /* We either did all the work that's ready to do or hit an error. */ + + if (!envP->fault_occurred) { + /* The work we did may have resulted in asynchronous messages + (asynchronous to the thing they refer to, not to us, of course). + In particular the message "Curl transaction has completed". + So we process those now. + */ + processCurlMessages(envP, curlMultiP); + + *transStillRunningP = runningHandles > 0; + } +} + + + +static void +finishCurlMulti(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + xmlrpc_timeoutType const timeoutType, + xmlrpc_timespec const deadline, + int * const interruptP) { +/*---------------------------------------------------------------------------- + Prosecute all the Curl transactions under the control of + *curlMultiP. E.g. send data if server is ready to take it, get + data if server has sent some, wind up the transaction if it is + done. + + Don't return until all the Curl transactions are done or we time out. + + The *interruptP flag alone will not interrupt us. We will wait in + spite of it for all Curl transactions to complete. *interruptP + just gives us a hint that the Curl transactions are being + interrupted, so we know there is work to do for them. (The way it + works is Caller sets up a "progress" function that checks the same + interrupt flag and reports "kill me." When we see the interrupt + flag, we call that progress function and get the message). +-----------------------------------------------------------------------------*/ + bool rpcStillRunning; + bool timedOut; + + rpcStillRunning = true; /* initial assumption */ + timedOut = false; + + while (rpcStillRunning && !timedOut && !envP->fault_occurred) { + + if (interruptP) { + waitForWorkInt(envP, curlMultiP, timeoutType, deadline, + interruptP); + } else + waitForWork(envP, curlMultiP, timeoutType, deadline, NULL); + + if (!envP->fault_occurred) { + xmlrpc_timespec nowTime; + + /* doCurlWork() (among other things) finds Curl + transactions that user wants to abort and finishes + them. + */ + doCurlWork(envP, curlMultiP, &rpcStillRunning); + + xmlrpc_gettimeofday(&nowTime); + + timedOut = (timeoutType == timeout_yes && + timeIsAfter(nowTime, deadline)); + } + } +} + + + +static void +getTimeoutParm(xmlrpc_env * const envP, + const struct xmlrpc_curl_xportparms * const curlXportParmsP, + size_t const parmSize, + unsigned int * const timeoutP) { + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(timeout)) + *timeoutP = 0; + else { + if (curlHasNosignal()) { + /* libcurl takes a 'long' in milliseconds for the timeout value */ + if ((curlXportParmsP->timeout + 999) / 1000 > LONG_MAX) + xmlrpc_faultf(envP, "Timeout value %u is too large.", + curlXportParmsP->timeout); + else + *timeoutP = curlXportParmsP->timeout; + } else + xmlrpc_faultf(envP, "You cannot specify a 'timeout' parameter " + "because the Curl library is too old and is not " + "capable of doing timeouts except by using " + "signals. You need at least Curl 7.10"); + } +} + + + +static void +getXportParms(xmlrpc_env * const envP, + const struct xmlrpc_curl_xportparms * const curlXportParmsP, + size_t const parmSize, + struct xmlrpc_client_transport * const transportP) { +/*---------------------------------------------------------------------------- + Get the parameters out of *curlXportParmsP and update *transportP + to reflect them. + + *curlXportParmsP is a 'parmSize' bytes long prefix of + struct xmlrpc_curl_xportparms. + + curlXportParmsP is something the user created. It's designed to be + friendly to the user, not to this program, and is encumbered by + lots of backward compatibility constraints. In particular, the + user may have coded and/or compiled it at a time that struct + xmlrpc_curl_xportparms was smaller than it is now! + + Also, the user might have specified something invalid. + + So that's why we don't simply attach a copy of *curlXportParmsP to + *transportP. + + To the extent that *curlXportParmsP is too small to contain a parameter, + we return the default value for that parameter. + + Special case: curlXportParmsP == NULL means there is no input at all. + In that case, we return default values for everything. +-----------------------------------------------------------------------------*/ + struct curlSetup * const curlSetupP = &transportP->curlSetupStuff; + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(user_agent)) + transportP->userAgent = NULL; + else if (curlXportParmsP->user_agent == NULL) + transportP->userAgent = NULL; + else + transportP->userAgent = strdup(curlXportParmsP->user_agent); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(network_interface)) + curlSetupP->networkInterface = NULL; + else if (curlXportParmsP->network_interface == NULL) + curlSetupP->networkInterface = NULL; + else + curlSetupP->networkInterface = + strdup(curlXportParmsP->network_interface); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(no_ssl_verifypeer)) + curlSetupP->sslVerifyPeer = true; + else + curlSetupP->sslVerifyPeer = !curlXportParmsP->no_ssl_verifypeer; + + if (!curlXportParmsP || + parmSize < XMLRPC_CXPSIZE(no_ssl_verifyhost)) + curlSetupP->sslVerifyHost = true; + else + curlSetupP->sslVerifyHost = !curlXportParmsP->no_ssl_verifyhost; + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(ssl_cert)) + curlSetupP->sslCert = NULL; + else if (curlXportParmsP->ssl_cert == NULL) + curlSetupP->sslCert = NULL; + else + curlSetupP->sslCert = strdup(curlXportParmsP->ssl_cert); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslcerttype)) + curlSetupP->sslCertType = NULL; + else if (curlXportParmsP->sslcerttype == NULL) + curlSetupP->sslCertType = NULL; + else + curlSetupP->sslCertType = strdup(curlXportParmsP->sslcerttype); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslcertpasswd)) + curlSetupP->sslCertPasswd = NULL; + else if (curlXportParmsP->sslcertpasswd == NULL) + curlSetupP->sslCertPasswd = NULL; + else + curlSetupP->sslCertPasswd = strdup(curlXportParmsP->sslcertpasswd); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkey)) + curlSetupP->sslKey = NULL; + else if (curlXportParmsP->sslkey == NULL) + curlSetupP->sslKey = NULL; + else + curlSetupP->sslKey = strdup(curlXportParmsP->sslkey); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkeytype)) + curlSetupP->sslKeyType = NULL; + else if (curlXportParmsP->sslkeytype == NULL) + curlSetupP->sslKeyType = NULL; + else + curlSetupP->sslKeyType = strdup(curlXportParmsP->sslkeytype); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkeypasswd)) + curlSetupP->sslKeyPasswd = NULL; + else if (curlXportParmsP->sslkeypasswd == NULL) + curlSetupP->sslKeyPasswd = NULL; + else + curlSetupP->sslKeyPasswd = strdup(curlXportParmsP->sslkeypasswd); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslengine)) + curlSetupP->sslEngine = NULL; + else if (curlXportParmsP->sslengine == NULL) + curlSetupP->sslEngine = NULL; + else + curlSetupP->sslEngine = strdup(curlXportParmsP->sslengine); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslengine_default)) + curlSetupP->sslEngineDefault = false; + else + curlSetupP->sslEngineDefault = !!curlXportParmsP->sslengine_default; + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslversion)) + curlSetupP->sslVersion = XMLRPC_SSLVERSION_DEFAULT; + else + curlSetupP->sslVersion = curlXportParmsP->sslversion; + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(cainfo)) + curlSetupP->caInfo = NULL; + else if (curlXportParmsP->cainfo == NULL) + curlSetupP->caInfo = NULL; + else + curlSetupP->caInfo = strdup(curlXportParmsP->cainfo); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(capath)) + curlSetupP->caPath = NULL; + else if (curlXportParmsP->capath == NULL) + curlSetupP->caPath = NULL; + else + curlSetupP->caPath = strdup(curlXportParmsP->capath); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(randomfile)) + curlSetupP->randomFile = NULL; + else if (curlXportParmsP->randomfile == NULL) + curlSetupP->randomFile = NULL; + else + curlSetupP->randomFile = strdup(curlXportParmsP->randomfile); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(egdsocket)) + curlSetupP->egdSocket = NULL; + else if (curlXportParmsP->egdsocket == NULL) + curlSetupP->egdSocket = NULL; + else + curlSetupP->egdSocket = strdup(curlXportParmsP->egdsocket); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(ssl_cipher_list)) + curlSetupP->sslCipherList = NULL; + else if (curlXportParmsP->ssl_cipher_list == NULL) + curlSetupP->sslCipherList = NULL; + else + curlSetupP->sslCipherList = strdup(curlXportParmsP->ssl_cipher_list); + + getTimeoutParm(envP, curlXportParmsP, parmSize, &curlSetupP->timeout); +} + + + +static void +freeXportParms(const struct xmlrpc_client_transport * const transportP) { + + const struct curlSetup * const curlSetupP = &transportP->curlSetupStuff; + + if (curlSetupP->sslCipherList) + xmlrpc_strfree(curlSetupP->sslCipherList); + if (curlSetupP->egdSocket) + xmlrpc_strfree(curlSetupP->egdSocket); + if (curlSetupP->randomFile) + xmlrpc_strfree(curlSetupP->randomFile); + if (curlSetupP->caPath) + xmlrpc_strfree(curlSetupP->caPath); + if (curlSetupP->caInfo) + xmlrpc_strfree(curlSetupP->caInfo); + if (curlSetupP->sslEngine) + xmlrpc_strfree(curlSetupP->sslEngine); + if (curlSetupP->sslKeyPasswd) + xmlrpc_strfree(curlSetupP->sslKeyPasswd); + if (curlSetupP->sslKeyType) + xmlrpc_strfree(curlSetupP->sslKeyType); + if (curlSetupP->sslKey) + xmlrpc_strfree(curlSetupP->sslKey); + if (curlSetupP->sslCertPasswd) + xmlrpc_strfree(curlSetupP->sslCertPasswd); + if (curlSetupP->sslCertType) + xmlrpc_strfree(curlSetupP->sslCertType); + if (curlSetupP->sslCert) + xmlrpc_strfree(curlSetupP->sslCert); + if (curlSetupP->networkInterface) + xmlrpc_strfree(curlSetupP->networkInterface); + if (transportP->userAgent) + xmlrpc_strfree(transportP->userAgent); +} + + + +static void +createSyncCurlSession(xmlrpc_env * const envP, + CURL ** const curlSessionPP) { +/*---------------------------------------------------------------------------- + Create a Curl session to be used for multiple serial transactions. + The Curl session we create is not complete -- it still has to be + further set up for each particular transaction. + + We can't set up anything here that changes from one transaction to the + next. + + We don't bother setting up anything that has to be set up for an + asynchronous transaction because code that is common between synchronous + and asynchronous transactions takes care of that anyway. + + That leaves things, such as cookies, that don't exist for + asynchronous transactions, and are common to multiple serial + synchronous transactions. +-----------------------------------------------------------------------------*/ + CURL * const curlSessionP = curl_easy_init(); + + if (curlSessionP == NULL) + xmlrpc_faultf(envP, "Could not create Curl session. " + "curl_easy_init() failed."); + else { + /* The following is a trick. CURLOPT_COOKIEFILE is the name + of the file containing the initial cookies for the Curl + session. But setting it is also what turns on the cookie + function itself, whereby the Curl library accepts and + stores cookies from the server and sends them back on + future requests. We don't have a file of initial cookies, but + we want to turn on cookie function, so we set the option to + something we know does not validly name a file. Curl will + ignore the error and just start up cookie function with no + initial cookies. + */ + curl_easy_setopt(curlSessionP, CURLOPT_COOKIEFILE, ""); + + *curlSessionPP = curlSessionP; + } +} + + + +static void +destroySyncCurlSession(CURL * const curlSessionP) { + + curl_easy_cleanup(curlSessionP); +} + + + +static void +makeSyncCurlSession(xmlrpc_env * const envP, + struct xmlrpc_client_transport * const transportP) { + + transportP->syncCurlSessionLockP = curlLock_create_pthread(); + if (transportP->syncCurlSessionLockP == NULL) + xmlrpc_faultf(envP, "Unable to create lock for " + "synchronous Curl session."); + else { + createSyncCurlSession(envP, &transportP->syncCurlSessionP); + + if (!envP->fault_occurred) { + /* We'll need a multi manager to actually execute this session: */ + transportP->syncCurlMultiP = curlMulti_create(); + + if (transportP->syncCurlMultiP == NULL) + xmlrpc_faultf(envP, "Unable to create Curl multi manager for " + "synchronous RPCs"); + + if (envP->fault_occurred) + destroySyncCurlSession(transportP->syncCurlSessionP); + } + if (envP->fault_occurred) + transportP->syncCurlSessionLockP->destroy( + transportP->syncCurlSessionLockP); + } +} + + + +static void +unmakeSyncCurlSession(struct xmlrpc_client_transport * const transportP) { + + curlMulti_destroy(transportP->syncCurlMultiP); + + destroySyncCurlSession(transportP->syncCurlSessionP); + + transportP->syncCurlSessionLockP->destroy( + transportP->syncCurlSessionLockP); +} + + + +static void +create(xmlrpc_env * const envP, + int const flags ATTR_UNUSED, + const char * const appname ATTR_UNUSED, + const char * const appversion ATTR_UNUSED, + const void * const transportparmsP, + size_t const parm_size, + struct xmlrpc_client_transport ** const handlePP) { +/*---------------------------------------------------------------------------- + This does the 'create' operation for a Curl client transport. +-----------------------------------------------------------------------------*/ + const struct xmlrpc_curl_xportparms * const curlXportParmsP = + transportparmsP; + + struct xmlrpc_client_transport * transportP; + + MALLOCVAR(transportP); + if (transportP == NULL) + xmlrpc_faultf(envP, "Unable to allocate transport descriptor."); + else { + transportP->interruptP = NULL; + + transportP->asyncCurlMultiP = curlMulti_create(); + + if (transportP->asyncCurlMultiP == NULL) + xmlrpc_faultf(envP, "Unable to create Curl multi manager for " + "asynchronous RPCs"); + else { + getXportParms(envP, curlXportParmsP, parm_size, transportP); + + if (!envP->fault_occurred) { + makeSyncCurlSession(envP, transportP); + + if (envP->fault_occurred) + freeXportParms(transportP); + } + if (envP->fault_occurred) + curlMulti_destroy(transportP->asyncCurlMultiP); + } + if (envP->fault_occurred) + free(transportP); + } + *handlePP = transportP; +} + + + +static void +setInterrupt(struct xmlrpc_client_transport * const clientTransportP, + int * const interruptP) { + + clientTransportP->interruptP = interruptP; +} + + + +static void +assertNoOutstandingCurlWork(curlMulti * const curlMultiP) { + + xmlrpc_env env; + bool immediateWorkToDo; + int runningHandles; + + xmlrpc_env_init(&env); + + curlMulti_perform(&env, curlMultiP, &immediateWorkToDo, &runningHandles); + + /* We know the above was a no-op, since we're asserting that there + is no outstanding work. + */ + XMLRPC_ASSERT(!env.fault_occurred); + XMLRPC_ASSERT(!immediateWorkToDo); + XMLRPC_ASSERT(runningHandles == 0); + xmlrpc_env_clean(&env); +} + + + +static void +destroy(struct xmlrpc_client_transport * const clientTransportP) { +/*---------------------------------------------------------------------------- + This does the 'destroy' operation for a Curl client transport. + + An RPC is a reference to a client XML transport, so you may not + destroy a transport while RPCs are running. To ensure no + asynchronous RPCs are running, you must successfully execute the + transport 'finishAsync' method, with no interruptions or timeouts + allowed. To speed that up, you can set the transport's interrupt + flag to 1 first, which will make all outstanding RPCs fail + immediately. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT(clientTransportP != NULL); + + assertNoOutstandingCurlWork(clientTransportP->asyncCurlMultiP); + /* We know this is true because a condition of destroying the + transport is that there be no outstanding asynchronous RPCs. + */ + assertNoOutstandingCurlWork(clientTransportP->syncCurlMultiP); + /* This is because a condition of destroying the transport is + that no transport method be running. The only way a + synchronous RPC can be in progress is for the 'perform' method + to be running. + */ + + unmakeSyncCurlSession(clientTransportP); + + curlMulti_destroy(clientTransportP->asyncCurlMultiP); + + freeXportParms(clientTransportP); + + free(clientTransportP); +} + + + +static void +performCurlTransaction(xmlrpc_env * const envP, + curlTransaction * const curlTransactionP, + curlMulti * const curlMultiP, + int * const interruptP) { + + curlMulti_addHandle(envP, curlMultiP, + curlTransaction_curlSession(curlTransactionP)); + + /* Failure here just means something screwy in the multi manager; + Above does not even begin to perform the HTTP transaction + */ + + if (!envP->fault_occurred) { + xmlrpc_timespec const dummy = {0,0}; + + finishCurlMulti(envP, curlMultiP, timeout_no, dummy, interruptP); + + /* Failure here just means something screwy in the multi + manager; any failure of the HTTP transaction would have been + recorded in *curlTransactionP. + */ + + if (!envP->fault_occurred) { + /* Curl session completed OK. But did HTTP transaction + work? + */ + curlTransaction_getError(curlTransactionP, envP); + } + /* If the CURL transaction is still going, removing the handle + here aborts it. At least it's supposed to. From what I've + seen in the Curl code in 2007, I don't think it does. I + couldn't get Curl maintainers interested in the problem, + except to say, "If you're right, there's a bug." + */ + curlMulti_removeHandle(curlMultiP, + curlTransaction_curlSession(curlTransactionP)); + } +} + + + +static void +startRpc(xmlrpc_env * const envP, + rpc * const rpcP) { + + curlMulti_addHandle(envP, + rpcP->transportP->asyncCurlMultiP, + curlTransaction_curlSession(rpcP->curlTransactionP)); +} + + + +static curlt_finishFn finishRpcCurlTransaction; +static curlt_progressFn curlTransactionProgress; + + + +static void +createRpc(xmlrpc_env * const envP, + struct xmlrpc_client_transport * const clientTransportP, + CURL * const curlSessionP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block * const responseXmlP, + xmlrpc_transport_asynch_complete complete, + struct xmlrpc_call_info * const callInfoP, + rpc ** const rpcPP) { + + rpc * rpcP; + + MALLOCVAR(rpcP); + if (rpcP == NULL) + xmlrpc_faultf(envP, "Couldn't allocate memory for rpc object"); + else { + rpcP->transportP = clientTransportP; + rpcP->curlSessionP = curlSessionP; + rpcP->callInfoP = callInfoP; + rpcP->complete = complete; + rpcP->responseXmlP = responseXmlP; + + curlTransaction_create(envP, + curlSessionP, + serverP, + callXmlP, responseXmlP, + clientTransportP->userAgent, + &clientTransportP->curlSetupStuff, + rpcP, + complete ? &finishRpcCurlTransaction : NULL, + &curlTransactionProgress, + &rpcP->curlTransactionP); + if (!envP->fault_occurred) { + if (envP->fault_occurred) + curlTransaction_destroy(rpcP->curlTransactionP); + } + if (envP->fault_occurred) + free(rpcP); + } + *rpcPP = rpcP; +} + + + +static void +destroyRpc(rpc * const rpcP) { + + XMLRPC_ASSERT_PTR_OK(rpcP); + + curlTransaction_destroy(rpcP->curlTransactionP); + + free(rpcP); +} + + + +static void +performRpc(xmlrpc_env * const envP, + rpc * const rpcP, + curlMulti * const curlMultiP, + int * const interruptP) { + + performCurlTransaction(envP, rpcP->curlTransactionP, curlMultiP, + interruptP); +} + + + +static curlt_finishFn finishRpcCurlTransaction; + +static void +finishRpcCurlTransaction(xmlrpc_env * const envP ATTR_UNUSED, + void * const userContextP) { +/*---------------------------------------------------------------------------- + Handle the event that a Curl transaction for an asynchronous RPC has + completed on the Curl session identified by 'curlSessionP'. + + Tell the requester of the RPC the results. + + Remove the Curl session from its Curl multi manager and destroy the + Curl session, the XML response buffer, the Curl transaction, and the RPC. +-----------------------------------------------------------------------------*/ + rpc * const rpcP = userContextP; + curlTransaction * const curlTransactionP = rpcP->curlTransactionP; + struct xmlrpc_client_transport * const transportP = rpcP->transportP; + + curlMulti_removeHandle(transportP->asyncCurlMultiP, + curlTransaction_curlSession(curlTransactionP)); + + { + xmlrpc_env env; + + xmlrpc_env_init(&env); + + curlTransaction_getError(curlTransactionP, &env); + + rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env); + + xmlrpc_env_clean(&env); + } + + curl_easy_cleanup(rpcP->curlSessionP); + + XMLRPC_MEMBLOCK_FREE(char, rpcP->responseXmlP); + + destroyRpc(rpcP); +} + + + +static curlt_progressFn curlTransactionProgress; + +static void +curlTransactionProgress(void * const context, + bool * const abortP) { + + rpc * const rpcP = context; + + assert(rpcP); + + if (rpcP->transportP->interruptP) + *abortP = *rpcP->transportP->interruptP; + else + *abortP = false; +} + + + +static void +sendRequest(xmlrpc_env * const envP, + struct xmlrpc_client_transport * const clientTransportP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_transport_asynch_complete complete, + struct xmlrpc_call_info * const callInfoP) { +/*---------------------------------------------------------------------------- + Initiate an XML-RPC rpc asynchronously. Don't wait for it to go to + the server. + + Unless we return failure, we arrange to have complete() called when + the rpc completes. + + This does the 'send_request' operation for a Curl client transport. +-----------------------------------------------------------------------------*/ + rpc * rpcP; + xmlrpc_mem_block * responseXmlP; + + responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0); + if (!envP->fault_occurred) { + CURL * const curlSessionP = curl_easy_init(); + + if (curlSessionP == NULL) + xmlrpc_faultf(envP, "Could not create Curl session. " + "curl_easy_init() failed."); + else { + createRpc(envP, clientTransportP, curlSessionP, serverP, + callXmlP, responseXmlP, complete, callInfoP, + &rpcP); + + if (!envP->fault_occurred) { + startRpc(envP, rpcP); + + if (envP->fault_occurred) + destroyRpc(rpcP); + } + if (envP->fault_occurred) + curl_easy_cleanup(curlSessionP); + } + if (envP->fault_occurred) + XMLRPC_MEMBLOCK_FREE(char, responseXmlP); + } + /* If we're returning success, the user's eventual finish_asynch + call will destroy this RPC, Curl session, and response buffer + and remove the Curl session from the Curl multi manager. + (If we're returning failure, we didn't create any of those). + */ +} + + + +static void +finishAsynch( + struct xmlrpc_client_transport * const clientTransportP, + xmlrpc_timeoutType const timeoutType, + xmlrpc_timeout const timeout) { +/*---------------------------------------------------------------------------- + Wait for the Curl multi manager to finish the Curl transactions for + all outstanding RPCs and destroy those RPCs. + + But give up if a) too much time passes as defined by 'timeoutType' + and 'timeout'; or b) the transport client requests interruption + (i.e. the transport's interrupt flag becomes nonzero). Normally, a + signal must get our attention for us to notice the interrupt flag. + + This does the 'finish_asynch' operation for a Curl client transport. + + It would be cool to replace this with something analogous to the + Curl asynchronous interface: Have something like curl_multi_fdset() + that returns a bunch of file descriptors on which the user can wait + (along with possibly other file descriptors of his own) and + something like curl_multi_perform() to finish whatever RPCs are + ready to finish at that moment. The implementation would be little + more than wrapping curl_multi_fdset() and curl_multi_perform(). + + Note that the user can call this multiple times, due to timeouts, + but must eventually call it once with no timeout so he + knows that all the RPCs are finished. Either that or terminate the + process so it doesn't matter if RPCs are still going. +-----------------------------------------------------------------------------*/ + xmlrpc_env env; + + xmlrpc_timespec waitTimeoutTime; + /* The datetime after which we should quit waiting */ + + xmlrpc_env_init(&env); + + if (timeoutType == timeout_yes) { + xmlrpc_timespec waitStartTime; + xmlrpc_gettimeofday(&waitStartTime); + addMilliseconds(waitStartTime, timeout, &waitTimeoutTime); + } + + finishCurlMulti(&env, clientTransportP->asyncCurlMultiP, + timeoutType, waitTimeoutTime, + clientTransportP->interruptP); + + /* If the above fails, it is catastrophic, because it means there is + no way to complete outstanding Curl transactions and RPCs, and + no way to release their resources. + + We should at least expand this interface some day to push the + problem back up to the user, but for now we just do this Hail Mary + response. + + Note that a failure of finish_curlMulti() does not mean that + a session completed with an error or an RPC completed with an + error. Those things are reported up through the user's + xmlrpc_transport_asynch_complete routine. A failure here is + something that stopped us from calling that. + + Note that a timeout causes a successful completion, + but without finishing all the RPCs! + */ + + if (env.fault_occurred) + fprintf(stderr, "finishAsync() failed. Xmlrpc-c Curl transport " + "is now in an unknown state and may not be able to " + "continue functioning. Specifics of the failure: %s\n", + env.fault_string); + + xmlrpc_env_clean(&env); +} + + + +static void +call(xmlrpc_env * const envP, + struct xmlrpc_client_transport * const clientTransportP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block ** const responseXmlPP) { + + xmlrpc_mem_block * responseXmlP; + rpc * rpcP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(serverP); + XMLRPC_ASSERT_PTR_OK(callXmlP); + XMLRPC_ASSERT_PTR_OK(responseXmlPP); + + responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0); + if (!envP->fault_occurred) { + /* Only one RPC at a time can use a Curl session, so we have to + hold the lock as long as our RPC exists. + */ + lockSyncCurlSession(clientTransportP); + createRpc(envP, clientTransportP, clientTransportP->syncCurlSessionP, + serverP, + callXmlP, responseXmlP, + NULL, NULL, + &rpcP); + + if (!envP->fault_occurred) { + performRpc(envP, rpcP, clientTransportP->syncCurlMultiP, + clientTransportP->interruptP); + + *responseXmlPP = responseXmlP; + + destroyRpc(rpcP); + } + unlockSyncCurlSession(clientTransportP); + if (envP->fault_occurred) + XMLRPC_MEMBLOCK_FREE(char, responseXmlP); + } +} + + + +static void +setupGlobalConstants(xmlrpc_env * const envP) { +/*---------------------------------------------------------------------------- + See longwinded discussion of the global constant issue at the top of + this file. +-----------------------------------------------------------------------------*/ + initWindowsStuff(envP); + + if (!envP->fault_occurred) { + CURLcode rc; + + rc = curl_global_init(CURL_GLOBAL_ALL); + + if (rc != CURLE_OK) + xmlrpc_faultf(envP, "curl_global_init() failed with code %d", rc); + } +} + + + +static void +teardownGlobalConstants(void) { +/*---------------------------------------------------------------------------- + See longwinded discussionof the global constant issue at the top of + this file. +-----------------------------------------------------------------------------*/ + curl_global_cleanup(); + + termWindowsStuff(); +} + + + +struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops = { + &setupGlobalConstants, + &teardownGlobalConstants, + &create, + &destroy, + &sendRequest, + &call, + &finishAsynch, + &setInterrupt, +}; diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/expat.html b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/expat.html new file mode 100644 index 0000000..c555659 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/expat.html @@ -0,0 +1,93 @@ + + + + +expat + + + +

expat - XML Parser Toolkit

+ +

This is outdated stuff from the independently developed Expat which +was forked in 2001 to make the Xmlrpc-c embedded version. + +

Version 1.2

+ +

Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center +Ltd. Expat is freely available with source under a very liberal license (the MIT license).

+ +

This is a production version of expat. Relative to expat 1.1, it +adds support for parsing external DTDs and parameter entities. +Compiling with -DXML_DTD enables this support. There's a new +-p option for xmlwf which will cause it to process +external DTDs and parameter entities; this implies the -x +option. See the comment above XML_SetParamEntityParsing +in xmlparse.h for the API addition that enables this.

+ +

For Xmlrpc-c, we find no reason to exclude this function from the +library, and ifdefs make code harder to maintain, so we include the +function unconditionally. (i.e. -DXML_DTD does nothing). + +

Expat is an XML 1.0 parser +written in C. It aims to be fully conforming. It is currently not a +validating XML processor. The current production version of expat 1.X +can be downloaded from ftp://ftp.jclark.com/pub/xml/expat.zip.

+ +

Development of expat 2.0 is being handled by a team led by Clark +Cooper, hosted by sourceforge.net. See http://expat.sourceforge.net for +the latest on expat 2.0.

+ +

The directory xmltok contains a low-level library for +tokenizing XML. The interface is documented in +xmltok/xmltok.h.

+ +

The directory xmlparse contains an XML parser library +which is built on top of the xmltok library. The +interface is documented in xmlparse/xmlparse.h. The +directory sample contains a simple example program using +this interface; sample/build.bat is a batch file to build +the example using Visual C++.

+ +

The directory xmlwf contains the xmlwf +application, which uses the xmlparse library. The +arguments to xmlwf are one or more files which are each +to be checked for well-formedness. An option -d +dir can be specified; for each well-formed input +file the corresponding canonical XML will +be written to dir/f, where +f is the filename (without any path) of the +input file. A -x option will cause references to +external general entities to be processed. A -s option +will make documents that are not standalone cause an error (a document +is considered standalone if either it is intrinsically standalone +because it has no external subset and no references to parameter +entities in the internal subset or it is declared as standalone in the +XML declaration).

+ +

The bin directory contains Win32 executables. The +lib directory contains Win32 import libraries.

+ +

Answers to some frequently asked questions about expat can be found +in the expat +FAQ.

+ +

+ +
+ +James Clark + +
+ + + + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlparse/xmlparse.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlparse/xmlparse.c new file mode 100644 index 0000000..fc1c9f3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlparse/xmlparse.c @@ -0,0 +1,4658 @@ +/* +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +/* In 2001, this was part of the Expat package. We copied it into + Xmlrpc-c because it's easier on the user than making him get and + link Expat separately, and we don't expect to benefit from separate + maintenance of Expat. + + But we changed all the external symbols that in Expat are named + "XML_xxxx" to "xmlrpc_XML_xxxx" because people do link Xmlrpc-c + libraries into programs that also link Expat (a good example is + where an Apache module uses Xmlrpc-c). We don't want our names to + collide with Expat's. +*/ + +#include +#include + +#include "xmlrpc_config.h" +#include "c_util.h" +#include "girmath.h" +#include "mallocvar.h" +#include "xmlrpc-c/string_int.h" +#include "xmldef.h" +#include "xmlparse.h" + +static const char * +extractXmlSample(const char * const start, + const char * const end, + size_t const maximumLen) { + + size_t const len = MIN(maximumLen, (size_t)(end - start)); + + return xmlrpc_makePrintable_lp(start, len); +} + + + +#ifdef XML_UNICODE +#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX +#define XmlConvert XmlUtf16Convert +#define XmlGetInternalEncoding xmlrpc_XmlGetUtf16InternalEncoding +#define XmlGetInternalEncodingNS xmlrpc_XmlGetUtf16InternalEncodingNS +#define XmlEncode xmlrpc_XmlUtf16Encode +#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) +typedef unsigned short ICHAR; +#else +#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX +#define XmlConvert XmlUtf8Convert +#define XmlGetInternalEncoding xmlrpc_XmlGetUtf8InternalEncoding +#define XmlGetInternalEncodingNS xmlrpc_XmlGetUtf8InternalEncodingNS +#define XmlEncode xmlrpc_XmlUtf8Encode +#define MUST_CONVERT(enc, s) (!(enc)->isUtf8) +typedef char ICHAR; +#endif + + +#ifndef XML_NS + +#define XmlInitEncodingNS XmlInitEncoding +#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding +#undef XmlGetInternalEncodingNS +#define XmlGetInternalEncodingNS XmlGetInternalEncoding +#define XmlParseXmlDeclNS XmlParseXmlDecl + +#endif + +#ifdef XML_UNICODE_WCHAR_T +#define XML_T(x) L ## x +#else +#define XML_T(x) x +#endif + +/* Round up n to be a multiple of sz, where sz is a power of 2. */ +#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) + +#include "xmltok.h" +#include "xmlrole.h" + +typedef const XML_Char *KEY; + +typedef struct { + KEY name; +} NAMED; + +typedef struct { + NAMED **v; + size_t size; + size_t used; + size_t usedLim; +} HASH_TABLE; + +typedef struct { + NAMED **p; + NAMED **end; +} HASH_TABLE_ITER; + +#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ +#define INIT_DATA_BUF_SIZE 1024 +#define INIT_ATTS_SIZE 16 +#define INIT_BLOCK_SIZE 1024 +#define INIT_BUFFER_SIZE 1024 + +#define EXPAND_SPARE 24 + +typedef struct binding { + struct prefix *prefix; + struct binding *nextTagBinding; + struct binding *prevPrefixBinding; + const struct attribute_id *attId; + XML_Char *uri; + int uriLen; + int uriAlloc; +} BINDING; + +typedef struct prefix { + const XML_Char *name; + BINDING *binding; +} PREFIX; + +typedef struct { + const XML_Char *str; + const XML_Char *localPart; + int uriLen; +} TAG_NAME; + +typedef struct tag { + struct tag *parent; + const char *rawName; + int rawNameLength; + TAG_NAME name; + char *buf; + char *bufEnd; + BINDING *bindings; +} TAG; + +typedef struct { + const XML_Char *name; + const XML_Char *textPtr; + int textLen; + const XML_Char *systemId; + const XML_Char *base; + const XML_Char *publicId; + const XML_Char *notation; + char open; +} ENTITY; + +typedef struct block { + struct block *next; + int size; + XML_Char s[1]; +} BLOCK; + +typedef struct { + BLOCK *blocks; + BLOCK *freeBlocks; + const XML_Char *end; + XML_Char *ptr; + XML_Char *start; +} STRING_POOL; + +/* The XML_Char before the name is used to determine whether +an attribute has been specified. */ +typedef struct attribute_id { + XML_Char *name; + PREFIX *prefix; + char maybeTokenized; + char xmlns; +} ATTRIBUTE_ID; + +typedef struct { + const ATTRIBUTE_ID *id; + char isCdata; + const XML_Char *value; +} DEFAULT_ATTRIBUTE; + +typedef struct { + const XML_Char *name; + PREFIX *prefix; + const ATTRIBUTE_ID *idAtt; + int nDefaultAtts; + int allocDefaultAtts; + DEFAULT_ATTRIBUTE *defaultAtts; +} ELEMENT_TYPE; + +typedef struct { + HASH_TABLE generalEntities; + HASH_TABLE elementTypes; + HASH_TABLE attributeIds; + HASH_TABLE prefixes; + STRING_POOL pool; + int complete; + int standalone; + HASH_TABLE paramEntities; + PREFIX defaultPrefix; +} DTD; + +typedef struct open_internal_entity { + const char *internalEventPtr; + const char *internalEventEndPtr; + struct open_internal_entity *next; + ENTITY *entity; +} OPEN_INTERNAL_ENTITY; + +typedef void Processor(XML_Parser parser, + const char * const start, + const char * const end, + const char ** const endPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP); + + +#define poolStart(pool) ((pool)->start) +#define poolEnd(pool) ((pool)->ptr) +#define poolLength(pool) ((pool)->ptr - (pool)->start) +#define poolChop(pool) ((void)--(pool->ptr)) +#define poolLastChar(pool) (((pool)->ptr)[-1]) +#define poolDiscard(pool) ((pool)->ptr = (pool)->start) +#define poolFinish(pool) ((pool)->start = (pool)->ptr) +#define poolAppendChar(pool, c) \ + (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ + ? 0 \ + : ((*((pool)->ptr)++ = c), 1)) + +typedef struct { + /* The first member must be userData so that the XML_GetUserData macro works. */ + void *m_userData; + void *m_handlerArg; + char *m_buffer; + /* first character to be parsed */ + const char *m_bufferPtr; + /* past last character to be parsed */ + char *m_bufferEnd; + /* allocated end of buffer */ + const char *m_bufferLim; + long m_parseEndByteIndex; + const char *m_parseEndPtr; + XML_Char *m_dataBuf; + XML_Char *m_dataBufEnd; + XML_StartElementHandler m_startElementHandler; + XML_EndElementHandler m_endElementHandler; + XML_CharacterDataHandler m_characterDataHandler; + XML_ProcessingInstructionHandler m_processingInstructionHandler; + XML_CommentHandler m_commentHandler; + XML_StartCdataSectionHandler m_startCdataSectionHandler; + XML_EndCdataSectionHandler m_endCdataSectionHandler; + XML_DefaultHandler m_defaultHandler; + XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; + XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; + XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; + XML_NotationDeclHandler m_notationDeclHandler; + XML_ExternalParsedEntityDeclHandler m_externalParsedEntityDeclHandler; + XML_InternalParsedEntityDeclHandler m_internalParsedEntityDeclHandler; + XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; + XML_NotStandaloneHandler m_notStandaloneHandler; + XML_ExternalEntityRefHandler m_externalEntityRefHandler; + void *m_externalEntityRefHandlerArg; + XML_UnknownEncodingHandler m_unknownEncodingHandler; + const ENCODING *m_encoding; + INIT_ENCODING m_initEncoding; + const ENCODING *m_internalEncoding; + const XML_Char *m_protocolEncodingName; + int m_ns; + void *m_unknownEncodingMem; + void *m_unknownEncodingData; + void *m_unknownEncodingHandlerData; + void (*m_unknownEncodingRelease)(void *); + PROLOG_STATE m_prologState; + Processor *m_processor; + /* The next processor to run */ + enum XML_Error m_errorCode; + /* Explanation of the failure of the most recent call to Expat. + XML_ERROR_NONE means it didn't fail. This is redundant with + m_errorString if the latter is non-null. + The latter is newer and better. + */ + const char * m_errorString; + /* malloc'ed string describing the failure of the most recent call + to Expat. NULL means m_errorCode is the only error information + available. + */ + const char *m_eventPtr; + const char *m_eventEndPtr; + const char *m_positionPtr; + OPEN_INTERNAL_ENTITY *m_openInternalEntities; + int m_defaultExpandInternalEntities; + int m_tagLevel; + ENTITY *m_declEntity; + const XML_Char *m_declNotationName; + const XML_Char *m_declNotationPublicId; + ELEMENT_TYPE *m_declElementType; + ATTRIBUTE_ID *m_declAttributeId; + char m_declAttributeIsCdata; + char m_declAttributeIsId; + DTD m_dtd; + const XML_Char *m_curBase; + TAG *m_tagStack; + TAG *m_freeTagList; + BINDING *m_inheritedBindings; + BINDING *m_freeBindingList; + int m_attsSize; + int m_nSpecifiedAtts; + int m_idAttIndex; + ATTRIBUTE *m_atts; + POSITION m_position; + STRING_POOL m_tempPool; + STRING_POOL m_temp2Pool; + char *m_groupConnector; + unsigned m_groupSize; + int m_hadExternalDoctype; + XML_Char m_namespaceSeparator; + enum XML_ParamEntityParsing m_paramEntityParsing; + XML_Parser m_parentParser; +} Parser; + +#define userData (((Parser *)parser)->m_userData) +#define handlerArg (((Parser *)parser)->m_handlerArg) +#define startElementHandler (((Parser *)parser)->m_startElementHandler) +#define endElementHandler (((Parser *)parser)->m_endElementHandler) +#define characterDataHandler (((Parser *)parser)->m_characterDataHandler) +#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler) +#define commentHandler (((Parser *)parser)->m_commentHandler) +#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler) +#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler) +#define defaultHandler (((Parser *)parser)->m_defaultHandler) +#define startDoctypeDeclHandler (((Parser *)parser)->m_startDoctypeDeclHandler) +#define endDoctypeDeclHandler (((Parser *)parser)->m_endDoctypeDeclHandler) +#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler) +#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler) +#define externalParsedEntityDeclHandler (((Parser *)parser)->m_externalParsedEntityDeclHandler) +#define internalParsedEntityDeclHandler (((Parser *)parser)->m_internalParsedEntityDeclHandler) +#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler) +#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler) +#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler) +#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler) +#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg) +#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler) +#define initEncoding (((Parser *)parser)->m_initEncoding) +#define internalEncoding (((Parser *)parser)->m_internalEncoding) +#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem) +#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData) +#define unknownEncodingHandlerData \ + (((Parser *)parser)->m_unknownEncodingHandlerData) +#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease) +#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName) +#define ns (((Parser *)parser)->m_ns) +#define prologState (((Parser *)parser)->m_prologState) +#define processor (((Parser *)parser)->m_processor) +#define errorCode (((Parser *)parser)->m_errorCode) +#define errorString (((Parser *)parser)->m_errorString) +#define eventPtr (((Parser *)parser)->m_eventPtr) +#define eventEndPtr (((Parser *)parser)->m_eventEndPtr) +#define positionPtr (((Parser *)parser)->m_positionPtr) +#define position (((Parser *)parser)->m_position) +#define openInternalEntities (((Parser *)parser)->m_openInternalEntities) +#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities) +#define tagLevel (((Parser *)parser)->m_tagLevel) +#define buffer (((Parser *)parser)->m_buffer) +#define bufferPtr (((Parser *)parser)->m_bufferPtr) +#define bufferEnd (((Parser *)parser)->m_bufferEnd) +#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex) +#define parseEndPtr (((Parser *)parser)->m_parseEndPtr) +#define bufferLim (((Parser *)parser)->m_bufferLim) +#define dataBuf (((Parser *)parser)->m_dataBuf) +#define dataBufEnd (((Parser *)parser)->m_dataBufEnd) +#define dtd (((Parser *)parser)->m_dtd) +#define curBase (((Parser *)parser)->m_curBase) +#define declEntity (((Parser *)parser)->m_declEntity) +#define declNotationName (((Parser *)parser)->m_declNotationName) +#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId) +#define declElementType (((Parser *)parser)->m_declElementType) +#define declAttributeId (((Parser *)parser)->m_declAttributeId) +#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata) +#define declAttributeIsId (((Parser *)parser)->m_declAttributeIsId) +#define freeTagList (((Parser *)parser)->m_freeTagList) +#define freeBindingList (((Parser *)parser)->m_freeBindingList) +#define inheritedBindings (((Parser *)parser)->m_inheritedBindings) +#define tagStack (((Parser *)parser)->m_tagStack) +#define atts (((Parser *)parser)->m_atts) +#define attsSize (((Parser *)parser)->m_attsSize) +#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts) +#define idAttIndex (((Parser *)parser)->m_idAttIndex) +#define tempPool (((Parser *)parser)->m_tempPool) +#define temp2Pool (((Parser *)parser)->m_temp2Pool) +#define groupConnector (((Parser *)parser)->m_groupConnector) +#define groupSize (((Parser *)parser)->m_groupSize) +#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype) +#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator) +#define parentParser (((Parser *)parser)->m_parentParser) +#define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing) + + + +static +void poolInit(STRING_POOL *pool) +{ + pool->blocks = 0; + pool->freeBlocks = 0; + pool->start = 0; + pool->ptr = 0; + pool->end = 0; +} + +static +void poolClear(STRING_POOL *pool) +{ + if (!pool->freeBlocks) + pool->freeBlocks = pool->blocks; + else { + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + p->next = pool->freeBlocks; + pool->freeBlocks = p; + p = tem; + } + } + pool->blocks = 0; + pool->start = 0; + pool->ptr = 0; + pool->end = 0; +} + +static +void poolDestroy(STRING_POOL *pool) +{ + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + free(p); + p = tem; + } + pool->blocks = 0; + p = pool->freeBlocks; + while (p) { + BLOCK *tem = p->next; + free(p); + p = tem; + } + pool->freeBlocks = 0; + pool->ptr = 0; + pool->start = 0; + pool->end = 0; +} + +static +int poolGrow(STRING_POOL *pool) +{ + if (pool->freeBlocks) { + if (pool->start == 0) { + pool->blocks = pool->freeBlocks; + pool->freeBlocks = pool->freeBlocks->next; + pool->blocks->next = 0; + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + pool->ptr = pool->start; + return 1; + } + if (pool->end - pool->start < pool->freeBlocks->size) { + BLOCK *tem = pool->freeBlocks->next; + pool->freeBlocks->next = pool->blocks; + pool->blocks = pool->freeBlocks; + pool->freeBlocks = tem; + memcpy(pool->blocks->s, pool->start, + (pool->end - pool->start) * sizeof(XML_Char)); + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + return 1; + } + } + if (pool->blocks && pool->start == pool->blocks->s) { + int blockSize = (pool->end - pool->start)*2; + pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + + blockSize * sizeof(XML_Char)); + if (!pool->blocks) + return 0; + pool->blocks->size = blockSize; + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + blockSize; + } + else { + BLOCK *tem; + int blockSize = pool->end - pool->start; + if (blockSize < INIT_BLOCK_SIZE) + blockSize = INIT_BLOCK_SIZE; + else + blockSize *= 2; + tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); + if (!tem) + return 0; + tem->size = blockSize; + tem->next = pool->blocks; + pool->blocks = tem; + if (pool->ptr != pool->start) + memcpy(tem->s, pool->start, + (pool->ptr - pool->start) * sizeof(XML_Char)); + pool->ptr = tem->s + (pool->ptr - pool->start); + pool->start = tem->s; + pool->end = tem->s + blockSize; + } + return 1; +} + + + +static +XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end) +{ + if (!pool->ptr && !poolGrow(pool)) + return 0; + for (;;) { + XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); + if (ptr == end) + break; + if (!poolGrow(pool)) + return 0; + } + return pool->start; +} + +static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s) +{ + do { + if (!poolAppendChar(pool, *s)) + return 0; + } while (*s++); + s = pool->start; + poolFinish(pool); + return s; +} + +static const XML_Char * +poolCopyStringN(STRING_POOL *pool, + const XML_Char *s, + int n) +{ + if (!pool->ptr && !poolGrow(pool)) + return 0; + for (; n > 0; --n, s++) { + if (!poolAppendChar(pool, *s)) + return 0; + + } + s = pool->start; + poolFinish(pool); + return s; +} + +static +XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end) +{ + if (!poolAppend(pool, enc, ptr, end)) + return 0; + if (pool->ptr == pool->end && !poolGrow(pool)) + return 0; + *(pool->ptr)++ = 0; + return pool->start; +} + +#define INIT_SIZE 64 + +static +int keyeq(KEY s1, KEY s2) +{ + for (; *s1 == *s2; s1++, s2++) + if (*s1 == 0) + return 1; + return 0; +} + +static +unsigned long hash(KEY s) +{ + unsigned long h = 0; + while (*s) + h = (h << 5) + h + (unsigned char)*s++; + return h; +} + +static +NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize) +{ + size_t i; + if (table->size == 0) { + if (!createSize) + return 0; + table->v = calloc(INIT_SIZE, sizeof(NAMED *)); + if (!table->v) + return 0; + table->size = INIT_SIZE; + table->usedLim = INIT_SIZE / 2; + i = hash(name) & (table->size - 1); + } + else { + unsigned long h = hash(name); + for (i = h & (table->size - 1); + table->v[i]; + i == 0 ? i = table->size - 1 : --i) { + if (keyeq(name, table->v[i]->name)) + return table->v[i]; + } + if (!createSize) + return 0; + if (table->used == table->usedLim) { + /* check for overflow */ + size_t newSize = table->size * 2; + NAMED **newV = calloc(newSize, sizeof(NAMED *)); + if (!newV) + return 0; + for (i = 0; i < table->size; i++) + if (table->v[i]) { + size_t j; + for (j = hash(table->v[i]->name) & (newSize - 1); + newV[j]; + j == 0 ? j = newSize - 1 : --j) + ; + newV[j] = table->v[i]; + } + free(table->v); + table->v = newV; + table->size = newSize; + table->usedLim = newSize/2; + for (i = h & (table->size - 1); + table->v[i]; + i == 0 ? i = table->size - 1 : --i) + ; + } + } + table->v[i] = calloc(1, createSize); + if (!table->v[i]) + return 0; + table->v[i]->name = name; + (table->used)++; + return table->v[i]; +} + +static +void hashTableDestroy(HASH_TABLE *table) +{ + size_t i; + for (i = 0; i < table->size; i++) { + NAMED *p = table->v[i]; + if (p) + free(p); + } + if (table->v) + free(table->v); +} + +static +void hashTableInit(HASH_TABLE *p) +{ + p->size = 0; + p->usedLim = 0; + p->used = 0; + p->v = 0; +} + +static +void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) +{ + iter->p = table->v; + iter->end = iter->p + table->size; +} + +static +NAMED *hashTableIterNext(HASH_TABLE_ITER *iter) +{ + while (iter->p != iter->end) { + NAMED *tem = *(iter->p)++; + if (tem) + return tem; + } + return 0; +} + + + +static int dtdInit(DTD *p) +{ + poolInit(&(p->pool)); + hashTableInit(&(p->generalEntities)); + hashTableInit(&(p->elementTypes)); + hashTableInit(&(p->attributeIds)); + hashTableInit(&(p->prefixes)); + p->complete = 1; + p->standalone = 0; + hashTableInit(&(p->paramEntities)); + p->defaultPrefix.name = 0; + p->defaultPrefix.binding = 0; + return 1; +} + + + +static void dtdSwap(DTD *p1, DTD *p2) +{ + DTD tem; + memcpy(&tem, p1, sizeof(DTD)); + memcpy(p1, p2, sizeof(DTD)); + memcpy(p2, &tem, sizeof(DTD)); +} + + + + +static void dtdDestroy(DTD *p) +{ + HASH_TABLE_ITER iter; + hashTableIterInit(&iter, &(p->elementTypes)); + for (;;) { + ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!e) + break; + if (e->allocDefaultAtts != 0) + free(e->defaultAtts); + } + hashTableDestroy(&(p->generalEntities)); + hashTableDestroy(&(p->paramEntities)); + hashTableDestroy(&(p->elementTypes)); + hashTableDestroy(&(p->attributeIds)); + hashTableDestroy(&(p->prefixes)); + poolDestroy(&(p->pool)); +} + +static int copyEntityTable(HASH_TABLE *newTable, + STRING_POOL *newPool, + const HASH_TABLE *oldTable) +{ + HASH_TABLE_ITER iter; + const XML_Char *cachedOldBase = 0; + const XML_Char *cachedNewBase = 0; + + hashTableIterInit(&iter, oldTable); + + for (;;) { + ENTITY *newE; + const XML_Char *name; + const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(newPool, oldE->name); + if (!name) + return 0; + newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); + if (!newE) + return 0; + if (oldE->systemId) { + const XML_Char *tem = poolCopyString(newPool, oldE->systemId); + if (!tem) + return 0; + newE->systemId = tem; + if (oldE->base) { + if (oldE->base == cachedOldBase) + newE->base = cachedNewBase; + else { + cachedOldBase = oldE->base; + tem = poolCopyString(newPool, cachedOldBase); + if (!tem) + return 0; + cachedNewBase = newE->base = tem; + } + } + } + else { + const XML_Char *tem = + poolCopyStringN(newPool, oldE->textPtr, oldE->textLen); + if (!tem) + return 0; + newE->textPtr = tem; + newE->textLen = oldE->textLen; + } + if (oldE->notation) { + const XML_Char *tem = poolCopyString(newPool, oldE->notation); + if (!tem) + return 0; + newE->notation = tem; + } + } + return 1; +} + + + +/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise. +The new DTD has already been initialized. */ + +static int dtdCopy(DTD *newDtd, const DTD *oldDtd) +{ + HASH_TABLE_ITER iter; + + /* Copy the prefix table. */ + + hashTableIterInit(&iter, &(oldDtd->prefixes)); + for (;;) { + const XML_Char *name; + const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); + if (!oldP) + break; + name = poolCopyString(&(newDtd->pool), oldP->name); + if (!name) + return 0; + if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) + return 0; + } + + hashTableIterInit(&iter, &(oldDtd->attributeIds)); + + /* Copy the attribute id table. */ + + for (;;) { + ATTRIBUTE_ID *newA; + const XML_Char *name; + const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); + + if (!oldA) + break; + /* Remember to allocate the scratch byte before the name. */ + if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) + return 0; + name = poolCopyString(&(newDtd->pool), oldA->name); + if (!name) + return 0; + ++name; + newA = (ATTRIBUTE_ID *) + lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID)); + if (!newA) + return 0; + newA->maybeTokenized = oldA->maybeTokenized; + if (oldA->prefix) { + newA->xmlns = oldA->xmlns; + if (oldA->prefix == &oldDtd->defaultPrefix) + newA->prefix = &newDtd->defaultPrefix; + else + newA->prefix = (PREFIX *) + lookup(&(newDtd->prefixes), oldA->prefix->name, 0); + } + } + + /* Copy the element type table. */ + + hashTableIterInit(&iter, &(oldDtd->elementTypes)); + + for (;;) { + int i; + ELEMENT_TYPE *newE; + const XML_Char *name; + const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(&(newDtd->pool), oldE->name); + if (!name) + return 0; + newE = (ELEMENT_TYPE *) + lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE)); + if (!newE) + return 0; + if (oldE->nDefaultAtts) { + newE->defaultAtts = (DEFAULT_ATTRIBUTE *) + malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); + if (!newE->defaultAtts) + return 0; + } + if (oldE->idAtt) + newE->idAtt = (ATTRIBUTE_ID *) + lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); + newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; + if (oldE->prefix) + newE->prefix = (PREFIX *) + lookup(&(newDtd->prefixes), oldE->prefix->name, 0); + for (i = 0; i < newE->nDefaultAtts; i++) { + newE->defaultAtts[i].id = (ATTRIBUTE_ID *) + lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); + newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; + if (oldE->defaultAtts[i].value) { + newE->defaultAtts[i].value = + poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); + if (!newE->defaultAtts[i].value) + return 0; + } + else + newE->defaultAtts[i].value = 0; + } + } + + /* Copy the entity tables. */ + if (!copyEntityTable(&(newDtd->generalEntities), + &(newDtd->pool), + &(oldDtd->generalEntities))) + return 0; + + if (!copyEntityTable(&(newDtd->paramEntities), + &(newDtd->pool), + &(oldDtd->paramEntities))) + return 0; + + newDtd->complete = oldDtd->complete; + newDtd->standalone = oldDtd->standalone; + return 1; +} + + + +static +int addBinding(XML_Parser parser, + PREFIX *prefix, + const ATTRIBUTE_ID *attId, + const XML_Char *uri, + BINDING **bindingsPtr) +{ + BINDING *b; + int len; + for (len = 0; uri[len]; len++) + ; + if (namespaceSeparator) + len++; + if (freeBindingList) { + b = freeBindingList; + if (len > b->uriAlloc) { + b->uri = realloc(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (!b->uri) + return 0; + b->uriAlloc = len + EXPAND_SPARE; + } + freeBindingList = b->nextTagBinding; + } + else { + b = malloc(sizeof(BINDING)); + if (!b) + return 0; + b->uri = malloc(sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (!b->uri) { + free(b); + return 0; + } + b->uriAlloc = len + EXPAND_SPARE; + } + b->uriLen = len; + memcpy(b->uri, uri, len * sizeof(XML_Char)); + if (namespaceSeparator) + b->uri[len - 1] = namespaceSeparator; + b->prefix = prefix; + b->attId = attId; + b->prevPrefixBinding = prefix->binding; + if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix) + prefix->binding = 0; + else + prefix->binding = b; + b->nextTagBinding = *bindingsPtr; + *bindingsPtr = b; + if (startNamespaceDeclHandler) + startNamespaceDeclHandler(handlerArg, prefix->name, + prefix->binding ? uri : 0); + return 1; +} + + + +#define CONTEXT_SEP XML_T('\f') + +static +const XML_Char *getContext(XML_Parser parser) +{ + HASH_TABLE_ITER iter; + int needSep = 0; + + if (dtd.defaultPrefix.binding) { + int i; + int len; + if (!poolAppendChar(&tempPool, XML_T('='))) + return 0; + len = dtd.defaultPrefix.binding->uriLen; + if (namespaceSeparator != XML_T('\0')) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i])) + return 0; + needSep = 1; + } + + hashTableIterInit(&iter, &(dtd.prefixes)); + for (;;) { + int i; + int len; + const XML_Char *s; + PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); + if (!prefix) + break; + if (!prefix->binding) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return 0; + for (s = prefix->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return 0; + if (!poolAppendChar(&tempPool, XML_T('='))) + return 0; + len = prefix->binding->uriLen; + if (namespaceSeparator != XML_T('\0')) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) + return 0; + needSep = 1; + } + + + hashTableIterInit(&iter, &(dtd.generalEntities)); + for (;;) { + const XML_Char *s; + ENTITY *e = (ENTITY *)hashTableIterNext(&iter); + if (!e) + break; + if (!e->open) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return 0; + for (s = e->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return 0; + needSep = 1; + } + + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return 0; + return tempPool.start; +} + +static +int setContext(XML_Parser parser, const XML_Char *context) +{ + const XML_Char *s = context; + + while (*context != XML_T('\0')) { + if (*s == CONTEXT_SEP || *s == XML_T('\0')) { + ENTITY *e; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return 0; + e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0); + if (e) + e->open = 1; + if (*s != XML_T('\0')) + s++; + context = s; + poolDiscard(&tempPool); + } + else if (*s == '=') { + PREFIX *prefix; + if (poolLength(&tempPool) == 0) + prefix = &dtd.defaultPrefix; + else { + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return 0; + prefix = (PREFIX *) + lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX)); + if (!prefix) + return 0; + if (prefix->name == poolStart(&tempPool)) { + prefix->name = poolCopyString(&dtd.pool, prefix->name); + if (!prefix->name) + return 0; + } + poolDiscard(&tempPool); + } + for (context = s + 1; + *context != CONTEXT_SEP && *context != XML_T('\0'); + ++context) + if (!poolAppendChar(&tempPool, *context)) + return 0; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return 0; + if (!addBinding(parser, prefix, 0, poolStart(&tempPool), + &inheritedBindings)) + return 0; + poolDiscard(&tempPool); + if (*context != XML_T('\0')) + ++context; + s = context; + } + else { + if (!poolAppendChar(&tempPool, *s)) + return 0; + s++; + } + } + return 1; +} + + + +static void +normalizeLines(XML_Char *s) +{ + XML_Char *p; + for (;; s++) { + if (*s == XML_T('\0')) + return; + if (*s == 0xD) + break; + } + p = s; + do { + if (*s == 0xD) { + *p++ = 0xA; + if (*++s == 0xA) + s++; + } + else + *p++ = *s++; + } while (*s); + *p = XML_T('\0'); +} + + + +static void +reportDefault(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char * const startArg, + const char * const end) { + + Parser * const parser = (Parser *)xmlParserP; + + const char * s; + + s = startArg; + + if (MUST_CONVERT(enc, s)) { + const char **eventPP; + const char **eventEndPP; + + if (enc == parser->m_encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + do { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + *eventPP = s; + } while (s != end); + } else + defaultHandler(handlerArg, (XML_Char *)s, + (XML_Char *)end - (XML_Char *)s); +} + + + +static int +reportProcessingInstruction(XML_Parser parser, + const ENCODING *enc, + const char *start, + const char *end) +{ + const XML_Char *target; + XML_Char *data; + const char *tem; + if (!processingInstructionHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); + return 1; + } + start += enc->minBytesPerChar * 2; + tem = start + XmlNameLength(enc, start); + target = poolStoreString(&tempPool, enc, start, tem); + if (!target) + return 0; + poolFinish(&tempPool); + data = poolStoreString(&tempPool, enc, + XmlSkipS(enc, tem), + end - enc->minBytesPerChar*2); + if (!data) + return 0; + normalizeLines(data); + processingInstructionHandler(handlerArg, target, data); + poolClear(&tempPool); + return 1; +} + +static int +reportComment(XML_Parser parser, + const ENCODING *enc, + const char *start, + const char *end) +{ + XML_Char *data; + if (!commentHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); + return 1; + } + data = poolStoreString(&tempPool, + enc, + start + enc->minBytesPerChar * 4, + end - enc->minBytesPerChar * 3); + if (!data) + return 0; + normalizeLines(data); + commentHandler(handlerArg, data); + poolClear(&tempPool); + return 1; +} + + + +static enum XML_Error +handleUnknownEncoding(XML_Parser const xmlParserP, + const XML_Char * const encodingName) { + + Parser * const parser = (Parser *) xmlParserP; + + if (unknownEncodingHandler) { + XML_Encoding info; + int i; + for (i = 0; i < 256; i++) + info.map[i] = -1; + info.convert = 0; + info.data = 0; + info.release = 0; + if (unknownEncodingHandler(unknownEncodingHandlerData, + encodingName, &info)) { + ENCODING *enc; + unknownEncodingMem = malloc(xmlrpc_XmlSizeOfUnknownEncoding()); + if (!unknownEncodingMem) { + if (info.release) + info.release(info.data); + return XML_ERROR_NO_MEMORY; + } + enc = (ns + ? xmlrpc_XmlInitUnknownEncodingNS + : xmlrpc_XmlInitUnknownEncoding)(unknownEncodingMem, + info.map, + info.convert, + info.data); + if (enc) { + unknownEncodingData = info.data; + unknownEncodingRelease = info.release; + parser->m_encoding = enc; + return XML_ERROR_NONE; + } + } + if (info.release) + info.release(info.data); + } + return XML_ERROR_UNKNOWN_ENCODING; +} + + + +static enum XML_Error +initializeEncoding(XML_Parser const xmlParserP) { + + Parser * const parser = (Parser *) xmlParserP; + + const char *s; +#ifdef XML_UNICODE + char encodingBuf[128]; + if (!protocolEncodingName) + s = 0; + else { + int i; + for (i = 0; protocolEncodingName[i]; i++) { + if (i == sizeof(encodingBuf) - 1 + || (protocolEncodingName[i] & ~0x7f) != 0) { + encodingBuf[0] = '\0'; + break; + } + encodingBuf[i] = (char)protocolEncodingName[i]; + } + encodingBuf[i] = '\0'; + s = encodingBuf; + } +#else + s = protocolEncodingName; +#endif + if ((ns ? xmlrpc_XmlInitEncodingNS : xmlrpc_XmlInitEncoding)( + &parser->m_initEncoding, &parser->m_encoding, s)) + return XML_ERROR_NONE; + return handleUnknownEncoding(xmlParserP, protocolEncodingName); +} + + + +static enum XML_Error +processXmlDecl(XML_Parser const xmlParserP, + int const isGeneralTextEntity, + const char * const s, + const char * const next) { + + Parser * const parser = (Parser *) xmlParserP; + + const char *encodingName = 0; + const ENCODING *newEncoding = 0; + const char *version; + int standalone = -1; + if (!(ns + ? xmlrpc_XmlParseXmlDeclNS + : xmlrpc_XmlParseXmlDecl)(isGeneralTextEntity, + parser->m_encoding, + s, + next, + &eventPtr, + &version, + &encodingName, + &newEncoding, + &standalone)) + return XML_ERROR_SYNTAX; + if (!isGeneralTextEntity && standalone == 1) { + dtd.standalone = 1; + if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; + } + if (defaultHandler) + reportDefault(xmlParserP, parser->m_encoding, s, next); + if (!protocolEncodingName) { + if (newEncoding) { + if (newEncoding->minBytesPerChar != + parser->m_encoding->minBytesPerChar) { + eventPtr = encodingName; + return XML_ERROR_INCORRECT_ENCODING; + } + parser->m_encoding = newEncoding; + } + else if (encodingName) { + enum XML_Error result; + const XML_Char * s = + poolStoreString(&tempPool, + parser->m_encoding, + encodingName, + encodingName + + XmlNameLength(parser->m_encoding, + encodingName)); + if (!s) + return XML_ERROR_NO_MEMORY; + result = handleUnknownEncoding(xmlParserP, s); + poolDiscard(&tempPool); + if (result == XML_ERROR_UNKNOWN_ENCODING) + eventPtr = encodingName; + return result; + } + } + return XML_ERROR_NONE; +} + + + +static ATTRIBUTE_ID * +getAttributeId(XML_Parser parser, + const ENCODING *enc, + const char *start, + const char *end) +{ + ATTRIBUTE_ID *id; + const XML_Char *name; + if (!poolAppendChar(&dtd.pool, XML_T('\0'))) + return 0; + name = poolStoreString(&dtd.pool, enc, start, end); + if (!name) + return 0; + ++name; + id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID)); + if (!id) + return 0; + if (id->name != name) + poolDiscard(&dtd.pool); + else { + poolFinish(&dtd.pool); + if (!ns) + ; + else if (name[0] == 'x' + && name[1] == 'm' + && name[2] == 'l' + && name[3] == 'n' + && name[4] == 's' + && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { + if (name[5] == '\0') + id->prefix = &dtd.defaultPrefix; + else + id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX)); + id->xmlns = 1; + } + else { + int i; + for (i = 0; name[i]; i++) { + if (name[i] == XML_T(':')) { + int j; + for (j = 0; j < i; j++) { + if (!poolAppendChar(&dtd.pool, name[j])) + return 0; + } + if (!poolAppendChar(&dtd.pool, XML_T('\0'))) + return 0; + id->prefix = (PREFIX *) + lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); + if (id->prefix->name == poolStart(&dtd.pool)) + poolFinish(&dtd.pool); + else + poolDiscard(&dtd.pool); + break; + } + } + } + } + return id; +} + +static +void normalizePublicId(XML_Char *publicId) +{ + XML_Char *p = publicId; + XML_Char *s; + for (s = publicId; *s; s++) { + switch (*s) { + case 0x20: + case 0xD: + case 0xA: + if (p != publicId && p[-1] != 0x20) + *p++ = 0x20; + break; + default: + *p++ = *s; + } + } + if (p != publicId && p[-1] == 0x20) + --p; + *p = XML_T('\0'); +} + + + +static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) +{ + const XML_Char *name; + for (name = elementType->name; *name; name++) { + if (*name == XML_T(':')) { + PREFIX *prefix; + const XML_Char *s; + for (s = elementType->name; s != name; s++) { + if (!poolAppendChar(&dtd.pool, *s)) + return 0; + } + if (!poolAppendChar(&dtd.pool, XML_T('\0'))) + return 0; + prefix = (PREFIX *) + lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); + if (!prefix) + return 0; + if (prefix->name == poolStart(&dtd.pool)) + poolFinish(&dtd.pool); + else + poolDiscard(&dtd.pool); + elementType->prefix = prefix; + + } + } + return 1; +} + + + +static enum XML_Error +appendAttributeValue(XML_Parser const xmlParserP, + const ENCODING * const enc, + int const isCdata, + const char * const ptrArg, + const char * const end, + STRING_POOL * const pool) { + + Parser * const parser = (Parser *) xmlParserP; + + const char * ptr; + + ptr = ptrArg; + + for (;;) { + const char *next; + int tok = XmlAttributeValueTok(enc, ptr, end, &next); + switch (tok) { + case XML_TOK_NONE: + return XML_ERROR_NONE; + case XML_TOK_INVALID: + if (enc == parser->m_encoding) + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (enc == parser->m_encoding) + eventPtr = ptr; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, ptr); + if (n < 0) { + if (enc == parser->m_encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + if (!isCdata + && n == 0x20 /* space */ + && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == parser->m_encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + for (i = 0; i < n; i++) { + if (!poolAppendChar(pool, buf[i])) + return XML_ERROR_NO_MEMORY; + } + } + break; + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, ptr, next)) + return XML_ERROR_NO_MEMORY; + break; + break; + case XML_TOK_TRAILING_CR: + next = ptr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_ATTRIBUTE_VALUE_S: + case XML_TOK_DATA_NEWLINE: + if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + if (!poolAppendChar(pool, 0x20)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + XML_Char ch = XmlPredefinedEntityName(enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (!poolAppendChar(pool, ch)) + return XML_ERROR_NO_MEMORY; + break; + } + name = poolStoreString(&temp2Pool, enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); + poolDiscard(&temp2Pool); + if (!entity) { + if (dtd.complete) { + if (enc == parser->m_encoding) + eventPtr = ptr; + return XML_ERROR_UNDEFINED_ENTITY; + } + } + else if (entity->open) { + if (enc == parser->m_encoding) + eventPtr = ptr; + return XML_ERROR_RECURSIVE_ENTITY_REF; + } + else if (entity->notation) { + if (enc == parser->m_encoding) + eventPtr = ptr; + return XML_ERROR_BINARY_ENTITY_REF; + } + else if (!entity->textPtr) { + if (enc == parser->m_encoding) + eventPtr = ptr; + return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; + } + else { + enum XML_Error result; + const XML_Char *textEnd = entity->textPtr + entity->textLen; + entity->open = 1; + result = appendAttributeValue(xmlParserP, internalEncoding, + isCdata, (char *)entity->textPtr, + (char *)textEnd, pool); + entity->open = 0; + if (result) + return result; + } + } + break; + default: + abort(); + } + ptr = next; + } + /* not reached */ +} + + + +static enum XML_Error +storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, + const char *ptr, const char *end, + STRING_POOL *pool) +{ + enum XML_Error result = + appendAttributeValue(parser, enc, isCdata, ptr, end, pool); + if (result) + return result; + if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) + poolChop(pool); + if (!poolAppendChar(pool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + return XML_ERROR_NONE; +} + + + +static +enum XML_Error +storeEntityValue(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char * const entityTextPtrArg, + const char * const entityTextEnd) { + + Parser * const parser = (Parser *) xmlParserP; + + STRING_POOL * const pool = &(dtd.pool); + const char * entityTextPtr; + + entityTextPtr = entityTextPtrArg; + + for (;;) { + const char * next; + int tok; + + tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: + if (parentParser || enc != parser->m_encoding) { + enum XML_Error result; + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&tempPool, enc, + entityTextPtr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0); + poolDiscard(&tempPool); + if (!entity) { + if (enc == parser->m_encoding) + eventPtr = entityTextPtr; + return XML_ERROR_UNDEFINED_ENTITY; + } + if (entity->open) { + if (enc == parser->m_encoding) + eventPtr = entityTextPtr; + return XML_ERROR_RECURSIVE_ENTITY_REF; + } + if (entity->systemId) { + if (enc == parser->m_encoding) + eventPtr = entityTextPtr; + return XML_ERROR_PARAM_ENTITY_REF; + } + entity->open = 1; + result = storeEntityValue(parser, + internalEncoding, + (char *)entity->textPtr, + (char *)(entity->textPtr + entity->textLen)); + entity->open = 0; + if (result) + return result; + break; + } + eventPtr = entityTextPtr; + return XML_ERROR_SYNTAX; + case XML_TOK_NONE: + return XML_ERROR_NONE; + case XML_TOK_ENTITY_REF: + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, entityTextPtr, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_TRAILING_CR: + next = entityTextPtr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_DATA_NEWLINE: + if (pool->end == pool->ptr && !poolGrow(pool)) + return XML_ERROR_NO_MEMORY; + *(pool->ptr)++ = 0xA; + break; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, entityTextPtr); + if (n < 0) { + if (enc == parser->m_encoding) + eventPtr = entityTextPtr; + return XML_ERROR_BAD_CHAR_REF; + } + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == parser->m_encoding) + eventPtr = entityTextPtr; + return XML_ERROR_BAD_CHAR_REF; + } + for (i = 0; i < n; i++) { + if (pool->end == pool->ptr && !poolGrow(pool)) + return XML_ERROR_NO_MEMORY; + *(pool->ptr)++ = buf[i]; + } + } + break; + case XML_TOK_PARTIAL: + if (enc == parser->m_encoding) + eventPtr = entityTextPtr; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_INVALID: + if (enc == parser->m_encoding) + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + default: + abort(); + } + entityTextPtr = next; + } + /* not reached */ +} + + + +static int +defineAttribute(ELEMENT_TYPE *type, + ATTRIBUTE_ID *attId, + int isCdata, + int isId, + const XML_Char *value) +{ + DEFAULT_ATTRIBUTE *att; + if (value || isId) { + /* The handling of default attributes gets messed up if we have + a default which duplicates a non-default. */ + int i; + for (i = 0; i < type->nDefaultAtts; i++) + if (attId == type->defaultAtts[i].id) + return 1; + if (isId && !type->idAtt && !attId->xmlns) + type->idAtt = attId; + } + if (type->nDefaultAtts == type->allocDefaultAtts) { + if (type->allocDefaultAtts == 0) { + type->allocDefaultAtts = 8; + type->defaultAtts = + malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); + } + else { + type->allocDefaultAtts *= 2; + type->defaultAtts = + realloc(type->defaultAtts, + type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); + } + if (!type->defaultAtts) + return 0; + } + att = type->defaultAtts + type->nDefaultAtts; + att->id = attId; + att->value = value; + att->isCdata = isCdata; + if (!isCdata) + attId->maybeTokenized = 1; + type->nDefaultAtts += 1; + return 1; +} + + + +/* If tagNamePtr is non-null, build a real list of attributes, +otherwise just check the attributes for well-formedness. */ + +static enum XML_Error +storeAtts(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char * const attStr, + TAG_NAME * const tagNamePtr, + BINDING ** const bindingsPtr) { + + Parser * const parser = (Parser *)xmlParserP; + + ELEMENT_TYPE *elementType = 0; + int nDefaultAtts = 0; + const XML_Char ** appAtts; + /* the attribute list to pass to the application */ + int attIndex = 0; + int i; + int n; + int nPrefixes = 0; + BINDING *binding; + const XML_Char *localPart; + + /* lookup the element type name */ + if (tagNamePtr) { + elementType = (ELEMENT_TYPE *) + lookup(&dtd.elementTypes, tagNamePtr->str, 0); + if (!elementType) { + tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str); + if (!tagNamePtr->str) + return XML_ERROR_NO_MEMORY; + elementType = (ELEMENT_TYPE *) + lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE)); + if (!elementType) + return XML_ERROR_NO_MEMORY; + if (ns && !setElementTypePrefix(xmlParserP, elementType)) + return XML_ERROR_NO_MEMORY; + } + nDefaultAtts = elementType->nDefaultAtts; + } + /* get the attributes from the tokenizer */ + n = XmlGetAttributes(enc, attStr, attsSize, atts); + if (n + nDefaultAtts > attsSize) { + int oldAttsSize = attsSize; + attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; + atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE)); + if (!atts) + return XML_ERROR_NO_MEMORY; + if (n > oldAttsSize) + XmlGetAttributes(enc, attStr, n, atts); + } + appAtts = (const XML_Char **)atts; + for (i = 0; i < n; i++) { + /* add the name and value to the attribute list */ + ATTRIBUTE_ID *attId = getAttributeId(xmlParserP, enc, atts[i].name, + atts[i].name + + XmlNameLength(enc, atts[i].name)); + if (!attId) + return XML_ERROR_NO_MEMORY; + /* detect duplicate attributes */ + if ((attId->name)[-1]) { + if (enc == parser->m_encoding) + eventPtr = atts[i].name; + return XML_ERROR_DUPLICATE_ATTRIBUTE; + } + (attId->name)[-1] = 1; + appAtts[attIndex++] = attId->name; + if (!atts[i].normalized) { + enum XML_Error result; + int isCdata = 1; + + /* figure out whether declared as other than CDATA */ + if (attId->maybeTokenized) { + int j; + for (j = 0; j < nDefaultAtts; j++) { + if (attId == elementType->defaultAtts[j].id) { + isCdata = elementType->defaultAtts[j].isCdata; + break; + } + } + } + + /* normalize the attribute value */ + result = storeAttributeValue(xmlParserP, enc, isCdata, + atts[i].valuePtr, atts[i].valueEnd, + &tempPool); + if (result) + return result; + if (tagNamePtr) { + appAtts[attIndex] = poolStart(&tempPool); + poolFinish(&tempPool); + } + else + poolDiscard(&tempPool); + } + else if (tagNamePtr) { + /* the value did not need normalizing */ + appAtts[attIndex] = + poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd); + if (appAtts[attIndex] == 0) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + } + /* handle prefixed attribute names */ + if (attId->prefix && tagNamePtr) { + if (attId->xmlns) { + /* deal with namespace declarations here */ + if (!addBinding(xmlParserP, attId->prefix, attId, appAtts[attIndex], + bindingsPtr)) + return XML_ERROR_NO_MEMORY; + --attIndex; + } + else { + /* deal with other prefixed names later */ + attIndex++; + nPrefixes++; + (attId->name)[-1] = 2; + } + } + else + attIndex++; + } + if (tagNamePtr) { + int j; + nSpecifiedAtts = attIndex; + if (elementType->idAtt && (elementType->idAtt->name)[-1]) { + for (i = 0; i < attIndex; i += 2) + if (appAtts[i] == elementType->idAtt->name) { + idAttIndex = i; + break; + } + } + else + idAttIndex = -1; + /* do attribute defaulting */ + for (j = 0; j < nDefaultAtts; j++) { + const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j; + if (!(da->id->name)[-1] && da->value) { + if (da->id->prefix) { + if (da->id->xmlns) { + if (!addBinding(xmlParserP, da->id->prefix, da->id, da->value, + bindingsPtr)) + return XML_ERROR_NO_MEMORY; + } + else { + (da->id->name)[-1] = 2; + nPrefixes++; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + else { + (da->id->name)[-1] = 1; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + } + appAtts[attIndex] = 0; + } + i = 0; + if (nPrefixes) { + /* expand prefixed attribute names */ + for (; i < attIndex; i += 2) { + if (appAtts[i][-1] == 2) { + ATTRIBUTE_ID *id; + ((XML_Char *)(appAtts[i]))[-1] = 0; + id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0); + if (id->prefix->binding) { + int j; + const BINDING *b = id->prefix->binding; + const XML_Char *s = appAtts[i]; + for (j = 0; j < b->uriLen; j++) { + if (!poolAppendChar(&tempPool, b->uri[j])) + return XML_ERROR_NO_MEMORY; + } + while (*s++ != ':') + ; + do { + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + } while (*s++); + appAtts[i] = poolStart(&tempPool); + poolFinish(&tempPool); + } + if (!--nPrefixes) + break; + } + else + ((XML_Char *)(appAtts[i]))[-1] = 0; + } + } + /* clear the flags that say whether attributes were specified */ + for (; i < attIndex; i += 2) + ((XML_Char *)(appAtts[i]))[-1] = 0; + if (!tagNamePtr) + return XML_ERROR_NONE; + for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) + binding->attId->name[-1] = 0; + /* expand the element type name */ + if (elementType->prefix) { + binding = elementType->prefix->binding; + if (!binding) + return XML_ERROR_NONE; + localPart = tagNamePtr->str; + while (*localPart++ != XML_T(':')) + ; + } + else if (dtd.defaultPrefix.binding) { + binding = dtd.defaultPrefix.binding; + localPart = tagNamePtr->str; + } + else + return XML_ERROR_NONE; + tagNamePtr->localPart = localPart; + tagNamePtr->uriLen = binding->uriLen; + for (i = 0; localPart[i++];) + ; + n = i + binding->uriLen; + if (n > binding->uriAlloc) { + TAG *p; + XML_Char *uri = malloc((n + EXPAND_SPARE) * sizeof(XML_Char)); + if (!uri) + return XML_ERROR_NO_MEMORY; + binding->uriAlloc = n + EXPAND_SPARE; + memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); + for (p = tagStack; p; p = p->parent) + if (p->name.str == binding->uri) + p->name.str = uri; + free(binding->uri); + binding->uri = uri; + } + memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char)); + tagNamePtr->str = binding->uri; + return XML_ERROR_NONE; +} + + + +static Processor epilogProcessor; + +static void +epilogProcessor(XML_Parser const xmlParserP, + const char * const startArg, + const char * const end, + const char ** const nextPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + const char * s; + + *errorP = NULL; + + s = startArg; + + processor = epilogProcessor; + eventPtr = s; + for (;;) { + const char *next; + int tok = XmlPrologTok(parser->m_encoding, s, end, &next); + eventEndPtr = next; + switch (tok) { + case -XML_TOK_PROLOG_S: + if (defaultHandler) { + eventEndPtr = end; + reportDefault(xmlParserP, parser->m_encoding, s, end); + } + /* fall through */ + case XML_TOK_NONE: + if (nextPtr) + *nextPtr = end; + *errorCodeP = XML_ERROR_NONE; + return; + case XML_TOK_PROLOG_S: + if (defaultHandler) + reportDefault(xmlParserP, parser->m_encoding, s, next); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(xmlParserP, parser->m_encoding, + s, next)) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + break; + case XML_TOK_COMMENT: + if (!reportComment(xmlParserP, parser->m_encoding, s, next)) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + break; + case XML_TOK_INVALID: + eventPtr = next; + *errorCodeP = XML_ERROR_INVALID_TOKEN; + return; + case XML_TOK_PARTIAL: + if (nextPtr) { + *nextPtr = s; + *errorCodeP = XML_ERROR_NONE; + } else + *errorCodeP = XML_ERROR_UNCLOSED_TOKEN; + return; + case XML_TOK_PARTIAL_CHAR: + if (nextPtr) { + *nextPtr = s; + *errorCodeP = XML_ERROR_NONE; + } else + *errorCodeP = XML_ERROR_PARTIAL_CHAR; + return; + default: + *errorCodeP = XML_ERROR_JUNK_AFTER_DOC_ELEMENT; + return; + } + eventPtr = s = next; + } +} + + + +static enum XML_Error +doCdataSection(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char ** const startPtr, + const char * const end, + const char ** const nextPtr) { + + Parser * const parser = (Parser *) xmlParserP; + + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == parser->m_encoding) { + eventPP = &eventPtr; + *eventPP = s; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = 0; + for (;;) { + const char *next; + int tok = XmlCdataSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_CDATA_SECT_CLOSE: + if (endCdataSectionHandler) + endCdataSectionHandler(handlerArg); + else if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + *startPtr = next; + return XML_ERROR_NONE; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + break; + case XML_TOK_DATA_CHARS: + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = next; + characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + if (s == next) + break; + *eventPP = s; + } + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)next - (XML_Char *)s); + } + else if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + break; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_CDATA_SECTION; + default: + abort(); + } + *eventPP = s = next; + } + /* not reached */ +} + + + +/* Forward declaration for recursive reference: */ +static void +doContent(XML_Parser const xmlParserP, + int const startTagLevel, + const ENCODING * const enc, + const char * const startArg, + const char * const end, + const char ** const nextPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP); + + +static Processor contentProcessor; + +static void +contentProcessor(XML_Parser const xmlParserP, + const char * const start, + const char * const end, + const char ** const endPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + const char * error; + + parser->m_errorString = NULL; + + doContent(xmlParserP, 0, parser->m_encoding, start, end, endPtr, + errorCodeP, &error); + + if (*errorCodeP != XML_ERROR_NONE) { + if (error) { + xmlrpc_asprintf(errorP, "Invalid XML \"content\". %s", error); + + xmlrpc_strfree(error); + } else { + const char * const sampleXml = extractXmlSample(start, end, 40); + + xmlrpc_asprintf(errorP, "Invalid XML \"content\" starting " + "with '%s'. %s", + sampleXml, + xmlrpc_XML_ErrorString(*errorCodeP)); + + xmlrpc_strfree(sampleXml); + } + } else + *errorP = NULL; +} + + + +/* The idea here is to avoid using stack for each CDATA section when +the whole file is parsed with one call. */ + + + +static Processor cdataSectionProcessor; + +static void +cdataSectionProcessor(XML_Parser const xmlParserP, + const char * const startArg, + const char * const end, + const char ** const endPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + enum XML_Error result; + const char * start; + + start = startArg; + + result = + doCdataSection(xmlParserP, parser->m_encoding, &start, end, endPtr); + + if (start) { + processor = contentProcessor; + contentProcessor(xmlParserP, start, end, endPtr, errorCodeP, errorP); + } else { + *errorCodeP = result; + *errorP = NULL; + } +} + + + +static void +doEntityRef(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char * const s, + const char * const next, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + XML_Char const ch = XmlPredefinedEntityName(enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + const XML_Char *name; + ENTITY *entity; + *errorP = NULL; + + if (ch) { + if (characterDataHandler) + characterDataHandler(handlerArg, &ch, 1); + else if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + *errorCodeP = XML_ERROR_NONE; + return; + } + name = poolStoreString(&dtd.pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); + poolDiscard(&dtd.pool); + if (!entity) { + if (dtd.complete || dtd.standalone) + *errorCodeP = XML_ERROR_UNDEFINED_ENTITY; + else { + if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + *errorCodeP = XML_ERROR_NONE; + } + return; + } + if (entity->open) { + *errorCodeP = XML_ERROR_RECURSIVE_ENTITY_REF; + return; + } + if (entity->notation) { + *errorCodeP = XML_ERROR_BINARY_ENTITY_REF; + return; + } + if (entity) { + if (entity->textPtr) { + OPEN_INTERNAL_ENTITY openEntity; + if (defaultHandler && !defaultExpandInternalEntities) { + reportDefault(xmlParserP, enc, s, next); + *errorCodeP = XML_ERROR_NONE; + return; + } + entity->open = 1; + openEntity.next = openInternalEntities; + openInternalEntities = &openEntity; + openEntity.entity = entity; + openEntity.internalEventPtr = 0; + openEntity.internalEventEndPtr = 0; + doContent(xmlParserP, + tagLevel, + internalEncoding, + (char *)entity->textPtr, + (char *)(entity->textPtr + entity->textLen), + 0, errorCodeP, errorP); + entity->open = 0; + openInternalEntities = openEntity.next; + if (*errorCodeP != XML_ERROR_NONE) + return; + } else if (externalEntityRefHandler) { + const XML_Char *context; + entity->open = 1; + context = getContext(xmlParserP); + entity->open = 0; + if (!context) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + context, + entity->base, + entity->systemId, + entity->publicId)) { + *errorCodeP = XML_ERROR_EXTERNAL_ENTITY_HANDLING; + return; + } + poolDiscard(&tempPool); + } else if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + } + *errorCodeP = XML_ERROR_NONE; +} + + + +static void +doStartTagNoAtts(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char * const s, + const char * const next, + const char ** const nextPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + TAG *tag; + + *errorP = NULL; + + if (freeTagList) { + tag = freeTagList; + freeTagList = freeTagList->parent; + } else { + tag = malloc(sizeof(TAG)); + if (!tag) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + tag->buf = malloc(INIT_TAG_BUF_SIZE); + if (!tag->buf) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; + } + tag->bindings = NULL; + tag->parent = tagStack; + tagStack = tag; + tag->name.localPart = 0; + tag->rawName = s + enc->minBytesPerChar; + tag->rawNameLength = XmlNameLength(enc, tag->rawName); + if (nextPtr) { + /* Need to guarantee that: tag->buf + + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= + tag->bufEnd - sizeof(XML_Char) + */ + + if (tag->rawNameLength + + (int)(sizeof(XML_Char) - 1) + + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) { + int bufSize = tag->rawNameLength * 4; + bufSize = ROUND_UP(bufSize, sizeof(XML_Char)); + tag->buf = realloc(tag->buf, bufSize); + if (!tag->buf) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + tag->bufEnd = tag->buf + bufSize; + } + memcpy(tag->buf, tag->rawName, tag->rawNameLength); + tag->rawName = tag->buf; + } + ++tagLevel; + if (startElementHandler) { + enum XML_Error result; + XML_Char *toPtr; + for (;;) { + const char *rawNameEnd = tag->rawName + tag->rawNameLength; + const char *fromPtr = tag->rawName; + if (nextPtr) + toPtr = (XML_Char *) + (tag->buf + ROUND_UP(tag->rawNameLength, + sizeof(XML_Char))); + else + toPtr = (XML_Char *)tag->buf; + tag->name.str = toPtr; + XmlConvert(enc, + &fromPtr, rawNameEnd, + (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); + if (fromPtr == rawNameEnd) + break; + else { + int const bufSize = (tag->bufEnd - tag->buf) << 1; + tag->buf = realloc(tag->buf, bufSize); + if (!tag->buf) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + tag->bufEnd = tag->buf + bufSize; + if (nextPtr) + tag->rawName = tag->buf; + } + } + *toPtr = XML_T('\0'); + result = storeAtts(xmlParserP, enc, s, + &(tag->name), &(tag->bindings)); + if (result) { + *errorCodeP = result; + return; + } + startElementHandler(handlerArg, tag->name.str, + (const XML_Char **)atts); + poolClear(&tempPool); + } else { + tag->name.str = 0; + if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + } +} + + + +static void +doEmptyElementNoAtts(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char * const s, + const char * const end, + const char * const next, + const char ** const nextPtr, + const char ** const eventPP, + const char ** const eventEndPP, + bool * const doneP, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + if (startElementHandler || endElementHandler) { + const char * const rawName = s + enc->minBytesPerChar; + + enum XML_Error result; + BINDING * bindings; + TAG_NAME name; + + bindings = NULL; /* initial value */ + name.str = poolStoreString(&tempPool, enc, rawName, + rawName + XmlNameLength(enc, rawName)); + if (!name.str) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + poolFinish(&tempPool); + result = storeAtts(xmlParserP, enc, s, &name, &bindings); + if (result) { + *errorCodeP = result; + return; + } + poolFinish(&tempPool); + if (startElementHandler) + startElementHandler(handlerArg, name.str, (const XML_Char **)atts); + if (endElementHandler) { + if (startElementHandler) + *eventPP = *eventEndPP; + endElementHandler(handlerArg, name.str); + } + poolClear(&tempPool); + while (bindings) { + BINDING * const b = bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + } else if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + + if (tagLevel == 0) { + epilogProcessor(xmlParserP, next, end, nextPtr, errorCodeP, errorP); + *doneP = true; + } else + *doneP = false; +} + + + +static void +doEndTag(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char * const s, + const char * const end, + const char * const next, + const char ** const nextPtr, + int const startTagLevel, + const char ** const eventPP, + bool * const doneP, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + if (tagLevel == startTagLevel) + *errorCodeP = XML_ERROR_ASYNC_ENTITY; + else { + TAG * const tag = tagStack; + + int len; + const char * rawName; + + tagStack = tag->parent; + tag->parent = freeTagList; + freeTagList = tag; + rawName = s + enc->minBytesPerChar*2; + len = XmlNameLength(enc, rawName); + if (len != tag->rawNameLength + || memcmp(tag->rawName, rawName, len) != 0) { + *eventPP = rawName; + *errorCodeP = XML_ERROR_TAG_MISMATCH; + } else { + --tagLevel; + if (endElementHandler && tag->name.str) { + if (tag->name.localPart) { + XML_Char * to; + const XML_Char * from; + to = (XML_Char *)tag->name.str + tag->name.uriLen; + from = tag->name.localPart; + while ((*to++ = *from++) != 0) + ; + } + endElementHandler(handlerArg, tag->name.str); + } else if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + + while (tag->bindings) { + BINDING * const b = tag->bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + tag->bindings = tag->bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + if (tagLevel == 0) { + epilogProcessor(xmlParserP, next, end, nextPtr, + errorCodeP, errorP); + *doneP = true; + } else { + *errorCodeP = XML_ERROR_NONE; + *doneP = false; + } + } + } +} + + + +static void +processContentToken(XML_Parser const xmlParserP, + int const tok, + const ENCODING * const enc, + const char * const s, + const char * const end, + const char ** const nextP, + const char ** const nextPtr, + int const startTagLevel, + const char ** const eventPP, + const char ** const eventEndPP, + bool * const doneP, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + *errorP = NULL; + *errorCodeP = XML_ERROR_NONE; + + switch (tok) { + case XML_TOK_TRAILING_CR: + if (nextPtr) { + *nextPtr = s; + *doneP = true; + } else { + *eventEndPP = end; + + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } else if (defaultHandler) + reportDefault(xmlParserP, enc, s, end); + + if (startTagLevel == 0) + *errorCodeP = XML_ERROR_NO_ELEMENTS; + else if (tagLevel != startTagLevel) { + *errorCodeP = XML_ERROR_ASYNC_ENTITY; + } else + *doneP = true; + } + break; + case XML_TOK_NONE: + if (nextPtr) { + *nextPtr = s; + *doneP = true; + } else if (startTagLevel > 0) { + if (tagLevel != startTagLevel) + *errorCodeP = XML_ERROR_ASYNC_ENTITY; + else + *doneP = true; + } else + *errorCodeP = XML_ERROR_NO_ELEMENTS; + break; + case XML_TOK_INVALID: + *eventPP = *nextP; + *errorCodeP = XML_ERROR_INVALID_TOKEN; + xmlrpc_asprintf(errorP, "Invalid token, starting %ld bytes in", + (long)(*nextP - s)); + break; + case XML_TOK_PARTIAL: + if (nextPtr) { + *nextPtr = s; + *doneP = true; + } else + *errorCodeP = XML_ERROR_UNCLOSED_TOKEN; + break; + case XML_TOK_PARTIAL_CHAR: + if (nextPtr) { + *nextPtr = s; + *doneP = true; + } else + *errorCodeP = XML_ERROR_PARTIAL_CHAR; + break; + case XML_TOK_ENTITY_REF: + doEntityRef(xmlParserP, enc, s, *nextP, errorCodeP, errorP); + break; + case XML_TOK_START_TAG_WITH_ATTS: + if (!startElementHandler) + *errorCodeP = storeAtts(xmlParserP, enc, s, 0, 0); + if (*errorCodeP == XML_ERROR_NONE) + doStartTagNoAtts(xmlParserP, enc, s, *nextP, nextPtr, + errorCodeP, errorP); + break; + case XML_TOK_START_TAG_NO_ATTS: + doStartTagNoAtts(xmlParserP, enc, s, *nextP, nextPtr, + errorCodeP, errorP); + break; + case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: + if (!startElementHandler) + *errorCodeP = storeAtts(xmlParserP, enc, s, 0, 0); + + if (*errorCodeP == XML_ERROR_NONE) + doEmptyElementNoAtts(xmlParserP, enc, s, end, *nextP, nextPtr, + eventPP, eventEndPP, + doneP, errorCodeP, errorP); + break; + case XML_TOK_EMPTY_ELEMENT_NO_ATTS: + doEmptyElementNoAtts(xmlParserP, enc, s, end, *nextP, nextPtr, + eventPP, eventEndPP, + doneP, errorCodeP, errorP); + break; + case XML_TOK_END_TAG: + doEndTag(xmlParserP, enc, s, end, *nextP, nextPtr, startTagLevel, + eventPP, doneP, errorCodeP, errorP); + break; + case XML_TOK_CHAR_REF: { + int const n = XmlCharRefNumber(enc, s); + if (n < 0) + *errorCodeP = XML_ERROR_BAD_CHAR_REF; + else { + if (characterDataHandler) { + XML_Char buf[XML_ENCODE_MAX]; + characterDataHandler(handlerArg, buf, + XmlEncode(n, (ICHAR *)buf)); + } else if (defaultHandler) + reportDefault(xmlParserP, enc, s, *nextP); + } + } break; + case XML_TOK_XML_DECL: + *errorCodeP = XML_ERROR_MISPLACED_XML_PI; + break; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } else if (defaultHandler) + reportDefault(xmlParserP, enc, s, *nextP); + break; + case XML_TOK_CDATA_SECT_OPEN: { + enum XML_Error result; + if (startCdataSectionHandler) + startCdataSectionHandler(handlerArg); + else if (defaultHandler) + reportDefault(xmlParserP, enc, s, *nextP); + result = doCdataSection(xmlParserP, enc, nextP, end, nextPtr); + if (!*nextP) { + processor = cdataSectionProcessor; + *errorCodeP = result; + } + } break; + case XML_TOK_TRAILING_RSQB: + if (nextPtr) { + *nextPtr = s; + *errorCodeP = XML_ERROR_NONE; + } else { + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + const char * from; + ICHAR * dataPtr; + from = s; + dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &from, end, &dataPtr, (ICHAR *)dataBufEnd); + characterDataHandler(handlerArg, dataBuf, + dataPtr - (ICHAR *)dataBuf); + } else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)end - (XML_Char *)s); + } else if (defaultHandler) + reportDefault(xmlParserP, enc, s, end); + + if (startTagLevel == 0) { + *eventPP = end; + *errorCodeP = XML_ERROR_NO_ELEMENTS; + } else if (tagLevel != startTagLevel) { + *eventPP = end; + *errorCodeP = XML_ERROR_ASYNC_ENTITY; + } else + *doneP = true; + } + break; + case XML_TOK_DATA_CHARS: + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + const char * from; + ICHAR * dataPtr; + dataPtr = (ICHAR *)dataBuf; + from = s; + XmlConvert(enc, &from, *nextP, &dataPtr, + (ICHAR *)dataBufEnd); + *eventEndPP = from; + characterDataHandler(handlerArg, dataBuf, + dataPtr - (ICHAR *)dataBuf); + if (from == *nextP) + break; + *eventPP = from; + } + } else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)*nextP - (XML_Char *)s); + } else if (defaultHandler) + reportDefault(xmlParserP, enc, s, *nextP); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(xmlParserP, enc, s, *nextP)) + *errorCodeP = XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(xmlParserP, enc, s, *nextP)) + *errorCodeP = XML_ERROR_NO_MEMORY; + break; + default: + if (defaultHandler) + reportDefault(xmlParserP, enc, s, *nextP); + break; + } +} + + + +static void +doContent(XML_Parser const xmlParserP, + int const startTagLevel, + const ENCODING * const enc, + const char * const startArg, + const char * const end, + const char ** const nextPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + const char **eventPP; + const char **eventEndPP; + const char * s; + bool done; + + if (enc == parser->m_encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + + s = startArg; + *eventPP = s; + done = false; + *errorCodeP = XML_ERROR_NONE; + *errorP = NULL; + + while (*errorCodeP == XML_ERROR_NONE && !done) { + int tok; + const char * next; + const char * error; + + next = s; /* XmlContentTok doesn't always set the last arg */ + /* XmlContentTok() is normally normal_contentTok(), aka + PREFIX(contentTok)() in xmltok/xmltok_impl.c + */ + tok = XmlContentTok(enc, s, end, &next); + *eventEndPP = next; + + processContentToken(xmlParserP, tok, enc, s, end, &next, nextPtr, + startTagLevel, eventPP, eventEndPP, &done, + errorCodeP, &error); + + if (*errorCodeP != XML_ERROR_NONE) { + const char * const xmlSample = extractXmlSample(s, end, 40); + + if (error) { + xmlrpc_asprintf(errorP, "Problem with token at '%s...': %s", + xmlSample, error); + xmlrpc_strfree(error); + } else + xmlrpc_asprintf(errorP, "Problem with token at '%s...': %s", + xmlSample, + xmlrpc_XML_ErrorString(*errorCodeP)); + + xmlrpc_strfree(xmlSample); + } + *eventPP = s = next; + } +} + + + +static Processor externalEntityContentProcessor; + +static void +externalEntityContentProcessor(XML_Parser const xmlParserP, + const char * const start, + const char * const end, + const char ** const endPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + *errorP = NULL; + + doContent(xmlParserP, 1, parser->m_encoding, start, end, endPtr, + errorCodeP, errorP); +} + + + +static Processor externalEntityInitProcessor3; + +static void +externalEntityInitProcessor3(XML_Parser const xmlParserP, + const char * const startArg, + const char * const end, + const char ** const endPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + const char * start; + const char *next; + int tok; + + tok = XmlContentTok(parser->m_encoding, startArg, end, &next); + + *errorP = NULL; + + start = startArg; + + switch (tok) { + case XML_TOK_XML_DECL: + { + enum XML_Error result = processXmlDecl(xmlParserP, 1, start, next); + if (result != XML_ERROR_NONE) { + *errorCodeP = result; + return; + } + start = next; + } + break; + case XML_TOK_PARTIAL: + if (endPtr) { + *endPtr = start; + *errorCodeP = XML_ERROR_NONE; + return; + } + eventPtr = start; + *errorCodeP = XML_ERROR_UNCLOSED_TOKEN; + return; + case XML_TOK_PARTIAL_CHAR: + if (endPtr) { + *endPtr = start; + *errorCodeP = XML_ERROR_NONE; + return; + } + eventPtr = start; + *errorCodeP = XML_ERROR_PARTIAL_CHAR; + return; + } + processor = externalEntityContentProcessor; + tagLevel = 1; + doContent(xmlParserP, 1, parser->m_encoding, start, end, endPtr, + errorCodeP, errorP); +} + + + +static Processor externalEntityInitProcessor2; + +static void +externalEntityInitProcessor2(XML_Parser const xmlParserP, + const char * const startArg, + const char * const end, + const char ** const endPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *)xmlParserP; + + const char * start; + const char * next; + int tok; + + tok = XmlContentTok(parser->m_encoding, startArg, end, &next); + + start = startArg; + + switch (tok) { + case XML_TOK_BOM: + start = next; + break; + case XML_TOK_PARTIAL: + if (endPtr) { + *endPtr = start; + *errorCodeP = XML_ERROR_NONE; + *errorP = NULL; + } else { + eventPtr = start; + *errorCodeP = XML_ERROR_UNCLOSED_TOKEN; + *errorP = NULL; + } + return; + case XML_TOK_PARTIAL_CHAR: + if (endPtr) { + *endPtr = start; + *errorCodeP = XML_ERROR_NONE; + *errorP = NULL; + } else { + eventPtr = start; + *errorCodeP = XML_ERROR_PARTIAL_CHAR; + *errorP = NULL; + } + return; + } + processor = externalEntityInitProcessor3; + externalEntityInitProcessor3(xmlParserP, start, end, endPtr, + errorCodeP, errorP); +} + + + +static Processor externalEntityInitProcessor; + +static void +externalEntityInitProcessor(XML_Parser const parser, + const char * const start, + const char * const end, + const char ** const endPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + enum XML_Error result; + + result = initializeEncoding(parser); + + if (result != XML_ERROR_NONE) { + *errorCodeP = result; + *errorP = NULL; + } else { + processor = externalEntityInitProcessor2; + + externalEntityInitProcessor2(parser, start, end, endPtr, + errorCodeP, errorP); + } +} + + + +static enum XML_Error +doIgnoreSection(XML_Parser const xmlParserP, + const ENCODING * const enc, + const char ** const startPtr, + const char * const end, + const char ** const nextPtr) { +/*---------------------------------------------------------------------------- + + We set *startPtr to non-null is the section is closed, and to null if + the section is not yet closed. +-----------------------------------------------------------------------------*/ + Parser * const parser = (Parser *) xmlParserP; + const char * const s = *startPtr; + + enum XML_Error retval; + const char * next; + int tok; + const char ** eventPP; + const char ** eventEndPP; + + if (enc == parser->m_encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = '\0'; + tok = XmlIgnoreSectionTok(enc, s, end, &next); + *eventEndPP = next; + + switch (tok) { + case XML_TOK_IGNORE_SECT: + if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + *startPtr = next; + retval = XML_ERROR_NONE; + break; + case XML_TOK_INVALID: + *eventPP = next; + retval = XML_ERROR_INVALID_TOKEN; + break; + case XML_TOK_PARTIAL_CHAR: + if (nextPtr) { + *nextPtr = s; + retval = XML_ERROR_NONE; + } else + retval = XML_ERROR_PARTIAL_CHAR; + break; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (nextPtr) { + *nextPtr = s; + retval = XML_ERROR_NONE; + } else + retval = XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ + break; + default: + assert(false); /* All possibilities are handled above */ + retval = 99; /* quiet compiler warning */ + } + + return retval; +} + + + +static Processor prologProcessor; + + +/* The idea here is to avoid using stack for each IGNORE section when +the whole file is parsed with one call. */ + +static Processor ignoreSectionProcessor; + +static void +ignoreSectionProcessor(XML_Parser const xmlParserP, + const char * const startArg, + const char * const end, + const char ** const endPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + enum XML_Error result; + const char * start; + + start = startArg; /* initial value */ + + result = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr); + + if (start) { + processor = prologProcessor; + prologProcessor(xmlParserP, start, end, endPtr, errorCodeP, errorP); + } else { + *errorCodeP = result; + *errorP = NULL; + } +} + + + +/* Forward declaration for recursive reference: */ +static void +processInternalParamEntity(XML_Parser const parser, + ENTITY * const entity, + enum XML_Error * const errorCodeP, + const char ** const errorP); + +static void +doProlog(XML_Parser const xmlParserP, + const ENCODING * const encArg, + const char * const startArg, + const char * const end, + int const tokArg, + const char * const nextArg, + const char ** const nextPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + int tok; + const char * next; + const ENCODING * enc; + const char * s; + + static const XML_Char externalSubsetName[] = { '#' , '\0' }; + + const char **eventPP; + const char **eventEndPP; + + *errorP = NULL; + + tok = tokArg; + next = nextArg; + enc = encArg; + s = startArg; + + if (enc == parser->m_encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + for (;;) { + int role; + *eventPP = s; + *eventEndPP = next; + if (tok <= 0) { + if (nextPtr != 0 && tok != XML_TOK_INVALID) { + *nextPtr = s; + *errorCodeP = XML_ERROR_NONE; + return; + } + switch (tok) { + case XML_TOK_INVALID: + *eventPP = next; + *errorCodeP = XML_ERROR_INVALID_TOKEN; + return; + case XML_TOK_PARTIAL: + *errorCodeP = XML_ERROR_UNCLOSED_TOKEN; + return; + case XML_TOK_PARTIAL_CHAR: + *errorCodeP = XML_ERROR_PARTIAL_CHAR; + return; + case XML_TOK_NONE: + if (enc != parser->m_encoding) + *errorCodeP = XML_ERROR_NONE; + else { + if (parentParser) { + if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) + == XML_ROLE_ERROR) { + *errorCodeP = XML_ERROR_SYNTAX; + } else { + *errorCodeP = XML_ERROR_NONE; + hadExternalDoctype = 0; + } + } else + *errorCodeP = XML_ERROR_NO_ELEMENTS; + } + return; + default: + tok = -tok; + next = end; + break; + } + } + role = XmlTokenRole(&prologState, tok, s, next, enc); + switch (role) { + case XML_ROLE_XML_DECL: { + enum XML_Error result = processXmlDecl(xmlParserP, 0, s, next); + if (result != XML_ERROR_NONE) { + *errorCodeP = result; + return; + } + enc = parser->m_encoding; + } + break; + case XML_ROLE_DOCTYPE_NAME: + if (startDoctypeDeclHandler) { + const XML_Char *name = poolStoreString(&tempPool, enc, s, next); + if (!name) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + startDoctypeDeclHandler(handlerArg, name); + poolClear(&tempPool); + } + break; + case XML_ROLE_TEXT_DECL: { + enum XML_Error result = processXmlDecl(xmlParserP, 1, s, next); + if (result != XML_ERROR_NONE) { + *errorCodeP = result; + return; + } + enc = parser->m_encoding; + } + break; + case XML_ROLE_DOCTYPE_PUBLIC_ID: + declEntity = (ENTITY *)lookup(&dtd.paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + /* fall through */ + case XML_ROLE_ENTITY_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) { + *errorCodeP = XML_ERROR_SYNTAX; + return; + } + if (declEntity) { + XML_Char *tem = poolStoreString(&dtd.pool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + normalizePublicId(tem); + declEntity->publicId = tem; + poolFinish(&dtd.pool); + } + break; + case XML_ROLE_DOCTYPE_CLOSE: + if (dtd.complete && hadExternalDoctype) { + dtd.complete = 0; + if (paramEntityParsing && externalEntityRefHandler) { + ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities, + externalSubsetName, + 0); + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + *errorCodeP = XML_ERROR_EXTERNAL_ENTITY_HANDLING; + return; + } + } + if (!dtd.complete + && !dtd.standalone + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) { + *errorCodeP = XML_ERROR_NOT_STANDALONE; + return; + } + } + if (endDoctypeDeclHandler) + endDoctypeDeclHandler(handlerArg); + break; + case XML_ROLE_INSTANCE_START: { + processor = contentProcessor; + contentProcessor(xmlParserP, s, end, nextPtr, errorCodeP, errorP); + return; + } + case XML_ROLE_ATTLIST_ELEMENT_NAME: + { + const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next); + if (!name) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + declElementType = (ELEMENT_TYPE *) + lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE)); + if (!declElementType) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + if (declElementType->name != name) + poolDiscard(&dtd.pool); + else { + poolFinish(&dtd.pool); + if (!setElementTypePrefix(xmlParserP, declElementType)) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + } + break; + } + case XML_ROLE_ATTRIBUTE_NAME: + declAttributeId = getAttributeId(xmlParserP, enc, s, next); + if (!declAttributeId) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + declAttributeIsCdata = 0; + declAttributeIsId = 0; + break; + case XML_ROLE_ATTRIBUTE_TYPE_CDATA: + declAttributeIsCdata = 1; + break; + case XML_ROLE_ATTRIBUTE_TYPE_ID: + declAttributeIsId = 1; + break; + case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: + case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: + if (dtd.complete + && !defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, + declAttributeIsId, 0)) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + break; + case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: + case XML_ROLE_FIXED_ATTRIBUTE_VALUE: + { + const XML_Char *attVal; + enum XML_Error result + = storeAttributeValue(xmlParserP, enc, declAttributeIsCdata, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar, + &dtd.pool); + if (result) { + *errorCodeP = result; + return; + } + attVal = poolStart(&dtd.pool); + poolFinish(&dtd.pool); + if (dtd.complete + /* ID attributes aren't allowed to have a default */ + && !defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, 0, attVal)) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + break; + } + case XML_ROLE_ENTITY_VALUE: + { + enum XML_Error result = storeEntityValue(xmlParserP, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (declEntity) { + declEntity->textPtr = poolStart(&dtd.pool); + declEntity->textLen = poolLength(&dtd.pool); + poolFinish(&dtd.pool); + if (internalParsedEntityDeclHandler + /* Check it's not a parameter entity */ + && ((ENTITY *)lookup(&dtd.generalEntities, declEntity->name, 0) + == declEntity)) { + *eventEndPP = s; + internalParsedEntityDeclHandler(handlerArg, + declEntity->name, + declEntity->textPtr, + declEntity->textLen); + } + } + else + poolDiscard(&dtd.pool); + if (result != XML_ERROR_NONE) { + *errorCodeP = result; + return; + } + } + break; + case XML_ROLE_DOCTYPE_SYSTEM_ID: + if (!dtd.standalone + && !paramEntityParsing + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) { + *errorCodeP = XML_ERROR_NOT_STANDALONE; + return; + } + hadExternalDoctype = 1; + if (!declEntity) { + declEntity = (ENTITY *)lookup(&dtd.paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + } + /* fall through */ + case XML_ROLE_ENTITY_SYSTEM_ID: + if (declEntity) { + declEntity->systemId = poolStoreString(&dtd.pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!declEntity->systemId) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + declEntity->base = curBase; + poolFinish(&dtd.pool); + } + break; + case XML_ROLE_ENTITY_NOTATION_NAME: + if (declEntity) { + declEntity->notation = poolStoreString(&dtd.pool, enc, s, next); + if (!declEntity->notation) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + poolFinish(&dtd.pool); + if (unparsedEntityDeclHandler) { + *eventEndPP = s; + unparsedEntityDeclHandler(handlerArg, + declEntity->name, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + } + + } + break; + case XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION: + if (declEntity && externalParsedEntityDeclHandler) { + *eventEndPP = s; + externalParsedEntityDeclHandler(handlerArg, + declEntity->name, + declEntity->base, + declEntity->systemId, + declEntity->publicId); + } + break; + case XML_ROLE_GENERAL_ENTITY_NAME: + { + const XML_Char *name; + if (XmlPredefinedEntityName(enc, s, next)) { + declEntity = 0; + break; + } + name = poolStoreString(&dtd.pool, enc, s, next); + if (!name) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + if (dtd.complete) { + declEntity = (ENTITY *) + lookup(&dtd.generalEntities, name, sizeof(ENTITY)); + if (!declEntity) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + if (declEntity->name != name) { + poolDiscard(&dtd.pool); + declEntity = 0; + } + else + poolFinish(&dtd.pool); + } + else { + poolDiscard(&dtd.pool); + declEntity = 0; + } + } + break; + case XML_ROLE_PARAM_ENTITY_NAME: + if (dtd.complete) { + const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next); + if (!name) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + declEntity = (ENTITY *) + lookup(&dtd.paramEntities, name, sizeof(ENTITY)); + if (!declEntity) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + if (declEntity->name != name) { + poolDiscard(&dtd.pool); + declEntity = 0; + } + else + poolFinish(&dtd.pool); + } + break; + case XML_ROLE_NOTATION_NAME: + declNotationPublicId = 0; + declNotationName = 0; + if (notationDeclHandler) { + declNotationName = poolStoreString(&tempPool, enc, s, next); + if (!declNotationName) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + poolFinish(&tempPool); + } + break; + case XML_ROLE_NOTATION_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) { + *errorCodeP = XML_ERROR_SYNTAX; + return; + } + if (declNotationName) { + XML_Char *tem = poolStoreString(&tempPool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + normalizePublicId(tem); + declNotationPublicId = tem; + poolFinish(&tempPool); + } + break; + case XML_ROLE_NOTATION_SYSTEM_ID: + if (declNotationName && notationDeclHandler) { + const XML_Char *systemId + = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!systemId) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + systemId, + declNotationPublicId); + } + poolClear(&tempPool); + break; + case XML_ROLE_NOTATION_NO_SYSTEM_ID: + if (declNotationPublicId && notationDeclHandler) { + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + 0, + declNotationPublicId); + } + poolClear(&tempPool); + break; + case XML_ROLE_ERROR: + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: + *errorCodeP = XML_ERROR_PARAM_ENTITY_REF; + case XML_TOK_XML_DECL: + *errorCodeP = XML_ERROR_MISPLACED_XML_PI; + default: + *errorCodeP = XML_ERROR_SYNTAX; + } + return; + case XML_ROLE_IGNORE_SECT: + { + enum XML_Error result; + if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + result = doIgnoreSection(xmlParserP, enc, &next, end, nextPtr); + if (!next) { + processor = ignoreSectionProcessor; + *errorCodeP = result; + return; + } + } + break; + case XML_ROLE_GROUP_OPEN: + if (prologState.level >= groupSize) { + if (groupSize) + groupConnector = realloc(groupConnector, groupSize *= 2); + else + groupConnector = malloc(groupSize = 32); + if (!groupConnector) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + } + groupConnector[prologState.level] = 0; + break; + case XML_ROLE_GROUP_SEQUENCE: + if (groupConnector[prologState.level] == '|') { + *errorCodeP = XML_ERROR_SYNTAX; + return; + } + groupConnector[prologState.level] = ','; + break; + case XML_ROLE_GROUP_CHOICE: + if (groupConnector[prologState.level] == ',') { + *errorCodeP = XML_ERROR_SYNTAX; + return; + } + groupConnector[prologState.level] = '|'; + break; + case XML_ROLE_PARAM_ENTITY_REF: + case XML_ROLE_INNER_PARAM_ENTITY_REF: + if (paramEntityParsing + && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) { + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&dtd.pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0); + poolDiscard(&dtd.pool); + if (!entity) { + /* FIXME what to do if !dtd.complete? */ + *errorCodeP = XML_ERROR_UNDEFINED_ENTITY; + return; + } + if (entity->open) { + *errorCodeP = XML_ERROR_RECURSIVE_ENTITY_REF; + return; + } + if (entity->textPtr) { + processInternalParamEntity(xmlParserP, entity, errorCodeP, errorP); + if (*errorCodeP != XML_ERROR_NONE) + return; + break; + } + if (role == XML_ROLE_INNER_PARAM_ENTITY_REF) { + *errorCodeP = XML_ERROR_PARAM_ENTITY_REF; + return; + } + if (externalEntityRefHandler) { + dtd.complete = 0; + entity->open = 1; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + entity->open = 0; + *errorCodeP = XML_ERROR_EXTERNAL_ENTITY_HANDLING; + return; + } + entity->open = 0; + if (dtd.complete) + break; + } + } + if (!dtd.standalone + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) { + *errorCodeP = XML_ERROR_NOT_STANDALONE; + return; + } + dtd.complete = 0; + if (defaultHandler) + reportDefault(xmlParserP, enc, s, next); + break; + case XML_ROLE_NONE: + switch (tok) { + case XML_TOK_PI: + if (!reportProcessingInstruction(xmlParserP, enc, s, next)) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + break; + case XML_TOK_COMMENT: + if (!reportComment(xmlParserP, enc, s, next)) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } + break; + } + break; + } + if (defaultHandler) { + switch (tok) { + case XML_TOK_PI: + case XML_TOK_COMMENT: + case XML_TOK_BOM: + case XML_TOK_XML_DECL: + case XML_TOK_IGNORE_SECT: + case XML_TOK_PARAM_ENTITY_REF: + break; + default: + if (role != XML_ROLE_IGNORE_SECT) + reportDefault(xmlParserP, enc, s, next); + } + } + s = next; + tok = XmlPrologTok(enc, s, end, &next); + } + /* not reached */ +} + + + +static Processor prologProcessor; + +static void +prologProcessor(XML_Parser const xmlParserP, + const char * const s, + const char * const end, + const char ** const nextPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + Parser * const parser = (Parser *) xmlParserP; + + const char * next; + int tok; + + *errorP = NULL; + + tok = XmlPrologTok(parser->m_encoding, s, end, &next); + + doProlog(xmlParserP, parser->m_encoding, s, end, tok, next, nextPtr, + errorCodeP, errorP); +} + + + +static Processor prologInitProcessor; + +static void +prologInitProcessor(XML_Parser const parser, + const char * const s, + const char * const end, + const char ** const nextPtr, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + enum XML_Error result; + + *errorP = NULL; + + result = initializeEncoding(parser); + + if (result != XML_ERROR_NONE) + *errorCodeP = result; + else { + processor = prologProcessor; + prologProcessor(parser, s, end, nextPtr, errorCodeP, errorP); + } +} + + + +static void +processInternalParamEntity(XML_Parser const parser, + ENTITY * const entity, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + const char *s, *end, *next; + int tok; + OPEN_INTERNAL_ENTITY openEntity; + + entity->open = 1; + openEntity.next = openInternalEntities; + openInternalEntities = &openEntity; + openEntity.entity = entity; + openEntity.internalEventPtr = 0; + openEntity.internalEventEndPtr = 0; + s = (char *)entity->textPtr; + end = (char *)(entity->textPtr + entity->textLen); + tok = XmlPrologTok(internalEncoding, s, end, &next); + + doProlog(parser, internalEncoding, s, end, tok, next, 0, + errorCodeP, errorP); + + entity->open = 0; + openInternalEntities = openEntity.next; +} + + + +XML_Parser +xmlrpc_XML_ParserCreate(const XML_Char * const encodingName) { + + XML_Parser const xmlParserP = malloc(sizeof(Parser)); + Parser * const parser = (Parser *)xmlParserP; + if (xmlParserP) { + processor = prologInitProcessor; + xmlrpc_XmlPrologStateInit(&prologState); + userData = 0; + handlerArg = 0; + startElementHandler = 0; + endElementHandler = 0; + characterDataHandler = 0; + processingInstructionHandler = 0; + commentHandler = 0; + startCdataSectionHandler = 0; + endCdataSectionHandler = 0; + defaultHandler = 0; + startDoctypeDeclHandler = 0; + endDoctypeDeclHandler = 0; + unparsedEntityDeclHandler = 0; + notationDeclHandler = 0; + externalParsedEntityDeclHandler = 0; + internalParsedEntityDeclHandler = 0; + startNamespaceDeclHandler = 0; + endNamespaceDeclHandler = 0; + notStandaloneHandler = 0; + externalEntityRefHandler = 0; + externalEntityRefHandlerArg = parser; + unknownEncodingHandler = 0; + buffer = 0; + bufferPtr = 0; + bufferEnd = 0; + parseEndByteIndex = 0; + parseEndPtr = 0; + bufferLim = 0; + declElementType = 0; + declAttributeId = 0; + declEntity = 0; + declNotationName = 0; + declNotationPublicId = 0; + memset(&position, 0, sizeof(POSITION)); + errorCode = XML_ERROR_NONE; + errorString = NULL; + eventPtr = 0; + eventEndPtr = 0; + positionPtr = 0; + openInternalEntities = 0; + tagLevel = 0; + tagStack = 0; + freeTagList = 0; + freeBindingList = 0; + inheritedBindings = 0; + attsSize = INIT_ATTS_SIZE; + atts = malloc(attsSize * sizeof(ATTRIBUTE)); + nSpecifiedAtts = 0; + dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); + groupSize = 0; + groupConnector = 0; + hadExternalDoctype = 0; + unknownEncodingMem = 0; + unknownEncodingRelease = 0; + unknownEncodingData = 0; + unknownEncodingHandlerData = 0; + namespaceSeparator = '!'; + parentParser = 0; + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; + ns = 0; + poolInit(&tempPool); + poolInit(&temp2Pool); + protocolEncodingName = + encodingName ? poolCopyString(&tempPool, encodingName) : 0; + curBase = 0; + if (!dtdInit(&dtd) || !atts || !dataBuf + || (encodingName && !protocolEncodingName)) { + xmlrpc_XML_ParserFree(xmlParserP); + return 0; + } + dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; + xmlrpc_XmlInitEncoding(&parser->m_initEncoding, + &parser->m_encoding, + 0); + internalEncoding = XmlGetInternalEncoding(); + } + return xmlParserP; +} + +XML_Parser +xmlrpc_XML_ParserCreateNS(const XML_Char * const encodingName, + XML_Char const nsSep) { + + static + const XML_Char implicitContext[] = { + XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='), + XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'), + XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'), + XML_T('.'), XML_T('w'), XML_T('3'), + XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'), + XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'), + XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'), + XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'), + XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'), + XML_T('\0') + }; + + XML_Parser const xmlParserP = xmlrpc_XML_ParserCreate(encodingName); + Parser * const parser = (Parser *)xmlParserP; + XML_Parser retval; + + if (xmlParserP) { + int succeeded; + xmlrpc_XmlInitEncodingNS(&initEncoding, &parser->m_encoding, 0); + ns = 1; + internalEncoding = XmlGetInternalEncodingNS(); + namespaceSeparator = nsSep; + + succeeded = setContext(xmlParserP, implicitContext); + if (succeeded) + retval = xmlParserP; + else { + xmlrpc_XML_ParserFree(xmlParserP); + retval = NULL; + } + } else + retval = NULL; + + return retval; +} + + + +int +xmlrpc_XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) +{ + if (!encodingName) + protocolEncodingName = 0; + else { + protocolEncodingName = poolCopyString(&tempPool, encodingName); + if (!protocolEncodingName) + return 0; + } + return 1; +} + + + +XML_Parser +xmlrpc_XML_ExternalEntityParserCreate(XML_Parser oldParser, + const XML_Char *context, + const XML_Char *encodingName) +{ + XML_Parser parser = oldParser; + DTD *oldDtd = &dtd; + XML_StartElementHandler oldStartElementHandler = startElementHandler; + XML_EndElementHandler oldEndElementHandler = endElementHandler; + XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; + XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler; + XML_CommentHandler oldCommentHandler = commentHandler; + XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler; + XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler; + XML_DefaultHandler oldDefaultHandler = defaultHandler; + XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler; + XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; + XML_ExternalParsedEntityDeclHandler oldExternalParsedEntityDeclHandler = externalParsedEntityDeclHandler; + XML_InternalParsedEntityDeclHandler oldInternalParsedEntityDeclHandler = internalParsedEntityDeclHandler; + XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler; + XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; + XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler; + XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler; + void *oldUserData = userData; + void *oldHandlerArg = handlerArg; + int oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; + int oldParamEntityParsing = paramEntityParsing; + parser = (ns + ? xmlrpc_XML_ParserCreateNS(encodingName, namespaceSeparator) + : xmlrpc_XML_ParserCreate(encodingName)); + if (!parser) + return 0; + startElementHandler = oldStartElementHandler; + endElementHandler = oldEndElementHandler; + characterDataHandler = oldCharacterDataHandler; + processingInstructionHandler = oldProcessingInstructionHandler; + commentHandler = oldCommentHandler; + startCdataSectionHandler = oldStartCdataSectionHandler; + endCdataSectionHandler = oldEndCdataSectionHandler; + defaultHandler = oldDefaultHandler; + unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; + notationDeclHandler = oldNotationDeclHandler; + externalParsedEntityDeclHandler = oldExternalParsedEntityDeclHandler; + internalParsedEntityDeclHandler = oldInternalParsedEntityDeclHandler; + startNamespaceDeclHandler = oldStartNamespaceDeclHandler; + endNamespaceDeclHandler = oldEndNamespaceDeclHandler; + notStandaloneHandler = oldNotStandaloneHandler; + externalEntityRefHandler = oldExternalEntityRefHandler; + unknownEncodingHandler = oldUnknownEncodingHandler; + userData = oldUserData; + if (oldUserData == oldHandlerArg) + handlerArg = userData; + else + handlerArg = parser; + if (oldExternalEntityRefHandlerArg != oldParser) + externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; + defaultExpandInternalEntities = oldDefaultExpandInternalEntities; + paramEntityParsing = oldParamEntityParsing; + if (context) { + if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) { + xmlrpc_XML_ParserFree(parser); + return 0; + } + processor = externalEntityInitProcessor; + } + else { + dtdSwap(&dtd, oldDtd); + parentParser = oldParser; + xmlrpc_XmlPrologStateInitExternalEntity(&prologState); + dtd.complete = 1; + hadExternalDoctype = 1; + } + return parser; +} + +static +void destroyBindings(BINDING *bindings) +{ + for (;;) { + BINDING *b = bindings; + if (!b) + break; + bindings = b->nextTagBinding; + free(b->uri); + free(b); + } +} + +void +xmlrpc_XML_ParserFree(XML_Parser parser) +{ + for (;;) { + TAG *p; + if (tagStack == 0) { + if (freeTagList == 0) + break; + tagStack = freeTagList; + freeTagList = 0; + } + p = tagStack; + tagStack = tagStack->parent; + free(p->buf); + destroyBindings(p->bindings); + free(p); + } + destroyBindings(freeBindingList); + destroyBindings(inheritedBindings); + poolDestroy(&tempPool); + poolDestroy(&temp2Pool); + if (parentParser) { + if (hadExternalDoctype) + dtd.complete = 0; + dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd); + } + dtdDestroy(&dtd); + free((void *)atts); + free(groupConnector); + free(buffer); + free(dataBuf); + free(unknownEncodingMem); + if (unknownEncodingRelease) + unknownEncodingRelease(unknownEncodingData); + if (errorString) + xmlrpc_strfree(errorString); + free(parser); +} + +void +xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser) +{ + handlerArg = parser; +} + +void +xmlrpc_XML_SetUserData(XML_Parser parser, void *p) +{ + if (handlerArg == userData) + handlerArg = userData = p; + else + userData = p; +} + +int +xmlrpc_XML_SetBase(XML_Parser parser, const XML_Char *p) +{ + if (p) { + p = poolCopyString(&dtd.pool, p); + if (!p) + return 0; + curBase = p; + } + else + curBase = 0; + return 1; +} + +const XML_Char * +xmlrpc_XML_GetBase(XML_Parser parser) +{ + return curBase; +} + +int +xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser) +{ + return nSpecifiedAtts; +} + +int +xmlrpc_XML_GetIdAttributeIndex(XML_Parser parser) +{ + return idAttIndex; +} + +void +xmlrpc_XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end) +{ + startElementHandler = start; + endElementHandler = end; +} + +void +xmlrpc_XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler) +{ + characterDataHandler = handler; +} + +void +xmlrpc_XML_SetProcessingInstructionHandler( + XML_Parser parser, + XML_ProcessingInstructionHandler handler) +{ + processingInstructionHandler = handler; +} + +void +xmlrpc_XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler) +{ + commentHandler = handler; +} + +void +xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end) +{ + startCdataSectionHandler = start; + endCdataSectionHandler = end; +} + +void +xmlrpc_XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler) +{ + defaultHandler = handler; + defaultExpandInternalEntities = 0; +} + +void +xmlrpc_XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler) +{ + defaultHandler = handler; + defaultExpandInternalEntities = 1; +} + +void +xmlrpc_XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end) +{ + startDoctypeDeclHandler = start; + endDoctypeDeclHandler = end; +} + +void +xmlrpc_XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler) +{ + unparsedEntityDeclHandler = handler; +} + +void +xmlrpc_XML_SetExternalParsedEntityDeclHandler( + XML_Parser parser, + XML_ExternalParsedEntityDeclHandler handler) +{ + externalParsedEntityDeclHandler = handler; +} + +void +xmlrpc_XML_SetInternalParsedEntityDeclHandler( + XML_Parser parser, + XML_InternalParsedEntityDeclHandler handler) +{ + internalParsedEntityDeclHandler = handler; +} + +void +xmlrpc_XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler) +{ + notationDeclHandler = handler; +} + +void +xmlrpc_XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end) +{ + startNamespaceDeclHandler = start; + endNamespaceDeclHandler = end; +} + +void +xmlrpc_XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler) +{ + notStandaloneHandler = handler; +} + +void +xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler) +{ + externalEntityRefHandler = handler; +} + +void +xmlrpc_XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) +{ + if (arg) + externalEntityRefHandlerArg = arg; + else + externalEntityRefHandlerArg = parser; +} + +void +xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *data) +{ + unknownEncodingHandler = handler; + unknownEncodingHandlerData = data; +} + + + +int +xmlrpc_XML_SetParamEntityParsing( + XML_Parser const parser ATTR_UNUSED, + enum XML_ParamEntityParsing const parsing) { + + int retval; + + paramEntityParsing = parsing; + retval = 1; + + return retval; +} + + + +static Processor errorProcessor; + +static void +errorProcessor(XML_Parser const parser ATTR_UNUSED, + const char * const s ATTR_UNUSED, + const char * const end ATTR_UNUSED, + const char ** const nextPtr ATTR_UNUSED, + enum XML_Error * const errorCodeP, + const char ** const errorP) { + + *errorP = errorString; + *errorCodeP = errorCode; +} + + + +static void +parseFinalLen0(Parser * const parser, + int * const retvalP) { + + positionPtr = bufferPtr; + parseEndPtr = bufferEnd; + + processor(parser, bufferPtr, bufferEnd, 0, &errorCode, &errorString); + + if (errorCode == XML_ERROR_NONE) + *retvalP = 1; + else { + eventEndPtr = eventPtr; + processor = errorProcessor; + *retvalP = 0; + } +} + + + +static void +parseNoBuffer(Parser * const parser, + const char * const s, + int const len, + bool const isFinal, + int * const succeededP) { + + parseEndByteIndex += len; + positionPtr = s; + + if (isFinal) { + processor(parser, s, parseEndPtr = s + len, 0, + &errorCode, &errorString); + if (errorCode == XML_ERROR_NONE) + *succeededP = true; + else { + eventEndPtr = eventPtr; + processor = errorProcessor; + *succeededP = false; + } + } else { + const char * end; + + parseEndPtr = s + len; + processor(parser, s, s + len, &end, &errorCode, &errorString); + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + *succeededP = false; + } else { + int const nLeftOver = s + len - end; + XmlUpdatePosition(parser->m_encoding, positionPtr, end, &position); + if (nLeftOver > 0) { + if (buffer == 0 || nLeftOver > bufferLim - buffer) { + REALLOCARRAY(buffer, len * 2); + if (buffer) + bufferLim = buffer + len * 2; + } + + if (buffer) { + memcpy(buffer, end, nLeftOver); + bufferPtr = buffer; + bufferEnd = buffer + nLeftOver; + *succeededP = true; + } else { + errorCode = XML_ERROR_NO_MEMORY; + eventPtr = eventEndPtr = 0; + processor = errorProcessor; + *succeededP = false; + } + } else + *succeededP = true; + } + } +} + + + +int +xmlrpc_XML_Parse(XML_Parser const xmlParserP, + const char * const s, + int const len, + int const isFinal) { + + Parser * const parser = (Parser *) xmlParserP; + + int retval; + + if (errorString) { + xmlrpc_strfree(errorString); + errorString = NULL; + } + + if (len == 0) { + if (!isFinal) + retval = 1; + else + parseFinalLen0(parser, &retval); + } else if (bufferPtr == bufferEnd) + parseNoBuffer(parser, s, len, isFinal, &retval); + else { + memcpy(xmlrpc_XML_GetBuffer(parser, len), s, len); + retval = xmlrpc_XML_ParseBuffer(parser, len, isFinal); + } + return retval; +} + + + +int +xmlrpc_XML_ParseBuffer(XML_Parser const xmlParserP, + int const len, + int const isFinal) { + + Parser * const parser = (Parser *)xmlParserP; + + const char * const start = bufferPtr; + + if (errorString) { + xmlrpc_strfree(errorString); + errorString = NULL; + } + + positionPtr = start; + bufferEnd += len; + parseEndByteIndex += len; + processor(xmlParserP, start, parseEndPtr = bufferEnd, + isFinal ? (const char **)0 : &bufferPtr, + &errorCode, &errorString); + if (errorCode == XML_ERROR_NONE) { + if (!isFinal) + XmlUpdatePosition(parser->m_encoding, positionPtr, bufferPtr, + &position); + return 1; + } else { + eventEndPtr = eventPtr; + processor = errorProcessor; + return 0; + } +} + +void * +xmlrpc_XML_GetBuffer(XML_Parser parser, int len) +{ + if (len > bufferLim - bufferEnd) { + /* FIXME avoid integer overflow */ + int neededSize = len + (bufferEnd - bufferPtr); + if (neededSize <= bufferLim - buffer) { + memmove(buffer, bufferPtr, bufferEnd - bufferPtr); + bufferEnd = buffer + (bufferEnd - bufferPtr); + bufferPtr = buffer; + } + else { + char *newBuf; + int bufferSize = bufferLim - bufferPtr; + if (bufferSize == 0) + bufferSize = INIT_BUFFER_SIZE; + do { + bufferSize *= 2; + } while (bufferSize < neededSize); + newBuf = malloc(bufferSize); + if (newBuf == 0) { + errorCode = XML_ERROR_NO_MEMORY; + return 0; + } + bufferLim = newBuf + bufferSize; + if (bufferPtr) { + memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); + free(buffer); + } + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; + } + } + return bufferEnd; +} + + + +enum XML_Error +xmlrpc_XML_GetErrorCode(XML_Parser const parser) { + + return errorCode; +} + + + +const char * +xmlrpc_XML_GetErrorString(XML_Parser const parser) { + + if (errorString) + return errorString; + else if (errorCode == XML_ERROR_NONE) + return NULL; + else + return xmlrpc_XML_ErrorString(errorCode); +} + + + +long +xmlrpc_XML_GetCurrentByteIndex(XML_Parser parser) +{ + if (eventPtr) + return parseEndByteIndex - (parseEndPtr - eventPtr); + return -1; +} + +int +xmlrpc_XML_GetCurrentByteCount(XML_Parser parser) +{ + if (eventEndPtr && eventPtr) + return eventEndPtr - eventPtr; + return 0; +} + + + +int +xmlrpc_XML_GetCurrentLineNumber(XML_Parser const xmlParserP) { + + Parser * const parser = (Parser *) xmlParserP; + + if (eventPtr) { + XmlUpdatePosition(parser->m_encoding, positionPtr, eventPtr, + &position); + positionPtr = eventPtr; + } + return position.lineNumber + 1; +} + + + +int +xmlrpc_XML_GetCurrentColumnNumber(XML_Parser const xmlParserP) { + + Parser * const parser = (Parser *) xmlParserP; + + if (eventPtr) { + XmlUpdatePosition(parser->m_encoding, positionPtr, eventPtr, + &position); + positionPtr = eventPtr; + } + return position.columnNumber; +} + + + +void +xmlrpc_XML_DefaultCurrent(XML_Parser const xmlParserP) { + + Parser * const parser = (Parser *) xmlParserP; + + if (defaultHandler) { + if (openInternalEntities) + reportDefault(xmlParserP, + internalEncoding, + openInternalEntities->internalEventPtr, + openInternalEntities->internalEventEndPtr); + else + reportDefault(xmlParserP, parser->m_encoding, + eventPtr, eventEndPtr); + } +} + +const XML_LChar * +xmlrpc_XML_ErrorString(int const code) { + + static const XML_LChar * const message[] = { + /* NONE */ NULL, + /* NO_MEMORY */ XML_T("out of memory"), + /* SYNTAX */ XML_T("syntax error"), + /* NO_ELEMENTS */ XML_T("no element found"), + /* INVALID_TOKEN */ XML_T("not well-formed"), + /* UNCLOSED_TOKEN */ XML_T("unclosed token"), + /* PARTIAL_CHAR */ XML_T("unclosed token"), + /* TAG_MISMATCH */ XML_T("mismatched tag"), + /* DUPLICATE_ATTRIBUTE */ XML_T("duplicate attribute"), + /* JUNK_AFTER_DOC_ELEMENT */ XML_T("junk after document element"), + /* PARAM_ENTITY_REF */ + XML_T("illegal parameter entity reference"), + /* UNDEFINED_ENTITY */ XML_T("undefined entity"), + /* RECURSIVE_ENTITY_REF */ XML_T("recursive entity reference"), + /* ASYNC_ENTITY */ XML_T("asynchronous entity"), + /* BAD_CHAR_REF */ + XML_T("reference to invalid character number"), + /* BINARY_ENTITY_REF */ XML_T("reference to binary entity"), + /* ATTRIBUTE_EXTERNAL_ENTITY_REF */ + XML_T("reference to external entity in attribute"), + /* MISPLACED_XML_PI */ + XML_T("xml processing instruction not at start " + "of external entity"), + /* UNKNOWN_ENCODING */ XML_T("unknown encoding"), + /* INCORRECT_ENCODING */ + XML_T("encoding specified in XML declaration is incorrect"), + /* UNCLOSED_CDATA_SECTION */ XML_T("unclosed CDATA section"), + /* EXTERNAL_ENTITY_HANDLING */ + XML_T("error in processing external entity reference"), + /* NOT_STANDALONE */ XML_T("document is not standalone") + }; + + const XML_LChar * retval; + + if (code > 0 && (unsigned)code < ARRAY_SIZE(message)) + retval = message[code]; + else + retval = NULL; + + return retval; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlparse/xmlparse.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlparse/xmlparse.h new file mode 100644 index 0000000..2b8c701 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlparse/xmlparse.h @@ -0,0 +1,556 @@ +/* + Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + See the file copying.txt for copying permission. +*/ + +#ifndef XMLPARSE_H_INCLUDED +#define XMLPARSE_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef XMLPARSEAPI +#define XMLPARSEAPI /* as nothing */ +#endif + +typedef void *XML_Parser; + +#ifdef XML_UNICODE_WCHAR_T + +/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t + uses Unicode. +*/ +/* Information is UTF-16 encoded as wchar_ts */ + +#ifndef XML_UNICODE +#define XML_UNICODE +#endif + +#include +typedef wchar_t XML_Char; +typedef wchar_t XML_LChar; + +#else /* not XML_UNICODE_WCHAR_T */ + +#ifdef XML_UNICODE + +/* Information is UTF-16 encoded as unsigned shorts */ +typedef unsigned short XML_Char; +typedef char XML_LChar; + +#else /* not XML_UNICODE */ + +/* Information is UTF-8 encoded. */ +typedef char XML_Char; +typedef char XML_LChar; + +#endif /* not XML_UNICODE */ + +#endif /* not XML_UNICODE_WCHAR_T */ + + +/* Constructs a new parser; encoding is the encoding specified by the external +protocol or null if there is none specified. */ + +XML_Parser XMLPARSEAPI +xmlrpc_XML_ParserCreate(const XML_Char * const encoding); + +/* Constructs a new parser and namespace processor. Element type names +and attribute names that belong to a namespace will be expanded; +unprefixed attribute names are never expanded; unprefixed element type +names are expanded only if there is a default namespace. The expanded +name is the concatenation of the namespace URI, the namespace separator character, +and the local part of the name. If the namespace separator is '\0' then +the namespace URI and the local part will be concatenated without any +separator. When a namespace is not declared, the name and prefix will be +passed through without expansion. */ + +XML_Parser XMLPARSEAPI +xmlrpc_XML_ParserCreateNS(const XML_Char * const encoding, + XML_Char const namespaceSeparator); + + +/* atts is array of name/value pairs, terminated by 0; + names and values are 0 terminated. */ + +typedef void (*XML_StartElementHandler)(void *userData, + const XML_Char *name, + const XML_Char **atts); + +typedef void (*XML_EndElementHandler)(void *userData, + const XML_Char *name); + +/* s is not 0 terminated. */ +typedef void (*XML_CharacterDataHandler)(void *userData, + const XML_Char *s, + int len); + +/* target and data are 0 terminated */ +typedef void (*XML_ProcessingInstructionHandler)(void *userData, + const XML_Char *target, + const XML_Char *data); + +/* data is 0 terminated */ +typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data); + +typedef void (*XML_StartCdataSectionHandler)(void *userData); +typedef void (*XML_EndCdataSectionHandler)(void *userData); + +/* This is called for any characters in the XML document for +which there is no applicable handler. This includes both +characters that are part of markup which is of a kind that is +not reported (comments, markup declarations), or characters +that are part of a construct which could be reported but +for which no handler has been supplied. The characters are passed +exactly as they were in the XML document except that +they will be encoded in UTF-8. Line boundaries are not normalized. +Note that a byte order mark character is not passed to the default handler. +There are no guarantees about how characters are divided between calls +to the default handler: for example, a comment might be split between +multiple calls. */ + +typedef void (*XML_DefaultHandler)(void *userData, + const XML_Char *s, + int len); + +/* This is called for the start of the DOCTYPE declaration when the +name of the DOCTYPE is encountered. */ +typedef void (*XML_StartDoctypeDeclHandler)(void *userData, + const XML_Char *doctypeName); + +/* This is called for the start of the DOCTYPE declaration when the +closing > is encountered, but after processing any external subset. */ +typedef void (*XML_EndDoctypeDeclHandler)(void *userData); + +/* This is called for a declaration of an unparsed (NDATA) +entity. The base argument is whatever was set by XML_SetBase. +The entityName, systemId and notationName arguments will never be null. +The other arguments may be. */ + +typedef void (*XML_UnparsedEntityDeclHandler)(void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +/* This is called for a declaration of notation. +The base argument is whatever was set by XML_SetBase. +The notationName will never be null. The other arguments can be. */ + +typedef void (*XML_NotationDeclHandler)(void *userData, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +typedef void (*XML_ExternalParsedEntityDeclHandler)(void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +typedef void (*XML_InternalParsedEntityDeclHandler)(void *userData, + const XML_Char *entityName, + const XML_Char *replacementText, + int replacementTextLength); + +/* When namespace processing is enabled, these are called once for +each namespace declaration. The call to the start and end element +handlers occur between the calls to the start and end namespace +declaration handlers. For an xmlns attribute, prefix will be null. +For an xmlns="" attribute, uri will be null. */ + +typedef void (*XML_StartNamespaceDeclHandler)(void *userData, + const XML_Char *prefix, + const XML_Char *uri); + +typedef void (*XML_EndNamespaceDeclHandler)(void *userData, + const XML_Char *prefix); + +/* This is called if the document is not standalone (it has an +external subset or a reference to a parameter entity, but does not +have standalone="yes"). If this handler returns 0, then processing +will not continue, and the parser will return a +XML_ERROR_NOT_STANDALONE error. */ + +typedef int (*XML_NotStandaloneHandler)(void *userData); + +/* This is called for a reference to an external parsed general entity. +The referenced entity is not automatically parsed. +The application can parse it immediately or later using +XML_ExternalEntityParserCreate. +The parser argument is the parser parsing the entity containing the reference; +it can be passed as the parser argument to XML_ExternalEntityParserCreate. +The systemId argument is the system identifier as specified in the entity declaration; +it will not be null. +The base argument is the system identifier that should be used as the base for +resolving systemId if systemId was relative; this is set by XML_SetBase; +it may be null. +The publicId argument is the public identifier as specified in the entity declaration, +or null if none was specified; the whitespace in the public identifier +will have been normalized as required by the XML spec. +The context argument specifies the parsing context in the format +expected by the context argument to +XML_ExternalEntityParserCreate; context is valid only until the handler +returns, so if the referenced entity is to be parsed later, it must be copied. +The handler should return 0 if processing should not continue because of +a fatal error in the handling of the external entity. +In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING +error. +Note that unlike other handlers the first argument is the parser, not userData. */ + +typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* This structure is filled in by the XML_UnknownEncodingHandler +to provide information to the parser about encodings that are unknown +to the parser. +The map[b] member gives information about byte sequences +whose first byte is b. +If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. +If map[b] is -1, then the byte sequence is malformed. +If map[b] is -n, where n >= 2, then b is the first byte of an n-byte +sequence that encodes a single Unicode scalar value. +The data member will be passed as the first argument to the convert function. +The convert function is used to convert multibyte sequences; +s will point to a n-byte sequence where map[(unsigned char)*s] == -n. +The convert function must return the Unicode scalar value +represented by this byte sequence or -1 if the byte sequence is malformed. +The convert function may be null if the encoding is a single-byte encoding, +that is if map[b] >= -1 for all bytes b. +When the parser is finished with the encoding, then if release is not null, +it will call release passing it the data member; +once release has been called, the convert function will not be called again. + +Expat places certain restrictions on the encodings that are supported +using this mechanism. + +1. Every ASCII character that can appear in a well-formed XML document, +other than the characters + + $@\^`{}~ + +must be represented by a single byte, and that byte must be the +same byte that represents that character in ASCII. + +2. No character may require more than 4 bytes to encode. + +3. All characters encoded must have Unicode scalar values <= 0xFFFF, +(ie characters that would be encoded by surrogates in UTF-16 +are not allowed). Note that this restriction doesn't apply to +the built-in support for UTF-8 and UTF-16. + +4. No Unicode character may be encoded by more than one distinct sequence +of bytes. */ + +typedef struct { + int map[256]; + void *data; + int (*convert)(void *data, const char *s); + void (*release)(void *data); +} XML_Encoding; + +/* This is called for an encoding that is unknown to the parser. +The encodingHandlerData argument is that which was passed as the +second argument to XML_SetUnknownEncodingHandler. +The name argument gives the name of the encoding as specified in +the encoding declaration. +If the callback can provide information about the encoding, +it must fill in the XML_Encoding structure, and return 1. +Otherwise it must return 0. +If info does not describe a suitable encoding, +then the parser will return an XML_UNKNOWN_ENCODING error. */ + +typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, + const XML_Char *name, + XML_Encoding *info); + +void XMLPARSEAPI +xmlrpc_XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end); + +void XMLPARSEAPI +xmlrpc_XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler); + +void XMLPARSEAPI +xmlrpc_XML_SetProcessingInstructionHandler( + XML_Parser parser, + XML_ProcessingInstructionHandler handler); +void XMLPARSEAPI +xmlrpc_XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler); + +void XMLPARSEAPI +xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end); + +/* This sets the default handler and also inhibits expansion of + internal entities. The entity reference will be passed to the default + handler. +*/ + +void XMLPARSEAPI +xmlrpc_XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler); + +/* This sets the default handler but does not inhibit expansion of internal entities. +The entity reference will not be passed to the default handler. */ + +void XMLPARSEAPI +xmlrpc_XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler); + +void XMLPARSEAPI +xmlrpc_XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end); + +void XMLPARSEAPI +xmlrpc_XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler); + +void XMLPARSEAPI +xmlrpc_XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler); + +void XMLPARSEAPI +xmlrpc_XML_SetExternalParsedEntityDeclHandler( + XML_Parser parser, + XML_ExternalParsedEntityDeclHandler handler); + +void XMLPARSEAPI +xmlrpc_XML_SetInternalParsedEntityDeclHandler( + XML_Parser parser, + XML_InternalParsedEntityDeclHandler handler); + +void XMLPARSEAPI +xmlrpc_XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end); + +void XMLPARSEAPI +xmlrpc_XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler); + +void XMLPARSEAPI +xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler); + +/* If a non-null value for arg is specified here, then it will be + passed as the first argument to the external entity ref handler + instead of the parser object. +*/ +void XMLPARSEAPI +xmlrpc_XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); + +void XMLPARSEAPI +xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *encodingHandlerData); + +/* This can be called within a handler for a start element, end element, + processing instruction or character data. It causes the corresponding + markup to be passed to the default handler. +*/ +void XMLPARSEAPI +xmlrpc_XML_DefaultCurrent(XML_Parser parser); + +/* This value is passed as the userData argument to callbacks. */ +void XMLPARSEAPI +xmlrpc_XML_SetUserData(XML_Parser parser, void *userData); + +/* Returns the last value set by XML_SetUserData or null. */ +#define XML_GetUserData(parser) (*(void **)(parser)) + +/* This is equivalent to supplying an encoding argument +to XML_ParserCreate. It must not be called after XML_Parse +or XML_ParseBuffer. */ + +int XMLPARSEAPI +xmlrpc_XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); + +/* If this function is called, then the parser will be passed + as the first argument to callbacks instead of userData. + The userData will still be accessible using XML_GetUserData. +*/ +void XMLPARSEAPI +xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser); + +/* Sets the base to be used for resolving relative URIs in system + identifiers in declarations. Resolving relative identifiers is left + to the application: this value will be passed through as the base + argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler + and XML_UnparsedEntityDeclHandler. The base argument will be copied. + Returns zero if out of memory, non-zero otherwise. +*/ +int XMLPARSEAPI +xmlrpc_XML_SetBase(XML_Parser parser, const XML_Char *base); + +const XML_Char XMLPARSEAPI * +xmlrpc_XML_GetBase(XML_Parser parser); + +/* Returns the number of the attribute/value pairs passed in last call + to the XML_StartElementHandler that were specified in the start-tag + rather than defaulted. Each attribute/value pair counts as 2; thus + this correspondds to an index into the atts array passed to the + XML_StartElementHandler. +*/ +int XMLPARSEAPI +xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser); + +/* Returns the index of the ID attribute passed in the last call to + XML_StartElementHandler, or -1 if there is no ID attribute. Each + attribute/value pair counts as 2; thus this correspondds to an index + into the atts array passed to the XML_StartElementHandler. +*/ +int XMLPARSEAPI +xmlrpc_XML_GetIdAttributeIndex(XML_Parser parser); + +/* Parses some input. Returns 0 if a fatal error is detected. + The last call to XML_Parse must have isFinal true; + len may be zero for this call (or any other). +*/ +int XMLPARSEAPI +xmlrpc_XML_Parse(XML_Parser const parser, const char * const s, int const len, int const isFinal); + +void XMLPARSEAPI * +xmlrpc_XML_GetBuffer(XML_Parser parser, int len); + +int XMLPARSEAPI +xmlrpc_XML_ParseBuffer(XML_Parser const parser, int const len, int const isFinal); + +/* Creates an XML_Parser object that can parse an external general + entity; context is a '\0'-terminated string specifying the parse + context; encoding is a '\0'-terminated string giving the name of the + externally specified encoding, or null if there is no externally + specified encoding. The context string consists of a sequence of + tokens separated by formfeeds (\f); a token consisting of a name + specifies that the general entity of the name is open; a token of the + form prefix=uri specifies the namespace for a particular prefix; a + token of the form =uri specifies the default namespace. This can be + called at any point after the first call to an + ExternalEntityRefHandler so longer as the parser has not yet been + freed. The new parser is completely independent and may safely be + used in a separate thread. The handlers and userData are initialized + from the parser argument. Returns 0 if out of memory. Otherwise + returns a new XML_Parser object. +*/ +XML_Parser XMLPARSEAPI +xmlrpc_XML_ExternalEntityParserCreate(XML_Parser parser, + const XML_Char *context, + const XML_Char *encoding); + +enum XML_ParamEntityParsing { + XML_PARAM_ENTITY_PARSING_NEVER, + XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, + XML_PARAM_ENTITY_PARSING_ALWAYS +}; + +/* Controls parsing of parameter entities (including the external DTD + subset). If parsing of parameter entities is enabled, then references + to external parameter entities (including the external DTD subset) + will be passed to the handler set with + XML_SetExternalEntityRefHandler. The context passed will be 0. + Unlike external general entities, external parameter entities can only + be parsed synchronously. If the external parameter entity is to be + parsed, it must be parsed during the call to the external entity ref + handler: the complete sequence of XML_ExternalEntityParserCreate, + XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during + this call. After XML_ExternalEntityParserCreate has been called to + create the parser for the external parameter entity (context must be 0 + for this call), it is illegal to make any calls on the old parser + until XML_ParserFree has been called on the newly created parser. If + the library has been compiled without support for parameter entity + parsing (ie without XML_DTD being defined), then + XML_SetParamEntityParsing will return 0 if parsing of parameter + entities is requested; otherwise it will return non-zero. +*/ +int XMLPARSEAPI +xmlrpc_XML_SetParamEntityParsing(XML_Parser parser, + enum XML_ParamEntityParsing parsing); + +enum XML_Error { + XML_ERROR_NONE, + XML_ERROR_NO_MEMORY, + XML_ERROR_SYNTAX, + XML_ERROR_NO_ELEMENTS, + XML_ERROR_INVALID_TOKEN, + XML_ERROR_UNCLOSED_TOKEN, + XML_ERROR_PARTIAL_CHAR, + XML_ERROR_TAG_MISMATCH, + XML_ERROR_DUPLICATE_ATTRIBUTE, + XML_ERROR_JUNK_AFTER_DOC_ELEMENT, + XML_ERROR_PARAM_ENTITY_REF, + XML_ERROR_UNDEFINED_ENTITY, + XML_ERROR_RECURSIVE_ENTITY_REF, + XML_ERROR_ASYNC_ENTITY, + XML_ERROR_BAD_CHAR_REF, + XML_ERROR_BINARY_ENTITY_REF, + XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, + XML_ERROR_MISPLACED_XML_PI, + XML_ERROR_UNKNOWN_ENCODING, + XML_ERROR_INCORRECT_ENCODING, + XML_ERROR_UNCLOSED_CDATA_SECTION, + XML_ERROR_EXTERNAL_ENTITY_HANDLING, + XML_ERROR_NOT_STANDALONE +}; + +/* If xmlrpc_XML_Parse or xmlrpc_XML_ParseBuffer have returned 0, then + xmlrpc_XML_GetErrorString and xmlrpc_XML_GetErrorCode return + information about the error. +*/ + +enum XML_Error XMLPARSEAPI +xmlrpc_XML_GetErrorCode(XML_Parser const parser); + +const char * XMLPARSEAPI +xmlrpc_XML_GetErrorString(XML_Parser const parser); + +/* These functions return information about the current parse location. + They may be called when XML_Parse or XML_ParseBuffer return 0; + in this case the location is the location of the character at which + the error was detected. + They may also be called from any other callback called to report + some parse event; in this the location is the location of the first + of the sequence of characters that generated the event. +*/ + +int XMLPARSEAPI +xmlrpc_XML_GetCurrentLineNumber(XML_Parser parser); +int XMLPARSEAPI +xmlrpc_XML_GetCurrentColumnNumber(XML_Parser parser); +long XMLPARSEAPI +xmlrpc_XML_GetCurrentByteIndex(XML_Parser parser); + +/* Return the number of bytes in the current event. +Returns 0 if the event is in an internal entity. */ + +int XMLPARSEAPI +xmlrpc_XML_GetCurrentByteCount(XML_Parser parser); + +/* For backwards compatibility with previous versions. */ +#define XML_GetErrorLineNumber XML_GetCurrentLineNumber +#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber +#define XML_GetErrorByteIndex XML_GetCurrentByteIndex + +/* Frees memory used by the parser. */ +void XMLPARSEAPI +xmlrpc_XML_ParserFree(XML_Parser parser); + +/* Returns a string describing the error. */ +const XML_LChar XMLPARSEAPI * +xmlrpc_XML_ErrorString(int const code); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/ascii.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/ascii.h new file mode 100644 index 0000000..a8a621c --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/ascii.h @@ -0,0 +1,86 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#define ASCII_A 0x41 +#define ASCII_B 0x42 +#define ASCII_C 0x43 +#define ASCII_D 0x44 +#define ASCII_E 0x45 +#define ASCII_F 0x46 +#define ASCII_G 0x47 +#define ASCII_H 0x48 +#define ASCII_I 0x49 +#define ASCII_J 0x4A +#define ASCII_K 0x4B +#define ASCII_L 0x4C +#define ASCII_M 0x4D +#define ASCII_N 0x4E +#define ASCII_O 0x4F +#define ASCII_P 0x50 +#define ASCII_Q 0x51 +#define ASCII_R 0x52 +#define ASCII_S 0x53 +#define ASCII_T 0x54 +#define ASCII_U 0x55 +#define ASCII_V 0x56 +#define ASCII_W 0x57 +#define ASCII_X 0x58 +#define ASCII_Y 0x59 +#define ASCII_Z 0x5A + +#define ASCII_a 0x61 +#define ASCII_b 0x62 +#define ASCII_c 0x63 +#define ASCII_d 0x64 +#define ASCII_e 0x65 +#define ASCII_f 0x66 +#define ASCII_g 0x67 +#define ASCII_h 0x68 +#define ASCII_i 0x69 +#define ASCII_j 0x6A +#define ASCII_k 0x6B +#define ASCII_l 0x6C +#define ASCII_m 0x6D +#define ASCII_n 0x6E +#define ASCII_o 0x6F +#define ASCII_p 0x70 +#define ASCII_q 0x71 +#define ASCII_r 0x72 +#define ASCII_s 0x73 +#define ASCII_t 0x74 +#define ASCII_u 0x75 +#define ASCII_v 0x76 +#define ASCII_w 0x77 +#define ASCII_x 0x78 +#define ASCII_y 0x79 +#define ASCII_z 0x7A + +#define ASCII_0 0x30 +#define ASCII_1 0x31 +#define ASCII_2 0x32 +#define ASCII_3 0x33 +#define ASCII_4 0x34 +#define ASCII_5 0x35 +#define ASCII_6 0x36 +#define ASCII_7 0x37 +#define ASCII_8 0x38 +#define ASCII_9 0x39 + +#define ASCII_TAB 0x09 +#define ASCII_SPACE 0x20 +#define ASCII_EXCL 0x21 +#define ASCII_QUOT 0x22 +#define ASCII_AMP 0x26 +#define ASCII_APOS 0x27 +#define ASCII_MINUS 0x2D +#define ASCII_PERIOD 0x2E +#define ASCII_COLON 0x3A +#define ASCII_SEMI 0x3B +#define ASCII_LT 0x3C +#define ASCII_EQUALS 0x3D +#define ASCII_GT 0x3E +#define ASCII_LSQB 0x5B +#define ASCII_RSQB 0x5D +#define ASCII_UNDERSCORE 0x5F diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/asciitab.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/asciitab.h new file mode 100644 index 0000000..e994576 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/asciitab.h @@ -0,0 +1,37 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, +/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, +/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, +/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, +/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, +/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, +/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, +/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, +/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, +/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, +/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/dllmain.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/dllmain.c new file mode 100644 index 0000000..d5aa4a3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/dllmain.c @@ -0,0 +1,15 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#define STRICT 1 +#define WIN32_LEAN_AND_MEAN 1 + +#include + +BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + return TRUE; +} + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/iasciitab.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/iasciitab.h new file mode 100644 index 0000000..2694d9d --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/iasciitab.h @@ -0,0 +1,38 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ +/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, +/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, +/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, +/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, +/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, +/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, +/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, +/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, +/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, +/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, +/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/latin1tab.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/latin1tab.h new file mode 100644 index 0000000..6e01d50 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/latin1tab.h @@ -0,0 +1,37 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, +/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, +/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, +/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/nametab.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/nametab.h new file mode 100644 index 0000000..b05e62c --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/nametab.h @@ -0,0 +1,150 @@ +static const unsigned namingBitmap[] = { +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, +0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, +0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, +0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, +0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, +0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, +0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, +0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, +0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, +0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, +0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, +0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, +0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, +0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, +0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, +0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, +0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, +0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, +0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, +0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, +0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, +0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, +0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, +0x40000000, 0xF580C900, 0x00000007, 0x02010800, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, +0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, +0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, +0x00000000, 0x00004C40, 0x00000000, 0x00000000, +0x00000007, 0x00000000, 0x00000000, 0x00000000, +0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, +0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, +0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, +0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, +0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, +0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, +0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, +0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, +0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, +0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, +0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, +0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, +0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, +0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, +0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, +0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, +0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, +0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, +0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, +0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, +0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, +0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, +0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, +0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, +0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, +0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, +0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, +0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, +}; +static const unsigned char nmstrtPages[] = { +0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, +0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, +0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const unsigned char namePages[] = { +0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, +0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, +0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, +0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/utf8tab.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/utf8tab.h new file mode 100644 index 0000000..28d9b59 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/utf8tab.h @@ -0,0 +1,38 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + + +/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, +/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmldef.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmldef.h new file mode 100644 index 0000000..2ef9d49 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmldef.h @@ -0,0 +1,49 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#include + +#ifdef XML_WINLIB + +#define WIN32_LEAN_AND_MEAN +#ifndef STRICT +#define STRICT 1 +#endif +#include + +#define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define calloc(x, y) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)*(y)) +#define free(x) HeapFree(GetProcessHeap(), 0, (x)) +#define realloc(x, y) HeapReAlloc(GetProcessHeap(), 0, x, y) +#define abort() /* as nothing */ + +#else /* not XML_WINLIB */ + +#include + +#endif /* not XML_WINLIB */ + +/* This file can be used for any definitions needed in +particular environments. */ + +/* Mozilla specific defines */ + +#ifdef MOZILLA_CLIENT + +#include "nspr.h" +#define malloc(x) PR_Malloc((size_t)(x)) +#define realloc(x, y) PR_Realloc((x), (size_t)(y)) +#define calloc(x, y) PR_Calloc((x),(y)) +#define free(x) PR_Free(x) +#if PR_BYTES_PER_INT != 4 +#define int int32 +#endif + +/* Enable Unicode string processing in expat. */ +#ifndef XML_UNICODE +#define XML_UNICODE +#endif + +#endif /* MOZILLA_CLIENT */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmlrole.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmlrole.c new file mode 100644 index 0000000..8219713 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmlrole.c @@ -0,0 +1,1262 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ +#include "xmlrpc_config.h" + +#include "xmldef.h" +#include "xmlrole.h" +#include "ascii.h" + +/* Doesn't check: + + that ,| are not mixed in a model group + content of literals + +*/ + +static const char KW_ANY[] = { ASCII_A, ASCII_N, ASCII_Y, '\0' }; +static const char KW_ATTLIST[] = { ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' }; +static const char KW_CDATA[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_DOCTYPE[] = { ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' }; +static const char KW_ELEMENT[] = { ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' }; +static const char KW_EMPTY[] = { ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' }; +static const char KW_ENTITIES[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' }; +static const char KW_ENTITY[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' }; +static const char KW_FIXED[] = { ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' }; +static const char KW_ID[] = { ASCII_I, ASCII_D, '\0' }; +static const char KW_IDREF[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' }; +static const char KW_IDREFS[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' }; +static const char KW_IGNORE[] = { ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' }; +static const char KW_IMPLIED[] = { ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' }; +static const char KW_INCLUDE[] = { ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' }; +static const char KW_NDATA[] = { ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_NMTOKEN[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' }; +static const char KW_NMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' }; +static const char KW_NOTATION[] = { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, '\0' }; +static const char KW_PCDATA[] = { ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_PUBLIC[] = { ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' }; +static const char KW_REQUIRED[] = { ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, '\0' }; +static const char KW_SYSTEM[] = { ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' }; + +#ifndef MIN_BYTES_PER_CHAR +#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) +#endif + +#define setTopLevel(state) \ + ((state)->handler = ((state)->documentEntity \ + ? internalSubset \ + : externalSubset1)) + +typedef int PROLOG_HANDLER(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc); + +static PROLOG_HANDLER + prolog0, prolog1, prolog2, + doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, + internalSubset, + entity0, entity1, entity2, entity3, entity4, entity5, entity6, + entity7, entity8, entity9, + notation0, notation1, notation2, notation3, notation4, + attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, + attlist7, attlist8, attlist9, + element0, element1, element2, element3, element4, element5, element6, + element7, + externalSubset0, externalSubset1, + condSect0, condSect1, condSect2, + declClose, + error; + +static +int common(PROLOG_STATE *state, int tok); + +static +int prolog0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + state->handler = prolog1; + return XML_ROLE_NONE; + case XML_TOK_XML_DECL: + state->handler = prolog1; + return XML_ROLE_XML_DECL; + case XML_TOK_PI: + state->handler = prolog1; + return XML_ROLE_NONE; + case XML_TOK_COMMENT: + state->handler = prolog1; + case XML_TOK_BOM: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (!XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_DOCTYPE)) + break; + state->handler = doctype0; + return XML_ROLE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static +int prolog1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PI: + case XML_TOK_COMMENT: + case XML_TOK_BOM: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (!XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_DOCTYPE)) + break; + state->handler = doctype0; + return XML_ROLE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static +int prolog2(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PI: + case XML_TOK_COMMENT: + return XML_ROLE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static +int doctype0(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = doctype1; + return XML_ROLE_DOCTYPE_NAME; + } + return common(state, tok); +} + +static +int doctype1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = internalSubset; + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = doctype3; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = doctype2; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + +static +int doctype2(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = doctype3; + return XML_ROLE_DOCTYPE_PUBLIC_ID; + } + return common(state, tok); +} + +static +int doctype3(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = doctype4; + return XML_ROLE_DOCTYPE_SYSTEM_ID; + } + return common(state, tok); +} + +static +int doctype4(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = internalSubset; + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + } + return common(state, tok); +} + +static +int doctype5(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + } + return common(state, tok); +} + +static +int internalSubset(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ENTITY)) { + state->handler = entity0; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ATTLIST)) { + state->handler = attlist0; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ELEMENT)) { + state->handler = element0; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_NOTATION)) { + state->handler = notation0; + return XML_ROLE_NONE; + } + break; + case XML_TOK_PI: + case XML_TOK_COMMENT: + return XML_ROLE_NONE; + case XML_TOK_PARAM_ENTITY_REF: + return XML_ROLE_PARAM_ENTITY_REF; + case XML_TOK_CLOSE_BRACKET: + state->handler = doctype5; + return XML_ROLE_NONE; + } + return common(state, tok); +} + + + +static +int externalSubset0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + state->handler = externalSubset1; + if (tok == XML_TOK_XML_DECL) + return XML_ROLE_TEXT_DECL; + return externalSubset1(state, tok, ptr, end, enc); +} + +static +int externalSubset1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_COND_SECT_OPEN: + state->handler = condSect0; + return XML_ROLE_NONE; + case XML_TOK_COND_SECT_CLOSE: + if (state->includeLevel == 0) + break; + state->includeLevel -= 1; + return XML_ROLE_NONE; + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_BRACKET: + break; + case XML_TOK_NONE: + if (state->includeLevel) + break; + return XML_ROLE_NONE; + default: + return internalSubset(state, tok, ptr, end, enc); + } + return common(state, tok); +} + + + +static +int entity0(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PERCENT: + state->handler = entity1; + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = entity2; + return XML_ROLE_GENERAL_ENTITY_NAME; + } + return common(state, tok); +} + +static +int entity1(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = entity7; + return XML_ROLE_PARAM_ENTITY_NAME; + } + return common(state, tok); +} + +static +int entity2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = entity4; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = entity3; + return XML_ROLE_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_ENTITY_VALUE; + } + return common(state, tok); +} + +static +int entity3(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = entity4; + return XML_ROLE_ENTITY_PUBLIC_ID; + } + return common(state, tok); +} + + +static +int entity4(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = entity5; + return XML_ROLE_ENTITY_SYSTEM_ID; + } + return common(state, tok); +} + +static +int entity5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) { + state->handler = entity6; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + +static +int entity6(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = declClose; + return XML_ROLE_ENTITY_NOTATION_NAME; + } + return common(state, tok); +} + +static +int entity7(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = entity9; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = entity8; + return XML_ROLE_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_ENTITY_VALUE; + } + return common(state, tok); +} + +static +int entity8(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = entity9; + return XML_ROLE_ENTITY_PUBLIC_ID; + } + return common(state, tok); +} + +static +int entity9(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_ENTITY_SYSTEM_ID; + } + return common(state, tok); +} + +static +int notation0(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = notation1; + return XML_ROLE_NOTATION_NAME; + } + return common(state, tok); +} + +static +int notation1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = notation3; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = notation2; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + +static +int notation2(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = notation4; + return XML_ROLE_NOTATION_PUBLIC_ID; + } + return common(state, tok); +} + +static +int notation3(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_NOTATION_SYSTEM_ID; + } + return common(state, tok); +} + +static +int notation4(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_NOTATION_SYSTEM_ID; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_NOTATION_NO_SYSTEM_ID; + } + return common(state, tok); +} + +static +int attlist0(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist1; + return XML_ROLE_ATTLIST_ELEMENT_NAME; + } + return common(state, tok); +} + +static +int attlist1(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist2; + return XML_ROLE_ATTRIBUTE_NAME; + } + return common(state, tok); +} + +static +int attlist2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + { + static const char *types[] = { + KW_CDATA, + KW_ID, + KW_IDREF, + KW_IDREFS, + KW_ENTITY, + KW_ENTITIES, + KW_NMTOKEN, + KW_NMTOKENS, + }; + int i; + for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) + if (XmlNameMatchesAscii(enc, ptr, end, types[i])) { + state->handler = attlist8; + return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; + } + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) { + state->handler = attlist5; + return XML_ROLE_NONE; + } + break; + case XML_TOK_OPEN_PAREN: + state->handler = attlist3; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int attlist3(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NMTOKEN: + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist4; + return XML_ROLE_ATTRIBUTE_ENUM_VALUE; + } + return common(state, tok); +} + +static +int attlist4(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = attlist8; + return XML_ROLE_NONE; + case XML_TOK_OR: + state->handler = attlist3; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int attlist5(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_PAREN: + state->handler = attlist6; + return XML_ROLE_NONE; + } + return common(state, tok); +} + + +static +int attlist6(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = attlist7; + return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; + } + return common(state, tok); +} + +static +int attlist7(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = attlist8; + return XML_ROLE_NONE; + case XML_TOK_OR: + state->handler = attlist6; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +/* default value */ +static +int attlist8(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_POUND_NAME: + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_IMPLIED)) { + state->handler = attlist1; + return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; + } + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_REQUIRED)) { + state->handler = attlist1; + return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; + } + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_FIXED)) { + state->handler = attlist9; + return XML_ROLE_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = attlist1; + return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; + } + return common(state, tok); +} + +static +int attlist9(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = attlist1; + return XML_ROLE_FIXED_ATTRIBUTE_VALUE; + } + return common(state, tok); +} + +static +int element0(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element1; + return XML_ROLE_ELEMENT_NAME; + } + return common(state, tok); +} + +static +int element1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) { + state->handler = declClose; + return XML_ROLE_CONTENT_EMPTY; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) { + state->handler = declClose; + return XML_ROLE_CONTENT_ANY; + } + break; + case XML_TOK_OPEN_PAREN: + state->handler = element2; + state->level = 1; + return XML_ROLE_GROUP_OPEN; + } + return common(state, tok); +} + +static +int element2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_POUND_NAME: + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_PCDATA)) { + state->handler = element3; + return XML_ROLE_CONTENT_PCDATA; + } + break; + case XML_TOK_OPEN_PAREN: + state->level = 2; + state->handler = element6; + return XML_ROLE_GROUP_OPEN; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT; + case XML_TOK_NAME_QUESTION: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_OPT; + case XML_TOK_NAME_ASTERISK: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_REP; + case XML_TOK_NAME_PLUS: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_PLUS; + } + return common(state, tok); +} + +static +int element3(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN: + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_OR: + state->handler = element4; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int element4(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element5; + return XML_ROLE_CONTENT_ELEMENT; + } + return common(state, tok); +} + +static +int element5(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_OR: + state->handler = element4; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int element6(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_PAREN: + state->level += 1; + return XML_ROLE_GROUP_OPEN; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT; + case XML_TOK_NAME_QUESTION: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_OPT; + case XML_TOK_NAME_ASTERISK: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_REP; + case XML_TOK_NAME_PLUS: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_PLUS; + } + return common(state, tok); +} + +static +int element7(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN: + state->level -= 1; + if (state->level == 0) + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->level -= 1; + if (state->level == 0) + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_CLOSE_PAREN_QUESTION: + state->level -= 1; + if (state->level == 0) + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_OPT; + case XML_TOK_CLOSE_PAREN_PLUS: + state->level -= 1; + if (state->level == 0) + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_PLUS; + case XML_TOK_COMMA: + state->handler = element6; + return XML_ROLE_GROUP_SEQUENCE; + case XML_TOK_OR: + state->handler = element6; + return XML_ROLE_GROUP_CHOICE; + } + return common(state, tok); +} + + + +static +int condSect0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) { + state->handler = condSect1; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) { + state->handler = condSect2; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + + + +static int +condSect1(PROLOG_STATE * state, + int tok, + const char * ptr ATTR_UNUSED, + const char * end ATTR_UNUSED, + const ENCODING * enc ATTR_UNUSED) { + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = externalSubset1; + state->includeLevel += 1; + return XML_ROLE_NONE; + } + return common(state, tok); +} + + + +static int +condSect2(PROLOG_STATE * state, + int tok, + const char * ptr ATTR_UNUSED, + const char * end ATTR_UNUSED, + const ENCODING * enc ATTR_UNUSED) { + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = externalSubset1; + return XML_ROLE_IGNORE_SECT; + } + return common(state, tok); +} + + + +static +int declClose(PROLOG_STATE *state, + int tok, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_NONE; + } + return common(state, tok); +} + +#if 0 + +static +int ignore(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_DECL_CLOSE: + state->handler = internalSubset; + return 0; + default: + return XML_ROLE_NONE; + } + return common(state, tok); +} +#endif + +static +int error(PROLOG_STATE *state ATTR_UNUSED, + int tok ATTR_UNUSED, + const char *ptr ATTR_UNUSED, + const char *end ATTR_UNUSED, + const ENCODING *enc ATTR_UNUSED) +{ + return XML_ROLE_NONE; +} + +static +int common(PROLOG_STATE *state, int tok ATTR_UNUSED) +{ + if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) + return XML_ROLE_INNER_PARAM_ENTITY_REF; + state->handler = error; + return XML_ROLE_ERROR; +} + + + +void +xmlrpc_XmlPrologStateInit(PROLOG_STATE * const state) { + + state->handler = prolog0; + state->documentEntity = 1; + state->includeLevel = 0; +} + + + +void +xmlrpc_XmlPrologStateInitExternalEntity(PROLOG_STATE * const state) { + + state->handler = externalSubset0; + state->documentEntity = 0; + state->includeLevel = 0; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmlrole.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmlrole.h new file mode 100644 index 0000000..3cccb83 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmlrole.h @@ -0,0 +1,96 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#ifndef XmlRole_INCLUDED +#define XmlRole_INCLUDED 1 + +#include "xmltok.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + XML_ROLE_ERROR = -1, + XML_ROLE_NONE = 0, + XML_ROLE_XML_DECL, + XML_ROLE_INSTANCE_START, + XML_ROLE_DOCTYPE_NAME, + XML_ROLE_DOCTYPE_SYSTEM_ID, + XML_ROLE_DOCTYPE_PUBLIC_ID, + XML_ROLE_DOCTYPE_CLOSE, + XML_ROLE_GENERAL_ENTITY_NAME, + XML_ROLE_PARAM_ENTITY_NAME, + XML_ROLE_ENTITY_VALUE, + XML_ROLE_ENTITY_SYSTEM_ID, + XML_ROLE_ENTITY_PUBLIC_ID, + XML_ROLE_ENTITY_NOTATION_NAME, + XML_ROLE_NOTATION_NAME, + XML_ROLE_NOTATION_SYSTEM_ID, + XML_ROLE_NOTATION_NO_SYSTEM_ID, + XML_ROLE_NOTATION_PUBLIC_ID, + XML_ROLE_ATTRIBUTE_NAME, + XML_ROLE_ATTRIBUTE_TYPE_CDATA, + XML_ROLE_ATTRIBUTE_TYPE_ID, + XML_ROLE_ATTRIBUTE_TYPE_IDREF, + XML_ROLE_ATTRIBUTE_TYPE_IDREFS, + XML_ROLE_ATTRIBUTE_TYPE_ENTITY, + XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, + XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, + XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, + XML_ROLE_ATTRIBUTE_ENUM_VALUE, + XML_ROLE_ATTRIBUTE_NOTATION_VALUE, + XML_ROLE_ATTLIST_ELEMENT_NAME, + XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, + XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, + XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, + XML_ROLE_FIXED_ATTRIBUTE_VALUE, + XML_ROLE_ELEMENT_NAME, + XML_ROLE_CONTENT_ANY, + XML_ROLE_CONTENT_EMPTY, + XML_ROLE_CONTENT_PCDATA, + XML_ROLE_GROUP_OPEN, + XML_ROLE_GROUP_CLOSE, + XML_ROLE_GROUP_CLOSE_REP, + XML_ROLE_GROUP_CLOSE_OPT, + XML_ROLE_GROUP_CLOSE_PLUS, + XML_ROLE_GROUP_CHOICE, + XML_ROLE_GROUP_SEQUENCE, + XML_ROLE_CONTENT_ELEMENT, + XML_ROLE_CONTENT_ELEMENT_REP, + XML_ROLE_CONTENT_ELEMENT_OPT, + XML_ROLE_CONTENT_ELEMENT_PLUS, + XML_ROLE_TEXT_DECL, + XML_ROLE_IGNORE_SECT, + XML_ROLE_INNER_PARAM_ENTITY_REF, + XML_ROLE_PARAM_ENTITY_REF, + XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION +}; + +typedef struct prolog_state { + int (*handler)(struct prolog_state *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc); + unsigned level; + unsigned includeLevel; + int documentEntity; +} PROLOG_STATE; + +XMLTOKAPI void +xmlrpc_XmlPrologStateInit(PROLOG_STATE * const state); + +XMLTOKAPI void +xmlrpc_XmlPrologStateInitExternalEntity(PROLOG_STATE * const state); + +#define XmlTokenRole(state, tok, ptr, end, enc) \ + (((state)->handler)(state, tok, ptr, end, enc)) + +#ifdef __cplusplus +} +#endif + +#endif /* not XmlRole_INCLUDED */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok.c new file mode 100644 index 0000000..9eb8284 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok.c @@ -0,0 +1,1538 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#include "xmlrpc_config.h" +#include "xmldef.h" +#include "xmltok.h" +#include "nametab.h" + +#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok) + +#define VTABLE1 \ + { PREFIX(prologTok), PREFIX(contentTok), \ + PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \ + { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \ + PREFIX(sameName), \ + PREFIX(nameMatchesAscii), \ + PREFIX(nameLength), \ + PREFIX(skipS), \ + PREFIX(getAtts), \ + PREFIX(charRefNumber), \ + PREFIX(predefinedEntityName), \ + PREFIX(updatePosition), \ + PREFIX(isPublicId) + +#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) + +#define UCS2_GET_NAMING(pages, hi, lo) \ + (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F))) + +/* A 2 byte UTF-8 representation splits the characters 11 bits +between the bottom 5 and 6 bits of the bytes. +We need 8 bits to index into pages, 3 bits to add to that index and +5 bits to generate the mask. */ +#define UTF8_GET_NAMING2(pages, byte) \ + (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ + + ((((byte)[0]) & 3) << 1) \ + + ((((byte)[1]) >> 5) & 1)] \ + & (1 << (((byte)[1]) & 0x1F))) + +/* A 3 byte UTF-8 representation splits the characters 16 bits +between the bottom 4, 6 and 6 bits of the bytes. +We need 8 bits to index into pages, 3 bits to add to that index and +5 bits to generate the mask. */ +#define UTF8_GET_NAMING3(pages, byte) \ + (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \ + + ((((byte)[1]) >> 2) & 0xF)] \ + << 3) \ + + ((((byte)[1]) & 3) << 1) \ + + ((((byte)[2]) >> 5) & 1)] \ + & (1 << (((byte)[2]) & 0x1F))) + +#define UTF8_GET_NAMING(pages, p, n) \ + ((n) == 2 \ + ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ + : ((n) == 3 \ + ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \ + : 0)) + +#define UTF8_INVALID3(p) \ + ((*p) == 0xED \ + ? (((p)[1] & 0x20) != 0) \ + : ((*p) == 0xEF \ + ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \ + : 0)) + +#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0) + +static +int isNever(const ENCODING *enc ATTR_UNUSED, const char *p ATTR_UNUSED) +{ + return 0; +} + +static +int utf8_isName2(const ENCODING *enc ATTR_UNUSED, const char *p) +{ + return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); +} + +static +int utf8_isName3(const ENCODING *enc ATTR_UNUSED, const char *p) +{ + return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); +} + +#define utf8_isName4 isNever + +static +int utf8_isNmstrt2(const ENCODING *enc ATTR_UNUSED, const char *p) +{ + return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); +} + +static +int utf8_isNmstrt3(const ENCODING *enc ATTR_UNUSED, const char *p) +{ + return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); +} + +#define utf8_isNmstrt4 isNever + +#define utf8_isInvalid2 isNever + +static +int utf8_isInvalid3(const ENCODING *enc ATTR_UNUSED, const char *p) +{ + return UTF8_INVALID3((const unsigned char *)p); +} + +static +int utf8_isInvalid4(const ENCODING *enc ATTR_UNUSED, const char *p) +{ + return UTF8_INVALID4((const unsigned char *)p); +} + +struct normal_encoding { + ENCODING enc; + unsigned char type[256]; +#ifdef XML_MIN_SIZE + int (*byteType)(const ENCODING *, const char *); + int (*isNameMin)(const ENCODING *, const char *); + int (*isNmstrtMin)(const ENCODING *, const char *); + int (*byteToAscii)(const ENCODING *, const char *); + int (*charMatches)(const ENCODING *, const char *, int); +#endif /* XML_MIN_SIZE */ + int (*isName2)(const ENCODING *, const char *); + int (*isName3)(const ENCODING *, const char *); + int (*isName4)(const ENCODING *, const char *); + int (*isNmstrt2)(const ENCODING *, const char *); + int (*isNmstrt3)(const ENCODING *, const char *); + int (*isNmstrt4)(const ENCODING *, const char *); + int (*isInvalid2)(const ENCODING *, const char *); + int (*isInvalid3)(const ENCODING *, const char *); + int (*isInvalid4)(const ENCODING *, const char *); +}; + +#ifdef XML_MIN_SIZE + +#define STANDARD_VTABLE(E) \ + E ## byteType, \ + E ## isNameMin, \ + E ## isNmstrtMin, \ + E ## byteToAscii, \ + E ## charMatches, + +#else + +#define STANDARD_VTABLE(E) /* as nothing */ + +#endif + +#define NORMAL_VTABLE(E) \ + E ## isName2, \ + E ## isName3, \ + E ## isName4, \ + E ## isNmstrt2, \ + E ## isNmstrt3, \ + E ## isNmstrt4, \ + E ## isInvalid2, \ + E ## isInvalid3, \ + E ## isInvalid4 + +#define NULL_NORMAL_VTABLE \ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + +static int checkCharRefNumber(int); + +#include "xmltok_impl.h" +#include "ascii.h" + +#ifdef XML_MIN_SIZE +#define sb_isNameMin isNever +#define sb_isNmstrtMin isNever +#endif + +#ifdef XML_MIN_SIZE +#define MINBPC(enc) ((enc)->minBytesPerChar) +#else +/* minimum bytes per character */ +#define MINBPC(enc) 1 +#endif + +#define SB_BYTE_TYPE(enc, p) \ + (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) + +#ifdef XML_MIN_SIZE +static +int sb_byteType(const ENCODING *enc, const char *p) +{ + return SB_BYTE_TYPE(enc, p); +} +#define BYTE_TYPE(enc, p) \ + (((const struct normal_encoding *)(enc))->byteType(enc, p)) +#else +#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) +#endif + +#ifdef XML_MIN_SIZE +#define BYTE_TO_ASCII(enc, p) \ + (((const struct normal_encoding *)(enc))->byteToAscii(enc, p)) +static +int sb_byteToAscii(const ENCODING *enc, const char *p) +{ + return *p; +} +#else +#define BYTE_TO_ASCII(enc, p) (*(p)) +#endif + +#define IS_NAME_CHAR(enc, p, n) \ + (((const struct normal_encoding *)(enc))->isName ## n(enc, p)) +#define IS_NMSTRT_CHAR(enc, p, n) \ + (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p)) +#define IS_INVALID_CHAR(enc, p, n) \ + (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p)) + +#ifdef XML_MIN_SIZE +#define IS_NAME_CHAR_MINBPC(enc, p) \ + (((const struct normal_encoding *)(enc))->isNameMin(enc, p)) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) \ + (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p)) +#else +#define IS_NAME_CHAR_MINBPC(enc, p) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) +#endif + +#ifdef XML_MIN_SIZE +#define CHAR_MATCHES(enc, p, c) \ + (((const struct normal_encoding *)(enc))->charMatches(enc, p, c)) +static +int sb_charMatches(const ENCODING *enc, const char *p, int c) +{ + return *p == c; +} +#else +/* c is an ASCII character */ +#define CHAR_MATCHES(enc, p, c) (*(p) == c) +#endif + +#define PREFIX(ident) normal_ ## ident +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ + UTF8_cval1 = 0x00, + UTF8_cval2 = 0xc0, + UTF8_cval3 = 0xe0, + UTF8_cval4 = 0xf0 +}; + +static +void utf8_toUtf8(const ENCODING * enc ATTR_UNUSED, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + char *to; + const char *from; + if (fromLim - *fromP > toLim - *toP) { + /* Avoid copying partial characters. */ + for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) + if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) + break; + } + for (to = *toP, from = *fromP; from != fromLim; from++, to++) + *to = *from; + *fromP = from; + *toP = to; +} + +static +void utf8_toUtf16(const ENCODING *enc, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + unsigned short *to = *toP; + const char *from = *fromP; + while (from != fromLim && to != toLim) { + switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { + case BT_LEAD2: + *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f); + from += 2; + break; + case BT_LEAD3: + *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f); + from += 3; + break; + case BT_LEAD4: + { + unsigned long n; + if (to + 1 == toLim) + break; + n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); + n -= 0x10000; + to[0] = (unsigned short)((n >> 10) | 0xD800); + to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); + to += 2; + from += 4; + } + break; + default: + *to++ = *from++; + break; + } + } + *fromP = from; + *toP = to; +} + +static const struct normal_encoding utf8_encoding_ns = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#include "asciitab.h" +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +static const struct normal_encoding utf8_encoding = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +static const struct normal_encoding internal_utf8_encoding_ns = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#include "iasciitab.h" +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +static const struct normal_encoding internal_utf8_encoding = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +static +void latin1_toUtf8(const ENCODING *enc ATTR_UNUSED, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + for (;;) { + unsigned char c; + if (*fromP == fromLim) + break; + c = (unsigned char)**fromP; + if (c & 0x80) { + if (toLim - *toP < 2) + break; + *(*toP)++ = ((c >> 6) | UTF8_cval2); + *(*toP)++ = ((c & 0x3f) | 0x80); + (*fromP)++; + } + else { + if (*toP == toLim) + break; + *(*toP)++ = *(*fromP)++; + } + } +} + +static +void latin1_toUtf16(const ENCODING *enc ATTR_UNUSED, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + while (*fromP != fromLim && *toP != toLim) + *(*toP)++ = (unsigned char)*(*fromP)++; +} + +static const struct normal_encoding latin1_encoding_ns = { + { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE +}; + +static const struct normal_encoding latin1_encoding = { + { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE +}; + +static +void ascii_toUtf8(const ENCODING *enc ATTR_UNUSED, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + while (*fromP != fromLim && *toP != toLim) + *(*toP)++ = *(*fromP)++; +} + +static const struct normal_encoding ascii_encoding_ns = { + { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, + { +#include "asciitab.h" +/* BT_NONXML == 0 */ + }, + STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE +}; + +static const struct normal_encoding ascii_encoding = { + { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +/* BT_NONXML == 0 */ + }, + STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE +}; + +static int unicode_byte_type(char hi, char lo) +{ + switch ((unsigned char)hi) { + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + return BT_LEAD4; + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + return BT_TRAIL; + case 0xFF: + switch ((unsigned char)lo) { + case 0xFF: + case 0xFE: + return BT_NONXML; + } + break; + } + return BT_NONASCII; +} + +#define DEFINE_UTF16_TO_UTF8(E) \ +static \ +void E ## toUtf8(const ENCODING *enc ATTR_UNUSED, \ + const char **fromP, const char *fromLim, \ + char **toP, const char *toLim) \ +{ \ + const char *from; \ + for (from = *fromP; from != fromLim; from += 2) { \ + int plane; \ + unsigned char lo2; \ + unsigned char lo = GET_LO(from); \ + unsigned char hi = GET_HI(from); \ + switch (hi) { \ + case 0: \ + if (lo < 0x80) { \ + if (*toP == toLim) { \ + *fromP = from; \ + return; \ + } \ + *(*toP)++ = lo; \ + break; \ + } \ + /* fall through */ \ + case 0x1: case 0x2: case 0x3: \ + case 0x4: case 0x5: case 0x6: case 0x7: \ + if (toLim - *toP < 2) { \ + *fromP = from; \ + return; \ + } \ + *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ + *(*toP)++ = ((lo & 0x3f) | 0x80); \ + break; \ + default: \ + if (toLim - *toP < 3) { \ + *fromP = from; \ + return; \ + } \ + /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ + *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ + *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ + *(*toP)++ = ((lo & 0x3f) | 0x80); \ + break; \ + case 0xD8: case 0xD9: case 0xDA: case 0xDB: \ + if (toLim - *toP < 4) { \ + *fromP = from; \ + return; \ + } \ + plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ + *(*toP)++ = ((plane >> 2) | UTF8_cval4); \ + *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ + from += 2; \ + lo2 = GET_LO(from); \ + *(*toP)++ = (((lo & 0x3) << 4) \ + | ((GET_HI(from) & 0x3) << 2) \ + | (lo2 >> 6) \ + | 0x80); \ + *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ + break; \ + } \ + } \ + *fromP = from; \ +} + +#define DEFINE_UTF16_TO_UTF16(E) \ +static \ +void E ## toUtf16(const ENCODING *enc ATTR_UNUSED, \ + const char **fromP, const char *fromLim, \ + unsigned short **toP, const unsigned short *toLim) \ +{ \ + /* Avoid copying first half only of surrogate */ \ + if (fromLim - *fromP > ((toLim - *toP) << 1) \ + && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \ + fromLim -= 2; \ + for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \ + *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ +} + +#define SET2(ptr, ch) \ + (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8))) +#define GET_LO(ptr) ((unsigned char)(ptr)[0]) +#define GET_HI(ptr) ((unsigned char)(ptr)[1]) + +DEFINE_UTF16_TO_UTF8(little2_) +DEFINE_UTF16_TO_UTF16(little2_) + +#undef SET2 +#undef GET_LO +#undef GET_HI + +#define SET2(ptr, ch) \ + (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF))) +#define GET_LO(ptr) ((unsigned char)(ptr)[1]) +#define GET_HI(ptr) ((unsigned char)(ptr)[0]) + +DEFINE_UTF16_TO_UTF8(big2_) +DEFINE_UTF16_TO_UTF16(big2_) + +#undef SET2 +#undef GET_LO +#undef GET_HI + +#define LITTLE2_BYTE_TYPE(enc, p) \ + ((p)[1] == 0 \ + ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ + : unicode_byte_type((p)[1], (p)[0])) +#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1) +#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c) +#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) +#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) + +#ifdef XML_MIN_SIZE + +static +int little2_byteType(const ENCODING *enc, const char *p) +{ + return LITTLE2_BYTE_TYPE(enc, p); +} + +static +int little2_byteToAscii(const ENCODING *enc, const char *p) +{ + return LITTLE2_BYTE_TO_ASCII(enc, p); +} + +static +int little2_charMatches(const ENCODING *enc, const char *p, int c) +{ + return LITTLE2_CHAR_MATCHES(enc, p, c); +} + +static +int little2_isNameMin(const ENCODING *enc, const char *p) +{ + return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); +} + +static +int little2_isNmstrtMin(const ENCODING *enc, const char *p) +{ + return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); +} + +#undef VTABLE +#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 + +#else /* not XML_MIN_SIZE */ + +#undef PREFIX +#define PREFIX(ident) little2_ ## ident +#define MINBPC(enc) 2 +/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ +#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) +#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) +#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c) +#define IS_NAME_CHAR(enc, p, n) 0 +#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) +#define IS_NMSTRT_CHAR(enc, p, n) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) + +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +#endif /* not XML_MIN_SIZE */ + +static const struct normal_encoding little2_encoding_ns = { + { VTABLE, 2, 0, +#if XML_BYTE_ORDER == 12 + 1 +#else + 0 +#endif + }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE +}; + +static const struct normal_encoding little2_encoding = { + { VTABLE, 2, 0, +#if XML_BYTE_ORDER == 12 + 1 +#else + 0 +#endif + }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE +}; + +#if XML_BYTE_ORDER != 21 + +static const struct normal_encoding internal_little2_encoding_ns = { + { VTABLE, 2, 0, 1 }, + { +#include "iasciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE +}; + +static const struct normal_encoding internal_little2_encoding = { + { VTABLE, 2, 0, 1 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE +}; + +#endif + + +#define BIG2_BYTE_TYPE(enc, p) \ + ((p)[0] == 0 \ + ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ + : unicode_byte_type((p)[0], (p)[1])) +#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1) +#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c) +#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) +#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) + +#ifdef XML_MIN_SIZE + +static +int big2_byteType(const ENCODING *enc, const char *p) +{ + return BIG2_BYTE_TYPE(enc, p); +} + +static +int big2_byteToAscii(const ENCODING *enc, const char *p) +{ + return BIG2_BYTE_TO_ASCII(enc, p); +} + +static +int big2_charMatches(const ENCODING *enc, const char *p, int c) +{ + return BIG2_CHAR_MATCHES(enc, p, c); +} + +static +int big2_isNameMin(const ENCODING *enc, const char *p) +{ + return BIG2_IS_NAME_CHAR_MINBPC(enc, p); +} + +static +int big2_isNmstrtMin(const ENCODING *enc, const char *p) +{ + return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); +} + +#undef VTABLE +#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 + +#else /* not XML_MIN_SIZE */ + +#undef PREFIX +#define PREFIX(ident) big2_ ## ident +#define MINBPC(enc) 2 +/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ +#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) +#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) +#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c) +#define IS_NAME_CHAR(enc, p, n) 0 +#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p) +#define IS_NMSTRT_CHAR(enc, p, n) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) + +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +#endif /* not XML_MIN_SIZE */ + +static const struct normal_encoding big2_encoding_ns = { + { VTABLE, 2, 0, +#if XML_BYTE_ORDER == 21 + 1 +#else + 0 +#endif + }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE +}; + +static const struct normal_encoding big2_encoding = { + { VTABLE, 2, 0, +#if XML_BYTE_ORDER == 21 + 1 +#else + 0 +#endif + }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE +}; + +#if XML_BYTE_ORDER != 12 + +static const struct normal_encoding internal_big2_encoding_ns = { + { VTABLE, 2, 0, 1 }, + { +#include "iasciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE +}; + +static const struct normal_encoding internal_big2_encoding = { + { VTABLE, 2, 0, 1 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE +}; + +#endif + +#undef PREFIX + +static +int streqci(const char *s1, const char *s2) +{ + for (;;) { + char c1 = *s1++; + char c2 = *s2++; + if (ASCII_a <= c1 && c1 <= ASCII_z) + c1 += ASCII_A - ASCII_a; + if (ASCII_a <= c2 && c2 <= ASCII_z) + c2 += ASCII_A - ASCII_a; + if (c1 != c2) + return 0; + if (!c1) + break; + } + return 1; +} + +static +void initUpdatePosition(const ENCODING *enc ATTR_UNUSED, const char *ptr, + const char *end, POSITION *pos) +{ + normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); +} + +static +int toAscii(const ENCODING *enc, const char *ptr, const char *end) +{ + char buf[1]; + char *p = buf; + XmlUtf8Convert(enc, &ptr, end, &p, p + 1); + if (p == buf) + return -1; + else + return buf[0]; +} + +static +int isSpace(int c) +{ + switch (c) { + case 0x20: + case 0xD: + case 0xA: + case 0x9: + return 1; + } + return 0; +} + +/* Return 1 if there's just optional white space +or there's an S followed by name=val. */ +static +int parsePseudoAttribute(const ENCODING *enc, + const char *ptr, + const char *end, + const char **namePtr, + const char **nameEndPtr, + const char **valPtr, + const char **nextTokPtr) +{ + int c; + char open; + if (ptr == end) { + *namePtr = 0; + return 1; + } + if (!isSpace(toAscii(enc, ptr, end))) { + *nextTokPtr = ptr; + return 0; + } + do { + ptr += enc->minBytesPerChar; + } while (isSpace(toAscii(enc, ptr, end))); + if (ptr == end) { + *namePtr = 0; + return 1; + } + *namePtr = ptr; + for (;;) { + c = toAscii(enc, ptr, end); + if (c == -1) { + *nextTokPtr = ptr; + return 0; + } + if (c == ASCII_EQUALS) { + *nameEndPtr = ptr; + break; + } + if (isSpace(c)) { + *nameEndPtr = ptr; + do { + ptr += enc->minBytesPerChar; + } while (isSpace(c = toAscii(enc, ptr, end))); + if (c != ASCII_EQUALS) { + *nextTokPtr = ptr; + return 0; + } + break; + } + ptr += enc->minBytesPerChar; + } + if (ptr == *namePtr) { + *nextTokPtr = ptr; + return 0; + } + ptr += enc->minBytesPerChar; + c = toAscii(enc, ptr, end); + while (isSpace(c)) { + ptr += enc->minBytesPerChar; + c = toAscii(enc, ptr, end); + } + if (c != ASCII_QUOT && c != ASCII_APOS) { + *nextTokPtr = ptr; + return 0; + } + open = c; + ptr += enc->minBytesPerChar; + *valPtr = ptr; + for (;; ptr += enc->minBytesPerChar) { + c = toAscii(enc, ptr, end); + if (c == open) + break; + if (!(ASCII_a <= c && c <= ASCII_z) + && !(ASCII_A <= c && c <= ASCII_Z) + && !(ASCII_0 <= c && c <= ASCII_9) + && c != ASCII_PERIOD + && c != ASCII_MINUS + && c != ASCII_UNDERSCORE) { + *nextTokPtr = ptr; + return 0; + } + } + *nextTokPtr = ptr + enc->minBytesPerChar; + return 1; +} + +static const char KW_version[] = { + ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0' +}; + +static const char KW_encoding[] = { + ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0' +}; + +static const char KW_standalone[] = { + ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0' +}; + +static const char KW_yes[] = { + ASCII_y, ASCII_e, ASCII_s, '\0' +}; + +static const char KW_no[] = { + ASCII_n, ASCII_o, '\0' +}; + +static +int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, + const char *, + const char *), + int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **encodingName, + const ENCODING **encoding, + int *standalone) +{ + const char *val = 0; + const char *name = 0; + const char *nameEnd = 0; + ptr += 5 * enc->minBytesPerChar; + end -= 2 * enc->minBytesPerChar; + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) || !name) { + *badPtr = ptr; + return 0; + } + if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) { + if (!isGeneralTextEntity) { + *badPtr = name; + return 0; + } + } + else { + if (versionPtr) + *versionPtr = val; + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { + *badPtr = ptr; + return 0; + } + if (!name) { + if (isGeneralTextEntity) { + /* a TextDecl must have an EncodingDecl */ + *badPtr = ptr; + return 0; + } + return 1; + } + } + if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) { + int c = toAscii(enc, val, end); + if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) { + *badPtr = val; + return 0; + } + if (encodingName) + *encodingName = val; + if (encoding) + *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { + *badPtr = ptr; + return 0; + } + if (!name) + return 1; + } + if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) || isGeneralTextEntity) { + *badPtr = name; + return 0; + } + if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) { + if (standalone) + *standalone = 1; + } + else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) { + if (standalone) + *standalone = 0; + } + else { + *badPtr = val; + return 0; + } + while (isSpace(toAscii(enc, ptr, end))) + ptr += enc->minBytesPerChar; + if (ptr != end) { + *badPtr = ptr; + return 0; + } + return 1; +} + +static +int checkCharRefNumber(int result) +{ + switch (result >> 8) { + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + return -1; + case 0: + if (latin1_encoding.type[result] == BT_NONXML) + return -1; + break; + case 0xFF: + if (result == 0xFFFE || result == 0xFFFF) + return -1; + break; + } + return result; +} + + + +int +xmlrpc_XmlUtf8Encode(int const c, + char * const buf) { + + enum { + /* minN is minimum legal resulting value for N byte sequence */ + min2 = 0x80, + min3 = 0x800, + min4 = 0x10000 + }; + + if (c < 0) + return 0; + if (c < min2) { + buf[0] = (c | UTF8_cval1); + return 1; + } + if (c < min3) { + buf[0] = ((c >> 6) | UTF8_cval2); + buf[1] = ((c & 0x3f) | 0x80); + return 2; + } + if (c < min4) { + buf[0] = ((c >> 12) | UTF8_cval3); + buf[1] = (((c >> 6) & 0x3f) | 0x80); + buf[2] = ((c & 0x3f) | 0x80); + return 3; + } + if (c < 0x110000) { + buf[0] = ((c >> 18) | UTF8_cval4); + buf[1] = (((c >> 12) & 0x3f) | 0x80); + buf[2] = (((c >> 6) & 0x3f) | 0x80); + buf[3] = ((c & 0x3f) | 0x80); + return 4; + } + return 0; +} + + + +int +xmlrpc_XmlUtf16Encode(int const charNumArg, + unsigned short * const buf) { + + int charNum; + + charNum = charNumArg; /* initial value */ + + if (charNum < 0) + return 0; + if (charNum < 0x10000) { + buf[0] = charNum; + return 1; + } + if (charNum < 0x110000) { + charNum -= 0x10000; + buf[0] = (charNum >> 10) + 0xD800; + buf[1] = (charNum & 0x3FF) + 0xDC00; + return 2; + } + return 0; +} + + + +struct unknown_encoding { + struct normal_encoding normal; + int (*convert)(void *userData, const char *p); + void *userData; + unsigned short utf16[256]; + char utf8[256][4]; +}; + + + +int +xmlrpc_XmlSizeOfUnknownEncoding(void) { + + return sizeof(struct unknown_encoding); +} + + + +static +int unknown_isName(const ENCODING *enc, const char *p) +{ + int c = ((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, p); + if (c & ~0xFFFF) + return 0; + return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); +} + +static +int unknown_isNmstrt(const ENCODING *enc, const char *p) +{ + int c = ((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, p); + if (c & ~0xFFFF) + return 0; + return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); +} + +static +int unknown_isInvalid(const ENCODING *enc, const char *p) +{ + int c = ((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, p); + return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; +} + +static +void unknown_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + char buf[XML_UTF8_ENCODE_MAX]; + for (;;) { + const char *utf8; + int n; + if (*fromP == fromLim) + break; + utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP]; + n = *utf8++; + if (n == 0) { + int c = ((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); + n = xmlrpc_XmlUtf8Encode(c, buf); + if (n > toLim - *toP) + break; + utf8 = buf; + *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] + - (BT_LEAD2 - 2); + } + else { + if (n > toLim - *toP) + break; + (*fromP)++; + } + do { + *(*toP)++ = *utf8++; + } while (--n != 0); + } +} + +static +void unknown_toUtf16(const ENCODING *enc, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + while (*fromP != fromLim && *toP != toLim) { + unsigned short c + = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP]; + if (c == 0) { + c = (unsigned short)((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); + *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] + - (BT_LEAD2 - 2); + } + else + (*fromP)++; + *(*toP)++ = c; + } +} + +ENCODING * +xmlrpc_XmlInitUnknownEncoding(void * const mem, + int * const table, + int (*convert)(void *userData, const char *p), + void * const userData) { + + int i; + struct unknown_encoding *e = mem; + for (i = 0; i < (int)sizeof(struct normal_encoding); i++) + ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; + for (i = 0; i < 128; i++) + if (latin1_encoding.type[i] != BT_OTHER + && latin1_encoding.type[i] != BT_NONXML + && table[i] != i) + return 0; + for (i = 0; i < 256; i++) { + int c = table[i]; + if (c == -1) { + e->normal.type[i] = BT_MALFORM; + /* This shouldn't really get used. */ + e->utf16[i] = 0xFFFF; + e->utf8[i][0] = 1; + e->utf8[i][1] = 0; + } + else if (c < 0) { + if (c < -4) + return 0; + e->normal.type[i] = BT_LEAD2 - (c + 2); + e->utf8[i][0] = 0; + e->utf16[i] = 0; + } + else if (c < 0x80) { + if (latin1_encoding.type[c] != BT_OTHER + && latin1_encoding.type[c] != BT_NONXML + && c != i) + return 0; + e->normal.type[i] = latin1_encoding.type[c]; + e->utf8[i][0] = 1; + e->utf8[i][1] = (char)c; + e->utf16[i] = c == 0 ? 0xFFFF : c; + } + else if (checkCharRefNumber(c) < 0) { + e->normal.type[i] = BT_NONXML; + /* This shouldn't really get used. */ + e->utf16[i] = 0xFFFF; + e->utf8[i][0] = 1; + e->utf8[i][1] = 0; + } + else { + if (c > 0xFFFF) + return 0; + if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) + e->normal.type[i] = BT_NMSTRT; + else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) + e->normal.type[i] = BT_NAME; + else + e->normal.type[i] = BT_OTHER; + e->utf8[i][0] = (char)xmlrpc_XmlUtf8Encode(c, e->utf8[i] + 1); + e->utf16[i] = c; + } + } + e->userData = userData; + e->convert = convert; + if (convert) { + e->normal.isName2 = unknown_isName; + e->normal.isName3 = unknown_isName; + e->normal.isName4 = unknown_isName; + e->normal.isNmstrt2 = unknown_isNmstrt; + e->normal.isNmstrt3 = unknown_isNmstrt; + e->normal.isNmstrt4 = unknown_isNmstrt; + e->normal.isInvalid2 = unknown_isInvalid; + e->normal.isInvalid3 = unknown_isInvalid; + e->normal.isInvalid4 = unknown_isInvalid; + } + e->normal.enc.utf8Convert = unknown_toUtf8; + e->normal.enc.utf16Convert = unknown_toUtf16; + return &(e->normal.enc); +} + +/* If this enumeration is changed, getEncodingIndex and encodings +must also be changed. */ +enum { + UNKNOWN_ENC = -1, + ISO_8859_1_ENC = 0, + US_ASCII_ENC, + UTF_8_ENC, + UTF_16_ENC, + UTF_16BE_ENC, + UTF_16LE_ENC, + /* must match encodingNames up to here */ + NO_ENC +}; + +static const char KW_ISO_8859_1[] = { + ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0' +}; +static const char KW_US_ASCII[] = { + ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, '\0' +}; +static const char KW_UTF_8[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0' +}; +static const char KW_UTF_16[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0' +}; +static const char KW_UTF_16BE[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, '\0' +}; +static const char KW_UTF_16LE[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, '\0' +}; + +static +int getEncodingIndex(const char *name) +{ + static const char *encodingNames[] = { + KW_ISO_8859_1, + KW_US_ASCII, + KW_UTF_8, + KW_UTF_16, + KW_UTF_16BE, + KW_UTF_16LE, + }; + int i; + if (name == 0) + return NO_ENC; + for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++) + if (streqci(name, encodingNames[i])) + return i; + return UNKNOWN_ENC; +} + +/* For binary compatibility, we store the index of the encoding specified +at initialization in the isUtf16 member. */ + +#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16) +#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i) + +/* This is what detects the encoding. +encodingTable maps from encoding indices to encodings; +INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding; +state is XML_CONTENT_STATE if we're parsing an external text entity, +and XML_PROLOG_STATE otherwise. +*/ + + +static +int initScan(const ENCODING **encodingTable, + const INIT_ENCODING *enc, + int state, + const char *ptr, + const char *end, + const char **nextTokPtr) +{ + const ENCODING **encPtr; + + if (ptr == end) + return XML_TOK_NONE; + encPtr = enc->encPtr; + if (ptr + 1 == end) { + /* only a single byte available for auto-detection */ + /* so we're parsing an external text entity... */ + /* if UTF-16 was externally specified, then we need at least 2 bytes */ + switch (INIT_ENC_INDEX(enc)) { + case UTF_16_ENC: + case UTF_16LE_ENC: + case UTF_16BE_ENC: + return XML_TOK_PARTIAL; + } + switch ((unsigned char)*ptr) { + case 0xFE: + case 0xFF: + case 0xEF: /* possibly first byte of UTF-8 BOM */ + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + /* fall through */ + case 0x00: + case 0x3C: + return XML_TOK_PARTIAL; + } + } + else { + switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { + case 0xFEFF: + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + *nextTokPtr = ptr + 2; + *encPtr = encodingTable[UTF_16BE_ENC]; + return XML_TOK_BOM; + /* 00 3C is handled in the default case */ + case 0x3C00: + if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC + || INIT_ENC_INDEX(enc) == UTF_16_ENC) + && state == XML_CONTENT_STATE) + break; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + case 0xFFFE: + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + *nextTokPtr = ptr + 2; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XML_TOK_BOM; + case 0xEFBB: + /* Maybe a UTF-8 BOM (EF BB BF) */ + /* If there's an explicitly specified (external) encoding + of ISO-8859-1 or some flavour of UTF-16 + and this is an external text entity, + don't look for the BOM, + because it might be a legal data. */ + if (state == XML_CONTENT_STATE) { + int e = INIT_ENC_INDEX(enc); + if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC) + break; + } + if (ptr + 2 == end) + return XML_TOK_PARTIAL; + if ((unsigned char)ptr[2] == 0xBF) { + *encPtr = encodingTable[UTF_8_ENC]; + return XML_TOK_BOM; + } + break; + default: + if (ptr[0] == '\0') { + /* 0 isn't a legal data character. Furthermore a document entity can only + start with ASCII characters. So the only way this can fail to be big-endian + UTF-16 if it it's an external parsed general entity that's labelled as + UTF-16LE. */ + if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) + break; + *encPtr = encodingTable[UTF_16BE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + else if (ptr[1] == '\0') { + /* We could recover here in the case: + - parsing an external entity + - second byte is 0 + - no externally specified encoding + - no encoding declaration + by assuming UTF-16LE. But we don't, because this would mean when + presented just with a single byte, we couldn't reliably determine + whether we needed further bytes. */ + if (state == XML_CONTENT_STATE) + break; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + break; + } + } + *encPtr = encodingTable[INIT_ENC_INDEX(enc)]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); +} + + +#define NS(x) x +#define ns(x) x +#include "xmltok_ns.c" +#undef NS +#undef ns + +#define NS(x) x ## NS +#define ns(x) x ## _ns + +#include "xmltok_ns.c" + +#undef NS +#undef ns + +ENCODING * +xmlrpc_XmlInitUnknownEncodingNS(void * const mem, + int * const table, + int (*convert)(void *userData, const char *p), + void * const userData) { + + ENCODING * const enc = + xmlrpc_XmlInitUnknownEncoding(mem, table, convert, userData); + if (enc) + ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON; + return enc; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok.h new file mode 100644 index 0000000..453568f --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok.h @@ -0,0 +1,316 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#ifndef XmlTok_INCLUDED +#define XmlTok_INCLUDED 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef XMLTOKAPI +#define XMLTOKAPI /* as nothing */ +#endif + +/* The following token may be returned by XmlContentTok */ +#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of + illegal ]]> sequence */ +/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ +#define XML_TOK_NONE -4 /* The string to be scanned is empty */ +#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; + might be part of CRLF sequence */ +#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ +#define XML_TOK_PARTIAL -1 /* only part of a token */ +#define XML_TOK_INVALID 0 + +/* The following tokens are returned by XmlContentTok; some are also + returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */ + +#define XML_TOK_START_TAG_WITH_ATTS 1 +#define XML_TOK_START_TAG_NO_ATTS 2 +#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ +#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 +#define XML_TOK_END_TAG 5 +#define XML_TOK_DATA_CHARS 6 +#define XML_TOK_DATA_NEWLINE 7 +#define XML_TOK_CDATA_SECT_OPEN 8 +#define XML_TOK_ENTITY_REF 9 +#define XML_TOK_CHAR_REF 10 /* numeric character reference */ + +/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ +#define XML_TOK_PI 11 /* processing instruction */ +#define XML_TOK_XML_DECL 12 /* XML decl or text decl */ +#define XML_TOK_COMMENT 13 +#define XML_TOK_BOM 14 /* Byte order mark */ + +/* The following tokens are returned only by XmlPrologTok */ +#define XML_TOK_PROLOG_S 15 +#define XML_TOK_DECL_OPEN 16 /* */ +#define XML_TOK_NAME 18 +#define XML_TOK_NMTOKEN 19 +#define XML_TOK_POUND_NAME 20 /* #name */ +#define XML_TOK_OR 21 /* | */ +#define XML_TOK_PERCENT 22 +#define XML_TOK_OPEN_PAREN 23 +#define XML_TOK_CLOSE_PAREN 24 +#define XML_TOK_OPEN_BRACKET 25 +#define XML_TOK_CLOSE_BRACKET 26 +#define XML_TOK_LITERAL 27 +#define XML_TOK_PARAM_ENTITY_REF 28 +#define XML_TOK_INSTANCE_START 29 + +/* The following occur only in element type declarations */ +#define XML_TOK_NAME_QUESTION 30 /* name? */ +#define XML_TOK_NAME_ASTERISK 31 /* name* */ +#define XML_TOK_NAME_PLUS 32 /* name+ */ +#define XML_TOK_COND_SECT_OPEN 33 /* */ +#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ +#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ +#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ +#define XML_TOK_COMMA 38 + +/* The following token is returned only by XmlAttributeValueTok */ +#define XML_TOK_ATTRIBUTE_VALUE_S 39 + +/* The following token is returned only by XmlCdataSectionTok */ +#define XML_TOK_CDATA_SECT_CLOSE 40 + +/* With namespace processing this is returned by XmlPrologTok + for a name with a colon. */ +#define XML_TOK_PREFIXED_NAME 41 + +#define XML_TOK_IGNORE_SECT 42 + +#define XML_N_STATES 4 + +#define XML_PROLOG_STATE 0 +#define XML_CONTENT_STATE 1 +#define XML_CDATA_SECTION_STATE 2 +#define XML_IGNORE_SECTION_STATE 3 + +#define XML_N_LITERAL_TYPES 2 +#define XML_ATTRIBUTE_VALUE_LITERAL 0 +#define XML_ENTITY_VALUE_LITERAL 1 + +/* The size of the buffer passed to XmlUtf8Encode must be at least this. */ +#define XML_UTF8_ENCODE_MAX 4 +/* The size of the buffer passed to XmlUtf16Encode must be at least this. */ +#define XML_UTF16_ENCODE_MAX 2 + +typedef struct position { + /* first line and first column are 0 not 1 */ + unsigned long lineNumber; + unsigned long columnNumber; +} POSITION; + +typedef struct { + const char *name; + const char *valuePtr; + const char *valueEnd; + char normalized; +} ATTRIBUTE; + +struct encoding; +typedef struct encoding ENCODING; + +struct encoding { + int (*scanners[XML_N_STATES])(const ENCODING *, + const char *, + const char *, + const char **); + int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *, + const char *, + const char *, + const char **); + int (*sameName)(const ENCODING *, + const char *, const char *); + int (*nameMatchesAscii)(const ENCODING *, + const char *, const char *, const char *); + int (*nameLength)(const ENCODING *, const char *); + const char *(*skipS)(const ENCODING *, const char *); + int (*getAtts)(const ENCODING *enc, const char *ptr, + int attsMax, ATTRIBUTE *atts); + int (*charRefNumber)(const ENCODING *enc, const char *ptr); + int (*predefinedEntityName)(const ENCODING *, const char *, const char *); + void (*updatePosition)(const ENCODING *, + const char *ptr, + const char *end, + POSITION *); + int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end, + const char **badPtr); + void (*utf8Convert)(const ENCODING *enc, + const char **fromP, + const char *fromLim, + char **toP, + const char *toLim); + void (*utf16Convert)(const ENCODING *enc, + const char **fromP, + const char *fromLim, + unsigned short **toP, + const unsigned short *toLim); + int minBytesPerChar; + char isUtf8; + char isUtf16; +}; + +/* +Scan the string starting at ptr until the end of the next complete token, +but do not scan past eptr. Return an integer giving the type of token. + +Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. + +Return XML_TOK_PARTIAL when the string does not contain a complete token; +nextTokPtr will not be set. + +Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr +will be set to point to the character which made the token invalid. + +Otherwise the string starts with a valid token; nextTokPtr will be set to point +to the character following the end of that token. + +Each data character counts as a single token, but adjacent data characters +may be returned together. Similarly for characters in the prolog outside +literals, comments and processing instructions. +*/ + + +#define XmlTok(enc, state, ptr, end, nextTokPtr) \ + (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) + +#define XmlPrologTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) + +#define XmlContentTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) + +#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) + +#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) + +/* This is used for performing a 2nd-level tokenization on +the content of a literal that has already been returned by XmlTok. */ + +#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ + (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) + +#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) + +#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) + +#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) + +#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ + (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) + +#define XmlNameLength(enc, ptr) \ + (((enc)->nameLength)(enc, ptr)) + +#define XmlSkipS(enc, ptr) \ + (((enc)->skipS)(enc, ptr)) + +#define XmlGetAttributes(enc, ptr, attsMax, atts) \ + (((enc)->getAtts)(enc, ptr, attsMax, atts)) + +#define XmlCharRefNumber(enc, ptr) \ + (((enc)->charRefNumber)(enc, ptr)) + +#define XmlPredefinedEntityName(enc, ptr, end) \ + (((enc)->predefinedEntityName)(enc, ptr, end)) + +#define XmlUpdatePosition(enc, ptr, end, pos) \ + (((enc)->updatePosition)(enc, ptr, end, pos)) + +#define XmlIsPublicId(enc, ptr, end, badPtr) \ + (((enc)->isPublicId)(enc, ptr, end, badPtr)) + +#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) + +#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) + +typedef struct { + ENCODING initEnc; + const ENCODING **encPtr; +} INIT_ENCODING; + +XMLTOKAPI int +xmlrpc_XmlParseXmlDecl(int const isGeneralTextEntity, + const ENCODING * const enc, + const char * const ptr, + const char * const end, + const char ** const badPtr, + const char ** const versionPtr, + const char ** const encodingNamePtr, + const ENCODING ** const namedEncodingPtr, + int * const standalonePtr); + +XMLTOKAPI const ENCODING * +xmlrpc_XmlGetUtf8InternalEncoding(void); + +XMLTOKAPI const ENCODING * +xmlrpc_XmlGetUtf16InternalEncoding(void); + +XMLTOKAPI int +xmlrpc_XmlInitEncoding(INIT_ENCODING * const p, + const ENCODING ** const encPtr, + const char * const name); + +XMLTOKAPI int +xmlrpc_XmlUtf8Encode(int const c, + char * const buf); + +XMLTOKAPI int +xmlrpc_XmlUtf16Encode(int const charNum, + unsigned short * const buf); + +XMLTOKAPI int +xmlrpc_XmlSizeOfUnknownEncoding(void); + +XMLTOKAPI ENCODING * +xmlrpc_XmlInitUnknownEncoding(void * const mem, + int * const table, + int (*convert)(void *userData, const char *p), + void * const userData); + +int +xmlrpc_XmlParseXmlDeclNS(int const isGeneralTextEntity, + const ENCODING * const enc, + const char * const ptr, + const char * const end, + const char ** const badPtr, + const char ** const versionPtr, + const char ** const encodingNamePtr, + const ENCODING ** const namedEncodingPtr, + int * const standalonePtr); + +int +xmlrpc_XmlInitEncodingNS(INIT_ENCODING * const p, + const ENCODING ** const encPtr, + const char * const name); + +const ENCODING * +xmlrpc_XmlGetUtf8InternalEncodingNS(void); + +const ENCODING * +xmlrpc_XmlGetUtf16InternalEncodingNS(void); + +ENCODING * +xmlrpc_XmlInitUnknownEncodingNS(void * const mem, + int * const table, + int (*convert)(void *userData, const char *p), + void * const userData); + +#ifdef __cplusplus +} +#endif + +#endif /* not XmlTok_INCLUDED */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_impl.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_impl.c new file mode 100644 index 0000000..cc9bc59 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_impl.c @@ -0,0 +1,1748 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#ifndef IS_INVALID_CHAR +#define IS_INVALID_CHAR(enc, ptr, n) (0) +#endif + +#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (IS_INVALID_CHAR(enc, ptr, n)) { \ + *(nextTokPtr) = (ptr); \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define INVALID_CASES(ptr, nextTokPtr) \ + INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ + INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ + INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ + case BT_NONXML: \ + case BT_MALFORM: \ + case BT_TRAIL: \ + *(nextTokPtr) = (ptr); \ + return XML_TOK_INVALID; + +#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (!IS_NAME_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ + case BT_NONASCII: \ + if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + case BT_NMSTRT: \ + case BT_HEX: \ + case BT_DIGIT: \ + case BT_NAME: \ + case BT_MINUS: \ + ptr += MINBPC(enc); \ + break; \ + CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ + CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ + CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) + +#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ + case BT_NONASCII: \ + if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + case BT_NMSTRT: \ + case BT_HEX: \ + ptr += MINBPC(enc); \ + break; \ + CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ + CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ + CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) + +#ifndef PREFIX +#define PREFIX(ident) ident +#endif + +/* ptr points to character following " */ + switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { + case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + /* fall through */ + case BT_S: case BT_CR: case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DECL_OPEN; + case BT_NMSTRT: + case BT_HEX: + ptr += MINBPC(enc); + break; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return XML_TOK_PARTIAL; +} + +static +int PREFIX(checkPiTarget)(const ENCODING * enc ATTR_UNUSED, + const char * ptr, + const char * end, + int * tokPtr) +{ + int upper = 0; + *tokPtr = XML_TOK_PI; + if (end - ptr != MINBPC(enc)*3) + return 1; + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_x: + break; + case ASCII_X: + upper = 1; + break; + default: + return 1; + } + ptr += MINBPC(enc); + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_m: + break; + case ASCII_M: + upper = 1; + break; + default: + return 1; + } + ptr += MINBPC(enc); + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_l: + break; + case ASCII_L: + upper = 1; + break; + default: + return 1; + } + if (upper) + return 0; + *tokPtr = XML_TOK_XML_DECL; + return 1; +} + +/* ptr points to character following " 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CDATA_SECT_CLOSE; + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + INVALID_CASES(ptr, nextTokPtr) + default: + ptr += MINBPC(enc); + break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_DATA_CHARS; \ + } \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + case BT_RSQB: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +/* ptr points to character following " 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_LT: + return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_AMP: + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + INVALID_CASES(ptr, nextTokPtr) + default: + ptr += MINBPC(enc); + break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_DATA_CHARS; \ + } \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_RSQB: + if (ptr + MINBPC(enc) != end) { + if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) { + ptr += MINBPC(enc); + break; + } + if (ptr + 2*MINBPC(enc) != end) { + if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) { + ptr += MINBPC(enc); + break; + } + *nextTokPtr = ptr + 2*MINBPC(enc); + return XML_TOK_INVALID; + } + } + /* fall through */ + case BT_AMP: + case BT_LT: + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +/* ptr points to character following "%" */ + +static +int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: + *nextTokPtr = ptr; + return XML_TOK_PERCENT; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_SEMI: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_PARAM_ENTITY_REF; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return XML_TOK_PARTIAL; +} + +static +int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_CR: case BT_LF: case BT_S: + case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: + *nextTokPtr = ptr; + return XML_TOK_POUND_NAME; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return -XML_TOK_POUND_NAME; +} + +static +int PREFIX(scanLit)(int open, const ENCODING *enc, + const char *ptr, const char *end, + const char **nextTokPtr) +{ + while (ptr != end) { + int t = BYTE_TYPE(enc, ptr); + switch (t) { + INVALID_CASES(ptr, nextTokPtr) + case BT_QUOT: + case BT_APOS: + ptr += MINBPC(enc); + if (t != open) + break; + if (ptr == end) + return -XML_TOK_LITERAL; + *nextTokPtr = ptr; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_CR: case BT_LF: + case BT_GT: case BT_PERCNT: case BT_LSQB: + return XML_TOK_LITERAL; + default: + return XML_TOK_INVALID; + } + default: + ptr += MINBPC(enc); + break; + } + } + return XML_TOK_PARTIAL; +} + +static +int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + int tok; + if (ptr == end) + return XML_TOK_NONE; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_QUOT: + return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_APOS: + return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_LT: + { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + case BT_EXCL: + return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_QUEST: + return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_NMSTRT: + case BT_HEX: + case BT_NONASCII: + case BT_LEAD2: + case BT_LEAD3: + case BT_LEAD4: + *nextTokPtr = ptr - MINBPC(enc); + return XML_TOK_INSTANCE_START; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + case BT_CR: + if (ptr + MINBPC(enc) == end) + return -XML_TOK_PROLOG_S; + /* fall through */ + case BT_S: case BT_LF: + for (;;) { + ptr += MINBPC(enc); + if (ptr == end) + break; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_LF: + break; + case BT_CR: + /* don't split CR/LF pair */ + if (ptr + MINBPC(enc) != end) + break; + /* fall through */ + default: + *nextTokPtr = ptr; + return XML_TOK_PROLOG_S; + } + } + *nextTokPtr = ptr; + return XML_TOK_PROLOG_S; + case BT_PERCNT: + return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_COMMA: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_COMMA; + case BT_LSQB: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OPEN_BRACKET; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return -XML_TOK_CLOSE_BRACKET; + if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { + if (ptr + MINBPC(enc) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) { + *nextTokPtr = ptr + 2*MINBPC(enc); + return XML_TOK_COND_SECT_CLOSE; + } + } + *nextTokPtr = ptr; + return XML_TOK_CLOSE_BRACKET; + case BT_LPAR: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OPEN_PAREN; + case BT_RPAR: + ptr += MINBPC(enc); + if (ptr == end) + return -XML_TOK_CLOSE_PAREN; + switch (BYTE_TYPE(enc, ptr)) { + case BT_AST: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_ASTERISK; + case BT_QUEST: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_QUESTION; + case BT_PLUS: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_PLUS; + case BT_CR: case BT_LF: case BT_S: + case BT_GT: case BT_COMMA: case BT_VERBAR: + case BT_RPAR: + *nextTokPtr = ptr; + return XML_TOK_CLOSE_PAREN; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_VERBAR: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OR; + case BT_GT: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DECL_CLOSE; + case BT_NUM: + return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ + ptr += n; \ + tok = XML_TOK_NAME; \ + break; \ + } \ + if (IS_NAME_CHAR(enc, ptr, n)) { \ + ptr += n; \ + tok = XML_TOK_NMTOKEN; \ + break; \ + } \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NMSTRT: + case BT_HEX: + tok = XML_TOK_NAME; + ptr += MINBPC(enc); + break; + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + case BT_COLON: + tok = XML_TOK_NMTOKEN; + ptr += MINBPC(enc); + break; + case BT_NONASCII: + if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { + ptr += MINBPC(enc); + tok = XML_TOK_NAME; + break; + } + if (IS_NAME_CHAR_MINBPC(enc, ptr)) { + ptr += MINBPC(enc); + tok = XML_TOK_NMTOKEN; + break; + } + /* fall through */ + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_GT: case BT_RPAR: case BT_COMMA: + case BT_VERBAR: case BT_LSQB: case BT_PERCNT: + case BT_S: case BT_CR: case BT_LF: + *nextTokPtr = ptr; + return tok; + case BT_COLON: + ptr += MINBPC(enc); + switch (tok) { + case XML_TOK_NAME: + if (ptr == end) + return XML_TOK_PARTIAL; + tok = XML_TOK_PREFIXED_NAME; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + default: + tok = XML_TOK_NMTOKEN; + break; + } + break; + case XML_TOK_PREFIXED_NAME: + tok = XML_TOK_NMTOKEN; + break; + } + break; + case BT_PLUS: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_PLUS; + case BT_AST: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_ASTERISK; + case BT_QUEST: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_QUESTION; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return -tok; +} + +static +int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + const char *start; + if (ptr == end) + return XML_TOK_NONE; + start = ptr; + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_AMP: + if (ptr == start) + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_LT: + /* this is for inside entity references */ + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_LF: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_CR: + if (ptr == start) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_S: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_ATTRIBUTE_VALUE_S; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +static +int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + const char *start; + if (ptr == end) + return XML_TOK_NONE; + start = ptr; + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_AMP: + if (ptr == start) + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_PERCNT: + if (ptr == start) + return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_LF: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_CR: + if (ptr == start) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + + + +static +int PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + int level = 0; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + end = ptr + n; + } + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + INVALID_CASES(ptr, nextTokPtr) + case BT_LT: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) { + ++level; + ptr += MINBPC(enc); + } + } + break; + case BT_RSQB: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr += MINBPC(enc); + if (level == 0) { + *nextTokPtr = ptr; + return XML_TOK_IGNORE_SECT; + } + --level; + } + } + break; + default: + ptr += MINBPC(enc); + break; + } + } + return XML_TOK_PARTIAL; +} + + + +static +int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, + const char **badPtr) +{ + ptr += MINBPC(enc); + end -= MINBPC(enc); + for (; ptr != end; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_DIGIT: + case BT_HEX: + case BT_MINUS: + case BT_APOS: + case BT_LPAR: + case BT_RPAR: + case BT_PLUS: + case BT_COMMA: + case BT_SOL: + case BT_EQUALS: + case BT_QUEST: + case BT_CR: + case BT_LF: + case BT_SEMI: + case BT_EXCL: + case BT_AST: + case BT_PERCNT: + case BT_NUM: + case BT_COLON: + break; + case BT_S: + if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) { + *badPtr = ptr; + return 0; + } + break; + case BT_NAME: + case BT_NMSTRT: + if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) + break; + default: + switch (BYTE_TO_ASCII(enc, ptr)) { + case 0x24: /* $ */ + case 0x40: /* @ */ + break; + default: + *badPtr = ptr; + return 0; + } + break; + } + } + return 1; +} + +/* This must only be called for a well-formed start-tag or empty element tag. +Returns the number of attributes. Pointers to the first attsMax attributes +are stored in atts. */ + +static +int PREFIX(getAtts)(const ENCODING *enc, const char *ptr, + int attsMax, ATTRIBUTE *atts) +{ + enum { other, inName, inValue } state = inName; + int nAtts = 0; + int open = 0; /* defined when state == inValue; + initialization just to shut up compilers */ + + for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { +#define START_NAME \ + if (state == other) { \ + if (nAtts < attsMax) { \ + atts[nAtts].name = ptr; \ + atts[nAtts].normalized = 1; \ + } \ + state = inName; \ + } +#define LEAD_CASE(n) \ + case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONASCII: + case BT_NMSTRT: + case BT_HEX: + START_NAME + break; +#undef START_NAME + case BT_QUOT: + if (state != inValue) { + if (nAtts < attsMax) + atts[nAtts].valuePtr = ptr + MINBPC(enc); + state = inValue; + open = BT_QUOT; + } + else if (open == BT_QUOT) { + state = other; + if (nAtts < attsMax) + atts[nAtts].valueEnd = ptr; + nAtts++; + } + break; + case BT_APOS: + if (state != inValue) { + if (nAtts < attsMax) + atts[nAtts].valuePtr = ptr + MINBPC(enc); + state = inValue; + open = BT_APOS; + } + else if (open == BT_APOS) { + state = other; + if (nAtts < attsMax) + atts[nAtts].valueEnd = ptr; + nAtts++; + } + break; + case BT_AMP: + if (nAtts < attsMax) + atts[nAtts].normalized = 0; + break; + case BT_S: + if (state == inName) + state = other; + else if (state == inValue + && nAtts < attsMax + && atts[nAtts].normalized + && (ptr == atts[nAtts].valuePtr + || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE + || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE + || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) + atts[nAtts].normalized = 0; + break; + case BT_CR: case BT_LF: + /* This case ensures that the first attribute name is counted + Apart from that we could just change state on the quote. */ + if (state == inName) + state = other; + else if (state == inValue && nAtts < attsMax) + atts[nAtts].normalized = 0; + break; + case BT_GT: + case BT_SOL: + if (state != inValue) + return nAtts; + break; + default: + break; + } + } + /* not reached */ +} + +static +int PREFIX(charRefNumber)(const ENCODING *enc ATTR_UNUSED, const char *ptr) +{ + int result = 0; + /* skip &# */ + ptr += 2*MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_x)) { + for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { + int c = BYTE_TO_ASCII(enc, ptr); + switch (c) { + case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4: + case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9: + result <<= 4; + result |= (c - ASCII_0); + break; + case ASCII_A: case ASCII_B: case ASCII_C: case ASCII_D: case ASCII_E: case ASCII_F: + result <<= 4; + result += 10 + (c - ASCII_A); + break; + case ASCII_a: case ASCII_b: case ASCII_c: case ASCII_d: case ASCII_e: case ASCII_f: + result <<= 4; + result += 10 + (c - ASCII_a); + break; + } + if (result >= 0x110000) + return -1; + } + } + else { + for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { + int c = BYTE_TO_ASCII(enc, ptr); + result *= 10; + result += (c - ASCII_0); + if (result >= 0x110000) + return -1; + } + } + return checkCharRefNumber(result); +} + +static +int PREFIX(predefinedEntityName)(const ENCODING * enc ATTR_UNUSED, + const char * ptr, + const char * end) +{ + switch ((end - ptr)/MINBPC(enc)) { + case 2: + if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) { + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_l: + return ASCII_LT; + case ASCII_g: + return ASCII_GT; + } + } + break; + case 3: + if (CHAR_MATCHES(enc, ptr, ASCII_a)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_m)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_p)) + return ASCII_AMP; + } + } + break; + case 4: + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_q: + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_u)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_o)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_t)) + return ASCII_QUOT; + } + } + break; + case ASCII_a: + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_p)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_o)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_s)) + return ASCII_APOS; + } + } + break; + } + } + return 0; +} + +static +int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) +{ + for (;;) { + switch (BYTE_TYPE(enc, ptr1)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (*ptr1++ != *ptr2++) \ + return 0; + LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) +#undef LEAD_CASE + /* fall through */ + if (*ptr1++ != *ptr2++) + return 0; + break; + case BT_NONASCII: + case BT_NMSTRT: + case BT_COLON: + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 1) { + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 2) { + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 3) { + if (*ptr2++ != *ptr1++) + return 0; + } + } + } + break; + default: + if (MINBPC(enc) == 1 && *ptr1 == *ptr2) + return 1; + switch (BYTE_TYPE(enc, ptr2)) { + case BT_LEAD2: + case BT_LEAD3: + case BT_LEAD4: + case BT_NONASCII: + case BT_NMSTRT: + case BT_COLON: + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + return 0; + default: + return 1; + } + } + } + /* not reached */ +} + +static +int PREFIX(nameMatchesAscii)(const ENCODING * enc ATTR_UNUSED, + const char * ptr1, + const char * end1, + const char * ptr2) +{ + for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { + if (ptr1 == end1) + return 0; + if (!CHAR_MATCHES(enc, ptr1, *ptr2)) + return 0; + } + return ptr1 == end1; +} + +static +int PREFIX(nameLength)(const ENCODING *enc, const char *ptr) +{ + const char *start = ptr; + for (;;) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONASCII: + case BT_NMSTRT: + case BT_COLON: + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + ptr += MINBPC(enc); + break; + default: + return ptr - start; + } + } +} + +static +const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr) +{ + for (;;) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_LF: + case BT_CR: + case BT_S: + ptr += MINBPC(enc); + break; + default: + return ptr; + } + } +} + +static +void PREFIX(updatePosition)(const ENCODING *enc, + const char *ptr, + const char *end, + POSITION *pos) +{ + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_LF: + pos->columnNumber = (unsigned)-1; + pos->lineNumber++; + ptr += MINBPC(enc); + break; + case BT_CR: + pos->lineNumber++; + ptr += MINBPC(enc); + if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + pos->columnNumber = (unsigned)-1; + break; + default: + ptr += MINBPC(enc); + break; + } + pos->columnNumber++; + } +} + +#undef DO_LEAD_CASE +#undef MULTIBYTE_CASES +#undef INVALID_CASES +#undef CHECK_NAME_CASE +#undef CHECK_NAME_CASES +#undef CHECK_NMSTRT_CASE +#undef CHECK_NMSTRT_CASES diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_impl.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_impl.h new file mode 100644 index 0000000..eb92802 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_impl.h @@ -0,0 +1,46 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +enum { + BT_NONXML, + BT_MALFORM, + BT_LT, + BT_AMP, + BT_RSQB, + BT_LEAD2, + BT_LEAD3, + BT_LEAD4, + BT_TRAIL, + BT_CR, + BT_LF, + BT_GT, + BT_QUOT, + BT_APOS, + BT_EQUALS, + BT_QUEST, + BT_EXCL, + BT_SOL, + BT_SEMI, + BT_NUM, + BT_LSQB, + BT_S, + BT_NMSTRT, + BT_COLON, + BT_HEX, + BT_DIGIT, + BT_NAME, + BT_MINUS, + BT_OTHER, /* known not to be a name or name start character */ + BT_NONASCII, /* might be a name or name start character */ + BT_PERCNT, + BT_LPAR, + BT_RPAR, + BT_AST, + BT_PLUS, + BT_COMMA, + BT_VERBAR +}; + +#include diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_ns.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_ns.c new file mode 100644 index 0000000..a44a4cf --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmltok/xmltok_ns.c @@ -0,0 +1,112 @@ +const ENCODING * +NS(xmlrpc_XmlGetUtf8InternalEncoding)(void) { + + return &ns(internal_utf8_encoding).enc; +} + + + +const ENCODING * +NS(xmlrpc_XmlGetUtf16InternalEncoding)(void) { + +#if XML_BYTE_ORDER == 12 + return &ns(internal_little2_encoding).enc; +#elif XML_BYTE_ORDER == 21 + return &ns(internal_big2_encoding).enc; +#else + const short n = 1; + return *(const char *)&n ? + &ns(internal_little2_encoding).enc : + &ns(internal_big2_encoding).enc; +#endif +} + +static +const ENCODING *NS(encodings)[] = { + &ns(latin1_encoding).enc, + &ns(ascii_encoding).enc, + &ns(utf8_encoding).enc, + &ns(big2_encoding).enc, + &ns(big2_encoding).enc, + &ns(little2_encoding).enc, + &ns(utf8_encoding).enc /* NO_ENC */ +}; + +static +int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr); +} + +static +int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr); +} + + + +int +NS(xmlrpc_XmlInitEncoding)(INIT_ENCODING * const p, + const ENCODING ** const encPtr, + const char * const name) { + + int i = getEncodingIndex(name); + if (i == UNKNOWN_ENC) + return 0; + SET_INIT_ENC_INDEX(p, i); + p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); + p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); + p->initEnc.updatePosition = initUpdatePosition; + p->encPtr = encPtr; + *encPtr = &(p->initEnc); + return 1; +} + + + +static +const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) +{ +#define ENCODING_MAX 128 + char buf[ENCODING_MAX]; + char *p = buf; + int i; + XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); + if (ptr != end) + return 0; + *p = 0; + if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) + return enc; + i = getEncodingIndex(buf); + if (i == UNKNOWN_ENC) + return 0; + return NS(encodings)[i]; +} + + + +int +NS(xmlrpc_XmlParseXmlDecl)(int const isGeneralTextEntity, + const ENCODING * const enc, + const char * const ptr, + const char * const end, + const char ** const badPtr, + const char ** const versionPtr, + const char ** const encodingName, + const ENCODING ** const encoding, + int * const standalone) { + + return doParseXmlDecl(NS(findEncoding), + isGeneralTextEntity, + enc, + ptr, + end, + badPtr, + versionPtr, + encodingName, + encoding, + standalone); +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/Makefile.in b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/Makefile.in new file mode 100644 index 0000000..0860147 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/Makefile.in @@ -0,0 +1,209 @@ +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +ABYSS_SUBDIR = @ABYSS_SUBDIR@ +AS = @AS@ +ASYNCH_CLIENT = @ASYNCH_CLIENT@ +AUTH_CLIENT = @AUTH_CLIENT@ +AVAILABLE_MODULES = @AVAILABLE_MODULES@ +CC = @CC@ +CC_WARN_FLAGS = @CC_WARN_FLAGS@ +CLIENTTEST = @CLIENTTEST@ +CONFIGURE_DATE = @CONFIGURE_DATE@ +CPPTEST = @CPPTEST@ +CPP_WARN_FLAGS = @CPP_WARN_FLAGS@ +CXX = @CXX@ +DLLTOOL = @DLLTOOL@ +EFRPCTEST = @EFRPCTEST@ +EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@ +INTEROP_CGI = @INTEROP_CGI@ +INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@ +LIBTOOL = @LIBTOOL@ +LIBWWW_CFLAGS = @LIBWWW_CFLAGS@ +LIBWWW_CONFIG = @LIBWWW_CONFIG@ +LIBWWW_LDADD = @LIBWWW_LDADD@ +LIBWWW_LIBDIR = @LIBWWW_LIBDIR@ +LIBWWW_RPATH = @LIBWWW_RPATH@ +LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@ +LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@ +LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@ +LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@ +LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@ +LN_S = @LN_S@ +MAKEINFO = @MAKEINFO@ +MEERKAT_APP_LIST = @MEERKAT_APP_LIST@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +QUERY_MEERKAT = @QUERY_MEERKAT@ +RANLIB = @RANLIB@ +SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@ +SERVER = @SERVER@ +SERVERTEST = @SERVERTEST@ +SYNCH_CLIENT = @SYNCH_CLIENT@ +VALIDATEE = @VALIDATEE@ +VERSION = @VERSION@ +VERSION_INFO = @VERSION_INFO@ +XMLRPCCPP_H = @XMLRPCCPP_H@ +XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@ +XMLRPC_CGI_H = @XMLRPC_CGI_H@ +XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@ +XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@ + +EXTRA_DIST = codepage.c filemap.h unixfilemap.c xmlfile.c xmltchar.h xmlwf.dsp codepage.h readfilemap.c win32filemap.c xmlfile.h xmlwf.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../../xmlrpc_config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = gtar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = lib/expat/xmlwf + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: tags distdir info-am info dvi-am dvi check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/codepage.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/codepage.c new file mode 100644 index 0000000..fe7ab15 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/codepage.c @@ -0,0 +1,65 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#include "codepage.h" + +#ifdef WIN32 +#define STRICT 1 +#define WIN32_LEAN_AND_MEAN 1 + +#include + +int codepageMap(int cp, int *map) +{ + int i; + CPINFO info; + if (!GetCPInfo(cp, &info) || info.MaxCharSize > 2) + return 0; + for (i = 0; i < 256; i++) + map[i] = -1; + if (info.MaxCharSize > 1) { + for (i = 0; i < MAX_LEADBYTES; i++) { + int j, lim; + if (info.LeadByte[i] == 0 && info.LeadByte[i + 1] == 0) + break; + lim = info.LeadByte[i + 1]; + for (j = info.LeadByte[i]; j < lim; j++) + map[j] = -2; + } + } + for (i = 0; i < 256; i++) { + if (map[i] == -1) { + char c = i; + unsigned short n; + if (MultiByteToWideChar(cp, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + &c, 1, &n, 1) == 1) + map[i] = n; + } + } + return 1; +} + +int codepageConvert(int cp, const char *p) +{ + unsigned short c; + if (MultiByteToWideChar(cp, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + p, 2, &c, 1) == 1) + return c; + return -1; +} + +#else /* not WIN32 */ + +int codepageMap(int cp, int *map) +{ + return 0; +} + +int codepageConvert(int cp, const char *p) +{ + return -1; +} + +#endif /* not WIN32 */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/codepage.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/codepage.h new file mode 100644 index 0000000..b19a7f6 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/codepage.h @@ -0,0 +1,7 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +int codepageMap(int cp, int *map); +int codepageConvert(int cp, const char *p); diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/filemap.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/filemap.h new file mode 100644 index 0000000..a0a1847 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/filemap.h @@ -0,0 +1,17 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + + +#include + +#ifdef XML_UNICODE +int filemap(const wchar_t *name, + void (*processor)(const void *, size_t, const wchar_t *, void *arg), + void *arg); +#else +int filemap(const char *name, + void (*processor)(const void *, size_t, const char *, void *arg), + void *arg); +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/readfilemap.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/readfilemap.c new file mode 100644 index 0000000..249af3e --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/readfilemap.c @@ -0,0 +1,74 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#include +#include +#include +#include +#include + +#ifndef S_ISREG +#ifndef S_IFREG +#define S_IFREG _S_IFREG +#endif +#ifndef S_IFMT +#define S_IFMT _S_IFMT +#endif +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif /* not S_ISREG */ + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 +#endif +#endif + +int filemap(const char *name, + void (*processor)(const void *, size_t, const char *, void *arg), + void *arg) +{ + size_t nbytes; + int fd; + int n; + struct stat sb; + void *p; + + fd = open(name, O_RDONLY|O_BINARY); + if (fd < 0) { + perror(name); + return 0; + } + if (fstat(fd, &sb) < 0) { + perror(name); + return 0; + } + if (!S_ISREG(sb.st_mode)) { + fprintf(stderr, "%s: not a regular file\n", name); + return 0; + } + nbytes = sb.st_size; + p = malloc(nbytes); + if (!p) { + fprintf(stderr, "%s: out of memory\n", name); + return 0; + } + n = read(fd, p, nbytes); + if (n < 0) { + perror(name); + close(fd); + return 0; + } + if (n != nbytes) { + fprintf(stderr, "%s: read unexpected number of bytes\n", name); + close(fd); + return 0; + } + processor(p, nbytes, name, arg); + free(p); + close(fd); + return 1; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/unixfilemap.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/unixfilemap.c new file mode 100644 index 0000000..4944b02 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/unixfilemap.c @@ -0,0 +1,57 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#include "filemap.h" + +int filemap(const char *name, + void (*processor)(const void *, size_t, const char *, void *arg), + void *arg) +{ + int fd; + size_t nbytes; + struct stat sb; + void *p; + + fd = open(name, O_RDONLY); + if (fd < 0) { + perror(name); + return 0; + } + if (fstat(fd, &sb) < 0) { + perror(name); + close(fd); + return 0; + } + if (!S_ISREG(sb.st_mode)) { + close(fd); + fprintf(stderr, "%s: not a regular file\n", name); + return 0; + } + + nbytes = sb.st_size; + p = (void *)mmap((caddr_t)0, (size_t)nbytes, PROT_READ, + MAP_FILE|MAP_PRIVATE, fd, (off_t)0); + if (p == (void *)-1) { + perror(name); + close(fd); + return 0; + } + processor(p, nbytes, name, arg); + munmap((caddr_t)p, nbytes); + close(fd); + return 1; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/win32filemap.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/win32filemap.c new file mode 100644 index 0000000..ec30ff6 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/win32filemap.c @@ -0,0 +1,95 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#define STRICT 1 +#define WIN32_LEAN_AND_MEAN 1 + +#ifdef XML_UNICODE_WCHAR_T +#ifndef XML_UNICODE +#define XML_UNICODE +#endif +#endif + +#ifdef XML_UNICODE +#define UNICODE +#define _UNICODE +#endif /* XML_UNICODE */ +#include +#include +#include +#include "filemap.h" + +static void win32perror(const TCHAR *); + +int filemap(const TCHAR *name, + void (*processor)(const void *, size_t, const TCHAR *, void *arg), + void *arg) +{ + HANDLE f; + HANDLE m; + DWORD size; + DWORD sizeHi; + void *p; + + f = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (f == INVALID_HANDLE_VALUE) { + win32perror(name); + return 0; + } + size = GetFileSize(f, &sizeHi); + if (size == (DWORD)-1) { + win32perror(name); + return 0; + } + if (sizeHi) { + _ftprintf(stderr, _T("%s: bigger than 2Gb\n"), name); + return 0; + } + /* CreateFileMapping barfs on zero length files */ + if (size == 0) { + static const char c = '\0'; + processor(&c, 0, name, arg); + CloseHandle(f); + return 1; + } + m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL); + if (m == NULL) { + win32perror(name); + CloseHandle(f); + return 0; + } + p = MapViewOfFile(m, FILE_MAP_READ, 0, 0, 0); + if (p == NULL) { + win32perror(name); + CloseHandle(m); + CloseHandle(f); + return 0; + } + processor(p, size, name, arg); + UnmapViewOfFile(p); + CloseHandle(m); + CloseHandle(f); + return 1; +} + +static +void win32perror(const TCHAR *s) +{ + LPVOID buf; + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &buf, + 0, + NULL)) { + _ftprintf(stderr, _T("%s: %s"), s, buf); + fflush(stderr); + LocalFree(buf); + } + else + _ftprintf(stderr, _T("%s: unknown Windows error\n"), s); +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlfile.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlfile.c new file mode 100644 index 0000000..5b3b978 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlfile.c @@ -0,0 +1,217 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#include +#include +#include +#include +#include +#include "xmlparse.h" +#include "xmlfile.h" +#include "xmltchar.h" +#include "filemap.h" + +#if MSVCRT +#include +#endif + +#ifdef _POSIX_SOURCE +#include +#endif + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 +#endif +#endif + +#ifdef _DEBUG +#define READ_SIZE 16 +#else +#define READ_SIZE (1024*8) +#endif + + + +typedef struct { + XML_Parser parser; + int *retPtr; +} PROCESS_ARGS; + +static +void reportError(XML_Parser parser, const XML_Char *filename) +{ + int code = XML_GetErrorCode(parser); + const XML_Char *message = XML_ErrorString(code); + if (message) + ftprintf(stdout, T("%s:%d:%d: %s\n"), + filename, + XML_GetErrorLineNumber(parser), + XML_GetErrorColumnNumber(parser), + message); + else + ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code); +} + +static +void processFile(const void *data, + size_t size, + const XML_Char *filename, + void *args) +{ + XML_Parser parser = ((PROCESS_ARGS *)args)->parser; + int *retPtr = ((PROCESS_ARGS *)args)->retPtr; + if (!XML_Parse(parser, data, size, 1)) { + reportError(parser, filename); + *retPtr = 0; + } + else + *retPtr = 1; +} + +#ifdef WIN32 + +static +int isAsciiLetter(XML_Char c) +{ + return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z')); +} + +#endif /* WIN32 */ + +static +const XML_Char *resolveSystemId(const XML_Char *base, const XML_Char *systemId, XML_Char **toFree) +{ + XML_Char *s; + *toFree = 0; + if (!base + || *systemId == T('/') +#ifdef WIN32 + || *systemId == T('\\') + || (isAsciiLetter(systemId[0]) && systemId[1] == T(':')) +#endif + ) + return systemId; + *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2)*sizeof(XML_Char)); + if (!*toFree) + return systemId; + tcscpy(*toFree, base); + s = *toFree; + if (tcsrchr(s, T('/'))) + s = tcsrchr(s, T('/')) + 1; +#ifdef WIN32 + if (tcsrchr(s, T('\\'))) + s = tcsrchr(s, T('\\')) + 1; +#endif + tcscpy(s, systemId); + return *toFree; +} + +static +int externalEntityRefFilemap(XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId) +{ + int result; + XML_Char *s; + const XML_Char *filename; + XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); + PROCESS_ARGS args; + args.retPtr = &result; + args.parser = entParser; + filename = resolveSystemId(base, systemId, &s); + XML_SetBase(entParser, filename); + if (!filemap(filename, processFile, &args)) + result = 0; + free(s); + XML_ParserFree(entParser); + return result; +} + +static +int processStream(const XML_Char *filename, XML_Parser parser) +{ + int fd = topen(filename, O_BINARY|O_RDONLY); + if (fd < 0) { + tperror(filename); + return 0; + } + for (;;) { + int nread; + char *buf = XML_GetBuffer(parser, READ_SIZE); + if (!buf) { + close(fd); + ftprintf(stderr, T("%s: out of memory\n"), filename); + return 0; + } + nread = read(fd, buf, READ_SIZE); + if (nread < 0) { + tperror(filename); + close(fd); + return 0; + } + if (!XML_ParseBuffer(parser, nread, nread == 0)) { + reportError(parser, filename); + close(fd); + return 0; + } + if (nread == 0) { + close(fd); + break;; + } + } + return 1; +} + +static +int externalEntityRefStream(XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId) +{ + XML_Char *s; + const XML_Char *filename; + int ret; + XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); + filename = resolveSystemId(base, systemId, &s); + XML_SetBase(entParser, filename); + ret = processStream(filename, entParser); + free(s); + XML_ParserFree(entParser); + return ret; +} + +int XML_ProcessFile(XML_Parser parser, + const XML_Char *filename, + unsigned flags) +{ + int result; + + if (!XML_SetBase(parser, filename)) { + ftprintf(stderr, T("%s: out of memory"), filename); + exit(1); + } + + if (flags & XML_EXTERNAL_ENTITIES) + XML_SetExternalEntityRefHandler(parser, + (flags & XML_MAP_FILE) + ? externalEntityRefFilemap + : externalEntityRefStream); + if (flags & XML_MAP_FILE) { + PROCESS_ARGS args; + args.retPtr = &result; + args.parser = parser; + if (!filemap(filename, processFile, &args)) + result = 0; + } + else + result = processStream(filename, parser); + return result; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlfile.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlfile.h new file mode 100644 index 0000000..0c7ac19 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlfile.h @@ -0,0 +1,11 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#define XML_MAP_FILE 01 +#define XML_EXTERNAL_ENTITIES 02 + +extern int XML_ProcessFile(XML_Parser parser, + const XML_Char *filename, + unsigned flags); diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmltchar.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmltchar.h new file mode 100644 index 0000000..1088575 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmltchar.h @@ -0,0 +1,36 @@ +#ifdef XML_UNICODE +#ifndef XML_UNICODE_WCHAR_T +#error xmlwf requires a 16-bit Unicode-compatible wchar_t +#endif +#define T(x) L ## x +#define ftprintf fwprintf +#define tfopen _wfopen +#define fputts fputws +#define puttc putwc +#define tcscmp wcscmp +#define tcscpy wcscpy +#define tcscat wcscat +#define tcschr wcschr +#define tcsrchr wcsrchr +#define tcslen wcslen +#define tperror _wperror +#define topen _wopen +#define tmain wmain +#define tremove _wremove +#else /* not XML_UNICODE */ +#define T(x) x +#define ftprintf fprintf +#define tfopen fopen +#define fputts fputs +#define puttc putc +#define tcscmp strcmp +#define tcscpy strcpy +#define tcscat strcat +#define tcschr strchr +#define tcsrchr strrchr +#define tcslen strlen +#define tperror perror +#define topen open +#define tmain main +#define tremove remove +#endif /* not XML_UNICODE */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlwf.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlwf.c new file mode 100644 index 0000000..5d5662e --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlwf.c @@ -0,0 +1,766 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file copying.txt for copying permission. +*/ + +#include +#include +#include +#include + +#include "xmlparse.h" +#include "codepage.h" +#include "xmlfile.h" +#include "xmltchar.h" + +#if MSVCRT +#include +#endif + +/* This ensures proper sorting. */ + +#define NSSEP T('\001') + +static void characterData(void *userData, const XML_Char *s, int len) +{ + FILE *fp = userData; + for (; len > 0; --len, ++s) { + switch (*s) { + case T('&'): + fputts(T("&"), fp); + break; + case T('<'): + fputts(T("<"), fp); + break; + case T('>'): + fputts(T(">"), fp); + break; +#ifdef W3C14N + case 13: + fputts(T(" "), fp); + break; +#else + case T('"'): + fputts(T("""), fp); + break; + case 9: + case 10: + case 13: + ftprintf(fp, T("&#%d;"), *s); + break; +#endif + default: + puttc(*s, fp); + break; + } + } +} + +static void attributeValue(FILE *fp, const XML_Char *s) +{ + puttc(T('='), fp); + puttc(T('"'), fp); + for (;;) { + switch (*s) { + case 0: + case NSSEP: + puttc(T('"'), fp); + return; + case T('&'): + fputts(T("&"), fp); + break; + case T('<'): + fputts(T("<"), fp); + break; + case T('"'): + fputts(T("""), fp); + break; +#ifdef W3C14N + case 9: + fputts(T(" "), fp); + break; + case 10: + fputts(T(" "), fp); + break; + case 13: + fputts(T(" "), fp); + break; +#else + case T('>'): + fputts(T(">"), fp); + break; + case 9: + case 10: + case 13: + ftprintf(fp, T("&#%d;"), *s); + break; +#endif + default: + puttc(*s, fp); + break; + } + s++; + } +} + +/* Lexicographically comparing UTF-8 encoded attribute values, +is equivalent to lexicographically comparing based on the character number. */ + +static int attcmp(const void *att1, const void *att2) +{ + return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2); +} + +static void startElement(void *userData, const XML_Char *name, const XML_Char **atts) +{ + int nAtts; + const XML_Char **p; + FILE *fp = userData; + puttc(T('<'), fp); + fputts(name, fp); + + p = atts; + while (*p) + ++p; + nAtts = (p - atts) >> 1; + if (nAtts > 1) + qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp); + while (*atts) { + puttc(T(' '), fp); + fputts(*atts++, fp); + attributeValue(fp, *atts); + atts++; + } + puttc(T('>'), fp); +} + +static void endElement(void *userData, const XML_Char *name) +{ + FILE *fp = userData; + puttc(T('<'), fp); + puttc(T('/'), fp); + fputts(name, fp); + puttc(T('>'), fp); +} + +static int nsattcmp(const void *p1, const void *p2) +{ + const XML_Char *att1 = *(const XML_Char **)p1; + const XML_Char *att2 = *(const XML_Char **)p2; + int sep1 = (tcsrchr(att1, NSSEP) != 0); + int sep2 = (tcsrchr(att1, NSSEP) != 0); + if (sep1 != sep2) + return sep1 - sep2; + return tcscmp(att1, att2); +} + +static void startElementNS(void *userData, const XML_Char *name, const XML_Char **atts) +{ + int nAtts; + int nsi; + const XML_Char **p; + FILE *fp = userData; + const XML_Char *sep; + puttc(T('<'), fp); + + sep = tcsrchr(name, NSSEP); + if (sep) { + fputts(T("n1:"), fp); + fputts(sep + 1, fp); + fputts(T(" xmlns:n1"), fp); + attributeValue(fp, name); + nsi = 2; + } + else { + fputts(name, fp); + nsi = 1; + } + + p = atts; + while (*p) + ++p; + nAtts = (p - atts) >> 1; + if (nAtts > 1) + qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp); + while (*atts) { + name = *atts++; + sep = tcsrchr(name, NSSEP); + puttc(T(' '), fp); + if (sep) { + ftprintf(fp, T("n%d:"), nsi); + fputts(sep + 1, fp); + } + else + fputts(name, fp); + attributeValue(fp, *atts); + if (sep) { + ftprintf(fp, T(" xmlns:n%d"), nsi++); + attributeValue(fp, name); + } + atts++; + } + puttc(T('>'), fp); +} + +static void endElementNS(void *userData, const XML_Char *name) +{ + FILE *fp = userData; + const XML_Char *sep; + puttc(T('<'), fp); + puttc(T('/'), fp); + sep = tcsrchr(name, NSSEP); + if (sep) { + fputts(T("n1:"), fp); + fputts(sep + 1, fp); + } + else + fputts(name, fp); + puttc(T('>'), fp); +} + +#ifndef W3C14N + +static void processingInstruction(void *userData, const XML_Char *target, const XML_Char *data) +{ + FILE *fp = userData; + puttc(T('<'), fp); + puttc(T('?'), fp); + fputts(target, fp); + puttc(T(' '), fp); + fputts(data, fp); + puttc(T('?'), fp); + puttc(T('>'), fp); +} + +#endif /* not W3C14N */ + +static void defaultCharacterData(XML_Parser parser, const XML_Char *s, int len) +{ + XML_DefaultCurrent(parser); +} + +static void defaultStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts) +{ + XML_DefaultCurrent(parser); +} + +static void defaultEndElement(XML_Parser parser, const XML_Char *name) +{ + XML_DefaultCurrent(parser); +} + +static void defaultProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data) +{ + XML_DefaultCurrent(parser); +} + +static void nopCharacterData(XML_Parser parser, const XML_Char *s, int len) +{ +} + +static void nopStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts) +{ +} + +static void nopEndElement(XML_Parser parser, const XML_Char *name) +{ +} + +static void nopProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data) +{ +} + +static void markup(XML_Parser parser, const XML_Char *s, int len) +{ + FILE *fp = XML_GetUserData(parser); + for (; len > 0; --len, ++s) + puttc(*s, fp); +} + +static +void metaLocation(XML_Parser parser) +{ + const XML_Char *uri = XML_GetBase(parser); + if (uri) + ftprintf(XML_GetUserData(parser), T(" uri=\"%s\""), uri); + ftprintf(XML_GetUserData(parser), + T(" byte=\"%ld\" nbytes=\"%d\" line=\"%d\" col=\"%d\""), + XML_GetCurrentByteIndex(parser), + XML_GetCurrentByteCount(parser), + XML_GetCurrentLineNumber(parser), + XML_GetCurrentColumnNumber(parser)); +} + +static +void metaStartDocument(XML_Parser parser) +{ + fputts(T("\n"), XML_GetUserData(parser)); +} + +static +void metaEndDocument(XML_Parser parser) +{ + fputts(T("\n"), XML_GetUserData(parser)); +} + +static +void metaStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts) +{ + FILE *fp = XML_GetUserData(parser); + const XML_Char **specifiedAttsEnd + = atts + XML_GetSpecifiedAttributeCount(parser); + const XML_Char **idAttPtr; + int idAttIndex = XML_GetIdAttributeIndex(parser); + if (idAttIndex < 0) + idAttPtr = 0; + else + idAttPtr = atts + idAttIndex; + + ftprintf(fp, T("\n"), fp); + do { + ftprintf(fp, T("= specifiedAttsEnd) + fputts(T("\" defaulted=\"yes\"/>\n"), fp); + else if (atts == idAttPtr) + fputts(T("\" id=\"yes\"/>\n"), fp); + else + fputts(T("\"/>\n"), fp); + } while (*(atts += 2)); + fputts(T("\n"), fp); + } + else + fputts(T("/>\n"), fp); +} + +static +void metaEndElement(XML_Parser parser, const XML_Char *name) +{ + FILE *fp = XML_GetUserData(parser); + ftprintf(fp, T("\n"), fp); +} + +static +void metaProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data) +{ + FILE *fp = XML_GetUserData(parser); + ftprintf(fp, T("\n"), fp); +} + +static +void metaComment(XML_Parser parser, const XML_Char *data) +{ + FILE *fp = XML_GetUserData(parser); + fputts(T("\n"), fp); +} + +static +void metaStartCdataSection(XML_Parser parser) +{ + FILE *fp = XML_GetUserData(parser); + fputts(T("\n"), fp); +} + +static +void metaEndCdataSection(XML_Parser parser) +{ + FILE *fp = XML_GetUserData(parser); + fputts(T("\n"), fp); +} + +static +void metaCharacterData(XML_Parser parser, const XML_Char *s, int len) +{ + FILE *fp = XML_GetUserData(parser); + fputts(T("\n"), fp); +} + +static +void metaStartDoctypeDecl(XML_Parser parser, const XML_Char *doctypeName) +{ + FILE *fp = XML_GetUserData(parser); + ftprintf(fp, T("\n"), fp); +} + +static +void metaEndDoctypeDecl(XML_Parser parser) +{ + FILE *fp = XML_GetUserData(parser); + fputts(T("\n"), fp); +} + +static +void metaUnparsedEntityDecl(XML_Parser parser, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName) +{ + FILE *fp = XML_GetUserData(parser); + ftprintf(fp, T("\n"), fp); +} + +static +void metaNotationDecl(XML_Parser parser, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId) +{ + FILE *fp = XML_GetUserData(parser); + ftprintf(fp, T("\n"), fp); +} + + +static +void metaExternalParsedEntityDecl(XML_Parser parser, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId) +{ + FILE *fp = XML_GetUserData(parser); + ftprintf(fp, T("\n"), fp); +} + +static +void metaInternalParsedEntityDecl(XML_Parser parser, + const XML_Char *entityName, + const XML_Char *text, + int textLen) +{ + FILE *fp = XML_GetUserData(parser); + ftprintf(fp, T("'), fp); + characterData(fp, text, textLen); + fputts(T("\n"), fp); +} + +static +void metaStartNamespaceDecl(XML_Parser parser, + const XML_Char *prefix, + const XML_Char *uri) +{ + FILE *fp = XML_GetUserData(parser); + fputts(T("\n"), fp); + } + else + fputts(T("/>\n"), fp); +} + +static +void metaEndNamespaceDecl(XML_Parser parser, const XML_Char *prefix) +{ + FILE *fp = XML_GetUserData(parser); + if (!prefix) + fputts(T("\n"), fp); + else + ftprintf(fp, T("\n"), prefix); +} + +static +int unknownEncodingConvert(void *data, const char *p) +{ + return codepageConvert(*(int *)data, p); +} + +static +int unknownEncoding(void *userData, + const XML_Char *name, + XML_Encoding *info) +{ + int cp; + static const XML_Char prefixL[] = T("windows-"); + static const XML_Char prefixU[] = T("WINDOWS-"); + int i; + + for (i = 0; prefixU[i]; i++) + if (name[i] != prefixU[i] && name[i] != prefixL[i]) + return 0; + + cp = 0; + for (; name[i]; i++) { + static const XML_Char digits[] = T("0123456789"); + const XML_Char *s = tcschr(digits, name[i]); + if (!s) + return 0; + cp *= 10; + cp += s - digits; + if (cp >= 0x10000) + return 0; + } + if (!codepageMap(cp, info->map)) + return 0; + info->convert = unknownEncodingConvert; + /* We could just cast the code page integer to a void *, + and avoid the use of release. */ + info->release = free; + info->data = malloc(sizeof(int)); + if (!info->data) + return 0; + *(int *)info->data = cp; + return 1; +} + +static +int notStandalone(void *userData) +{ + return 0; +} + +static +void usage(const XML_Char *prog) +{ + ftprintf(stderr, T("usage: %s [-n] [-p] [-r] [-s] [-w] [-x] [-d output-dir] [-e encoding] file ...\n"), prog); + exit(1); +} + +int tmain(int argc, XML_Char **argv) +{ + int i, j; + const XML_Char *outputDir = 0; + const XML_Char *encoding = 0; + unsigned processFlags = XML_MAP_FILE; + int windowsCodePages = 0; + int outputType = 0; + int useNamespaces = 0; + int requireStandalone = 0; + int paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; + +#if MSVCRT + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF); +#endif + + i = 1; + j = 0; + while (i < argc) { + if (j == 0) { + if (argv[i][0] != T('-')) + break; + if (argv[i][1] == T('-') && argv[i][2] == T('\0')) { + i++; + break; + } + j++; + } + switch (argv[i][j]) { + case T('r'): + processFlags &= ~XML_MAP_FILE; + j++; + break; + case T('s'): + requireStandalone = 1; + j++; + break; + case T('n'): + useNamespaces = 1; + j++; + break; + case T('p'): + paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS; + /* fall through */ + case T('x'): + processFlags |= XML_EXTERNAL_ENTITIES; + j++; + break; + case T('w'): + windowsCodePages = 1; + j++; + break; + case T('m'): + outputType = 'm'; + j++; + break; + case T('c'): + outputType = 'c'; + useNamespaces = 0; + j++; + break; + case T('t'): + outputType = 't'; + j++; + break; + case T('d'): + if (argv[i][j + 1] == T('\0')) { + if (++i == argc) + usage(argv[0]); + outputDir = argv[i]; + } + else + outputDir = argv[i] + j + 1; + i++; + j = 0; + break; + case T('e'): + if (argv[i][j + 1] == T('\0')) { + if (++i == argc) + usage(argv[0]); + encoding = argv[i]; + } + else + encoding = argv[i] + j + 1; + i++; + j = 0; + break; + case T('\0'): + if (j > 1) { + i++; + j = 0; + break; + } + /* fall through */ + default: + usage(argv[0]); + } + } + if (i == argc) + usage(argv[0]); + for (; i < argc; i++) { + FILE *fp = 0; + XML_Char *outName = 0; + int result; + XML_Parser parser; + if (useNamespaces) + parser = XML_ParserCreateNS(encoding, NSSEP); + else + parser = XML_ParserCreate(encoding); + if (requireStandalone) + XML_SetNotStandaloneHandler(parser, notStandalone); + XML_SetParamEntityParsing(parser, paramEntityParsing); + if (outputType == 't') { + /* This is for doing timings; this gives a more realistic estimate of + the parsing time. */ + outputDir = 0; + XML_SetElementHandler(parser, nopStartElement, nopEndElement); + XML_SetCharacterDataHandler(parser, nopCharacterData); + XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction); + } + else if (outputDir) { + const XML_Char *file = argv[i]; + if (tcsrchr(file, T('/'))) + file = tcsrchr(file, T('/')) + 1; +#ifdef WIN32 + if (tcsrchr(file, T('\\'))) + file = tcsrchr(file, T('\\')) + 1; +#endif + outName = malloc((tcslen(outputDir) + tcslen(file) + 2) * sizeof(XML_Char)); + tcscpy(outName, outputDir); + tcscat(outName, T("/")); + tcscat(outName, file); + fp = tfopen(outName, T("wb")); + if (!fp) { + tperror(outName); + exit(1); + } + setvbuf(fp, NULL, _IOFBF, 16384); +#ifdef XML_UNICODE + puttc(0xFEFF, fp); +#endif + XML_SetUserData(parser, fp); + switch (outputType) { + case 'm': + XML_UseParserAsHandlerArg(parser); + XML_SetElementHandler(parser, metaStartElement, metaEndElement); + XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction); + XML_SetCommentHandler(parser, metaComment); + XML_SetCdataSectionHandler(parser, metaStartCdataSection, metaEndCdataSection); + XML_SetCharacterDataHandler(parser, metaCharacterData); + XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl, metaEndDoctypeDecl); + XML_SetUnparsedEntityDeclHandler(parser, metaUnparsedEntityDecl); + XML_SetNotationDeclHandler(parser, metaNotationDecl); + XML_SetExternalParsedEntityDeclHandler(parser, metaExternalParsedEntityDecl); + XML_SetInternalParsedEntityDeclHandler(parser, metaInternalParsedEntityDecl); + XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl, metaEndNamespaceDecl); + metaStartDocument(parser); + break; + case 'c': + XML_UseParserAsHandlerArg(parser); + XML_SetDefaultHandler(parser, markup); + XML_SetElementHandler(parser, defaultStartElement, defaultEndElement); + XML_SetCharacterDataHandler(parser, defaultCharacterData); + XML_SetProcessingInstructionHandler(parser, defaultProcessingInstruction); + break; + default: + if (useNamespaces) + XML_SetElementHandler(parser, startElementNS, endElementNS); + else + XML_SetElementHandler(parser, startElement, endElement); + XML_SetCharacterDataHandler(parser, characterData); +#ifndef W3C14N + XML_SetProcessingInstructionHandler(parser, processingInstruction); +#endif /* not W3C14N */ + break; + } + } + if (windowsCodePages) + XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0); + result = XML_ProcessFile(parser, argv[i], processFlags); + if (outputDir) { + if (outputType == 'm') + metaEndDocument(parser); + fclose(fp); + if (!result) + tremove(outName); + free(outName); + } + XML_ParserFree(parser); + } + return 0; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlwf.dsp b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlwf.dsp new file mode 100644 index 0000000..51de958 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/expat/xmlwf/xmlwf.dsp @@ -0,0 +1,136 @@ +# Microsoft Developer Studio Project File - Name="xmlwf" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=xmlwf - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "xmlwf.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "xmlwf.mak" CFG="xmlwf - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "xmlwf - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "xmlwf - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "xmlwf - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\xmlparse" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllimport) /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 setargv.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlwf.exe" + +!ELSEIF "$(CFG)" == "xmlwf - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".\xmlparse" /I "..\xmlparse" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllimport) /YX /FD /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 setargv.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\dbgbin\xmlwf.exe" + +!ENDIF + +# Begin Target + +# Name "xmlwf - Win32 Release" +# Name "xmlwf - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\codepage.c +# End Source File +# Begin Source File + +SOURCE=.\readfilemap.c +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\unixfilemap.c +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\win32filemap.c +# End Source File +# Begin Source File + +SOURCE=.\xmlfile.c +# End Source File +# Begin Source File + +SOURCE=.\xmlwf.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\codepage.h +# End Source File +# Begin Source File + +SOURCE=.\xmlfile.h +# End Source File +# Begin Source File + +SOURCE=.\xmltchar.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/asprintf.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/asprintf.c new file mode 100644 index 0000000..19c9632 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/asprintf.c @@ -0,0 +1,116 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include "xmlrpc_config.h" /* For HAVE_ASPRINTF, __inline__ */ +#include "xmlrpc-c/string_int.h" + + + +static __inline__ void +simpleVasprintf(char ** const retvalP, + const char * const fmt, + va_list varargs) { +/*---------------------------------------------------------------------------- + This is a poor man's implementation of vasprintf(), of GNU fame. +-----------------------------------------------------------------------------*/ + size_t const initialSize = 4096; + char * result; + + result = malloc(initialSize); + if (result != NULL) { + size_t bytesNeeded; + bytesNeeded = XMLRPC_VSNPRINTF(result, initialSize, fmt, varargs); + if (bytesNeeded > initialSize) { + free(result); + result = malloc(bytesNeeded); + if (result != NULL) + XMLRPC_VSNPRINTF(result, bytesNeeded, fmt, varargs); + } else if (bytesNeeded == initialSize) { + if (result[initialSize-1] != '\0') { + /* This is one of those old systems where vsnprintf() + returns the number of bytes it used, instead of the + number that it needed, and it in fact needed more than + we gave it. Rather than mess with this highly unlikely + case (old system and string > 4095 characters), we just + treat this like an out of memory failure. + */ + free(result); + result = NULL; + } + } + } + *retvalP = result; +} + + + +const char * const xmlrpc_strsol = "[insufficient memory to build string]"; + + + +void +xmlrpc_vasprintf(const char ** const retvalP, + const char * const fmt, + va_list varargs) { + + char * string; + +#if HAVE_ASPRINTF + vasprintf(&string, fmt, varargs); +#else + simpleVasprintf(&string, fmt, varargs); +#endif + + if (string == NULL) + *retvalP = xmlrpc_strsol; + else + *retvalP = string; +} + + + +void GNU_PRINTF_ATTR(2,3) +xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...) { + + va_list varargs; /* mysterious structure used by variable arg facility */ + + va_start(varargs, fmt); /* start up the mysterious variable arg facility */ + + xmlrpc_vasprintf(retvalP, fmt, varargs); + + va_end(varargs); +} + + + +const char * +xmlrpc_strdupnull(const char * const string) { + + if (string) + return strdup(string); + else + return NULL; +} + + + +void +xmlrpc_strfree(const char * const string) { + + if (string != xmlrpc_strsol) + free((void *)string); +} + + + +void +xmlrpc_strfreenull(const char * const string) { + + if (string) + xmlrpc_strfree(string); +} + + + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/error.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/error.c new file mode 100644 index 0000000..fd964d0 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/error.c @@ -0,0 +1,163 @@ +/* Copyright information is at end of file */ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include + +#include "xmlrpc-c/util_int.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/util.h" + + + +void +xmlrpc_assertion_failed(const char * const fileName, + int const lineNumber) { + + fprintf(stderr, "%s:%d: assertion failed\n", fileName, lineNumber); + abort(); +} + + + +static const char * const default_fault_string = + "Not enough memory for error message"; + +void xmlrpc_env_init (xmlrpc_env* env) +{ + XMLRPC_ASSERT(env != NULL); + + env->fault_occurred = 0; + env->fault_code = 0; + env->fault_string = NULL; +} + +void +xmlrpc_env_clean(xmlrpc_env * const envP) { + + XMLRPC_ASSERT(envP != NULL); + XMLRPC_ASSERT(envP->fault_string != XMLRPC_BAD_POINTER); + + /* env->fault_string may be one of three things: + ** 1) a NULL pointer + ** 2) a pointer to the default_fault_string + ** 3) a pointer to a malloc'd fault string + ** If we have case (3), we'll need to free it. */ + if (envP->fault_string && envP->fault_string != default_fault_string) + free(envP->fault_string); + envP->fault_string = XMLRPC_BAD_POINTER; +} + + + +void +xmlrpc_env_set_fault(xmlrpc_env * const envP, + int const faultCode, + const char * const faultDescription) { + + char * buffer; + + XMLRPC_ASSERT(envP != NULL); + XMLRPC_ASSERT(faultDescription != NULL); + + /* Clean up any leftover pointers. */ + xmlrpc_env_clean(envP); + + envP->fault_occurred = 1; + envP->fault_code = faultCode; + + /* Try to copy the fault string. If this fails, use a default. */ + buffer = strdup(faultDescription); + if (buffer == NULL) + envP->fault_string = (char *)default_fault_string; + else { + xmlrpc_force_to_utf8(buffer); + xmlrpc_force_to_xml_chars(buffer); + envP->fault_string = buffer; + } +} + + + +void +xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP, + int const code, + const char * const format, + va_list const args) { + + const char * faultDescription; + + xmlrpc_vasprintf(&faultDescription, format, args); + + xmlrpc_env_set_fault(envP, code, faultDescription); + + xmlrpc_strfree(faultDescription); +} + + + +void +xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP, + int const code, + const char * const format, + ...) { + va_list args; + + XMLRPC_ASSERT(envP != NULL); + XMLRPC_ASSERT(format != NULL); + + /* Print our error message to the buffer. */ + va_start(args, format); + xmlrpc_set_fault_formatted_v(envP, code, format, args); + va_end(args); +} + + + +void +xmlrpc_faultf(xmlrpc_env * const envP, + const char * const format, + ...) { + + va_list args; + + XMLRPC_ASSERT(envP != NULL); + XMLRPC_ASSERT(format != NULL); + + /* Print our error message to the buffer. */ + va_start(args, format); + xmlrpc_set_fault_formatted_v(envP, XMLRPC_INTERNAL_ERROR, format, args); + va_end(args); + +} + + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/make_printable.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/make_printable.c new file mode 100644 index 0000000..141bd30 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/make_printable.c @@ -0,0 +1,101 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include "xmlrpc_config.h" +#include "xmlrpc-c/string_int.h" + + + +const char * +xmlrpc_makePrintable_lp(const char * const input, + size_t const inputLength) { +/*---------------------------------------------------------------------------- + Convert an arbitrary string of characters in length-pointer form to + printable ASCII. E.g. convert newlines to "\n". + + Return the result in newly malloc'ed storage. Return NULL if we can't + get the storage. +-----------------------------------------------------------------------------*/ + char * output; + + output = malloc(inputLength*4+1); + /* Worst case, we render a character like \x01 -- 4 characters */ + + if (output != NULL) { + unsigned int inputCursor, outputCursor; + + for (inputCursor = 0, outputCursor = 0; + inputCursor < inputLength; + ++inputCursor) { + + if (0) { + } else if (input[inputCursor] == '\\') { + output[outputCursor++] = '\\'; + output[outputCursor++] = '\\'; + } else if (input[inputCursor] == '\n') { + output[outputCursor++] = '\\'; + output[outputCursor++] = 'n'; + } else if (input[inputCursor] == '\t') { + output[outputCursor++] = '\\'; + output[outputCursor++] = 't'; + } else if (input[inputCursor] == '\a') { + output[outputCursor++] = '\\'; + output[outputCursor++] = 'a'; + } else if (input[inputCursor] == '\r') { + output[outputCursor++] = '\\'; + output[outputCursor++] = 'r'; + } else if (isprint(input[inputCursor])) { + output[outputCursor++] = input[inputCursor]; + } else { + snprintf(&output[outputCursor], 5, "\\x%02x", + input[inputCursor]); + outputCursor += 4; + } + } + output[outputCursor++] = '\0'; + } + return output; +} + + + +const char * +xmlrpc_makePrintable(const char * const input) { +/*---------------------------------------------------------------------------- + Convert an arbitrary string of characters (NUL-terminated, though) to + printable ASCII. E.g. convert newlines to "\n". + + Return the result in newly malloc'ed storage. Return NULL if we can't + get the storage. +-----------------------------------------------------------------------------*/ + return xmlrpc_makePrintable_lp(input, strlen(input)); +} + + + +const char * +xmlrpc_makePrintableChar(char const input) { +/*---------------------------------------------------------------------------- + Return an ASCIIZ string consisting of the character 'input', + properly escaped so as to be printable. E.g., in C notation, '\n' + turns into "\\n" +-----------------------------------------------------------------------------*/ + const char * retval; + + if (input == '\0') + retval = strdup("\\0"); + else { + char buffer[2]; + + buffer[0] = input; + buffer[1] = '\0'; + + retval = xmlrpc_makePrintable(buffer); + } + return retval; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/memblock.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/memblock.c new file mode 100644 index 0000000..d79d4ca --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/memblock.c @@ -0,0 +1,214 @@ +/* Copyright information is at end of file */ +#include "xmlrpc_config.h" + +#include +#include +#include +#include + +#include "xmlrpc-c/util_int.h" +#include "xmlrpc-c/util.h" + +#ifdef EFENCE + /* when looking for corruption don't allocate extra slop */ +#define BLOCK_ALLOC_MIN (1) +#else +#define BLOCK_ALLOC_MIN (16) +#endif +#define BLOCK_ALLOC_MAX (128 * 1024 * 1024) + + +xmlrpc_mem_block * +xmlrpc_mem_block_new(xmlrpc_env * const env, + size_t const size) { + + xmlrpc_mem_block* block; + + XMLRPC_ASSERT_ENV_OK(env); + + block = (xmlrpc_mem_block*) malloc(sizeof(xmlrpc_mem_block)); + XMLRPC_FAIL_IF_NULL(block, env, XMLRPC_INTERNAL_ERROR, + "Can't allocate memory block"); + + xmlrpc_mem_block_init(env, block, size); + XMLRPC_FAIL_IF_FAULT(env); + + cleanup: + if (env->fault_occurred) { + if (block) + free(block); + return NULL; + } else { + return block; + } +} + +/* Destroy an existing xmlrpc_mem_block, and everything it contains. */ +void +xmlrpc_mem_block_free(xmlrpc_mem_block * const blockP) { + + XMLRPC_ASSERT(blockP != NULL); + XMLRPC_ASSERT(blockP->_block != NULL); + + xmlrpc_mem_block_clean(blockP); + free(blockP); +} + + + +/* Initialize the contents of the provided xmlrpc_mem_block. */ +void +xmlrpc_mem_block_init(xmlrpc_env * const envP, + xmlrpc_mem_block * const blockP, + size_t const size) { + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(blockP != NULL); + + blockP->_size = size; + if (size < BLOCK_ALLOC_MIN) + blockP->_allocated = BLOCK_ALLOC_MIN; + else + blockP->_allocated = size; + + blockP->_block = (void*) malloc(blockP->_allocated); + if (!blockP->_block) + xmlrpc_faultf(envP, "Can't allocate %u-byte memory block", + blockP->_allocated); +} + + + +/* Deallocate the contents of the provided xmlrpc_mem_block, but not + the block itself. +*/ +void +xmlrpc_mem_block_clean(xmlrpc_mem_block * const blockP) { + + XMLRPC_ASSERT(blockP != NULL); + XMLRPC_ASSERT(blockP->_block != NULL); + + free(blockP->_block); + blockP->_block = XMLRPC_BAD_POINTER; +} + + + +/* Get the size of the xmlrpc_mem_block. */ +size_t +xmlrpc_mem_block_size(const xmlrpc_mem_block * const blockP) { + + XMLRPC_ASSERT(blockP != NULL); + return blockP->_size; +} + + + +/* Get the contents of the xmlrpc_mem_block. */ +void * +xmlrpc_mem_block_contents(const xmlrpc_mem_block * const blockP) { + + XMLRPC_ASSERT(blockP != NULL); + return blockP->_block; +} + + + +/* Resize an xmlrpc_mem_block, preserving as much of the contents as + possible. +*/ +void +xmlrpc_mem_block_resize (xmlrpc_env * const envP, + xmlrpc_mem_block * const blockP, + size_t const size) { + + size_t proposed_alloc; + void* new_block; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(blockP != NULL); + + /* Check to see if we already have enough space. Maybe we'll get lucky. */ + if (size <= blockP->_allocated) { + blockP->_size = size; + return; + } + + /* Calculate a new allocation size. */ +#ifdef EFENCE + proposed_alloc = size; +#else + proposed_alloc = blockP->_allocated; + while (proposed_alloc < size && proposed_alloc <= BLOCK_ALLOC_MAX) + proposed_alloc *= 2; +#endif /* DEBUG_MEM_ERRORS */ + + if (proposed_alloc > BLOCK_ALLOC_MAX) + XMLRPC_FAIL(envP, XMLRPC_INTERNAL_ERROR, "Memory block too large"); + + /* Allocate our new memory block. */ + new_block = (void*) malloc(proposed_alloc); + XMLRPC_FAIL_IF_NULL(new_block, envP, XMLRPC_INTERNAL_ERROR, + "Can't resize memory block"); + + /* Copy over our data and update the xmlrpc_mem_block struct. */ + memcpy(new_block, blockP->_block, blockP->_size); + free(blockP->_block); + blockP->_block = new_block; + blockP->_size = size; + blockP->_allocated = proposed_alloc; + + cleanup: + return; +} + + + +void +xmlrpc_mem_block_append(xmlrpc_env * const envP, + xmlrpc_mem_block * const blockP, + const void * const data, + size_t const len) { + + int size; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(blockP != NULL); + + size = blockP->_size; + xmlrpc_mem_block_resize(envP, blockP, size + len); + XMLRPC_FAIL_IF_FAULT(envP); + + memcpy(((unsigned char*) blockP->_block) + size, data, len); + + cleanup: + return; +} + + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +*/ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/select.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/select.c new file mode 100644 index 0000000..8999884 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/select.c @@ -0,0 +1,59 @@ +#define _XOPEN_SOURCE 600 /* Get pselect() in */ + +#ifdef WIN32 +#include +#else +/* In some systems (SUS), the select() interface comes from ; + in others, from , and other from both. Including both + in this order appears to work on all. +*/ +#include +#include +#endif +#include + +#include "xmlrpc_config.h" + +#include "xmlrpc-c/select_int.h" + + +/* xmlrpc_pselect() is just for use with sockets. In a POSIX system, + it technically works for any file descriptor, but in Windows, select() + is part of the socket facility. +*/ + +int +xmlrpc_pselect(int const n, + fd_set * const readfdsP, + fd_set * const writefdsP, + fd_set * const exceptfdsP, + const xmlrpc_timespec * const timeoutP, + sigset_t * const sigmaskP) { + + int retval; + +#if HAVE_PSELECT +#if !HAVE_TIMESPEC + #error "Impossible configuration -- has pselect(), but not struct timespec" +#else + retval = pselect(n, readfdsP, writefdsP, exceptfdsP, timeoutP, sigmaskP); +#endif +#else /* HAVE_PSELECT */ + struct timeval timeout; + + timeout.tv_sec = timeoutP->tv_sec; + timeout.tv_usec = timeoutP->tv_nsec/1000; +#ifdef WIN32 + retval = select(n, readfdsP, writefdsP, exceptfdsP, &timeout); +#else + { + sigset_t origmask; + sigprocmask(SIG_SETMASK, sigmaskP, &origmask); + retval = select(n, readfdsP, writefdsP, exceptfdsP, &timeout); + sigprocmask(SIG_SETMASK, &origmask, NULL); + } +#endif +#endif + + return retval; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/sleep.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/sleep.c new file mode 100644 index 0000000..15b5150 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/sleep.c @@ -0,0 +1,21 @@ +#include "bool.h" + +#include "xmlrpc-c/sleep_int.h" + +#ifdef WIN32 +#include +#include +#else +#include +#endif + + +void +xmlrpc_millisecond_sleep(unsigned int const milliseconds) { + +#ifdef WIN32 + SleepEx(milliseconds, true); +#else + usleep(milliseconds * 1000); +#endif +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/time.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/time.c new file mode 100644 index 0000000..499ec68 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/time.c @@ -0,0 +1,173 @@ +#include "xmlrpc_config.h" +#include +#include + +#if !MSVCRT +#include +#endif + +#if MSVCRT +#include +#endif + +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/time_int.h" + + +/* A note about struct timeval and Windows: There is a 'struct + timeval' type in Windows, but it is just an argument to select(), + which is just part of the sockets interface. It's defined + identically to the POSIX type of the same name, but not meant for + general timekeeping as the POSIX type is. +*/ + +#if HAVE_GETTIMEOFDAY +static void +gettimeofdayPosix(xmlrpc_timespec * const todP) { + + struct timeval tv; + + gettimeofday(&tv, NULL); + + todP->tv_sec = tv.tv_sec; + todP->tv_nsec = tv.tv_usec * 1000; +} +#endif + + + +#if MSVCRT +static void +gettimeofdayWindows(xmlrpc_timespec * const todP) { + + __int64 const epochOffset = 116444736000000000i64; + /* Number of 100-nanosecond units between the beginning of the + Windows epoch (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970). + */ + FILETIME ft; + LARGE_INTEGER li; + __int64 t; + + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + t = (li.QuadPart - epochOffset) * 100; /* nanoseconds */ + todP->tv_sec = (long)(t / 1E9); + todP->tv_nsec = (long)(t - (__int64)todP->tv_sec * 1E9); +} +#endif + + + +void +xmlrpc_gettimeofday(xmlrpc_timespec * const todP) { + + assert(todP); + +#if HAVE_GETTIMEOFDAY + gettimeofdayPosix(todP); +#else +#if MSVCRT + gettimeofdayWindows(todP); +#else + #error "We don't know how to get the time of day on this system" +#endif +#endif /* HAVE_GETTIMEOFDAY */ +} + + + +static bool +isLeapYear(unsigned int const yearOfAd) { + + return + (yearOfAd % 4) == 0 && + ((yearOfAd % 100) != 0 || (yearOfAd % 400) == 0); +} + + + +void +xmlrpc_timegm(const struct tm * const tmP, + time_t * const timeValueP, + const char ** const errorP) { +/*---------------------------------------------------------------------------- + This does what GNU libc's timegm() does. +-----------------------------------------------------------------------------*/ + if (tmP->tm_year < 70 || + tmP->tm_mon > 11 || + tmP->tm_mon < 0 || + tmP->tm_mday > 31 || + tmP->tm_min > 60 || + tmP->tm_sec > 60 || + tmP->tm_hour > 24) { + + xmlrpc_asprintf(errorP, "Invalid time specification; a member " + "of struct tm is out of range"); + } else { + static unsigned int const monthDaysNonLeap[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + unsigned int totalDays; + unsigned int year; + unsigned int month; + + totalDays = 0; /* initial value */ + + for (year = 70; year < (unsigned int)tmP->tm_year; ++year) + totalDays += isLeapYear(1900 + year) ? 366 : 365; + + for (month = 0; month < (unsigned int)tmP->tm_mon; ++month) + totalDays += monthDaysNonLeap[month]; + + if (tmP->tm_mon > 1 && isLeapYear(1900 + tmP->tm_year)) + totalDays += 1; + + totalDays += tmP->tm_mday - 1; + + *errorP = NULL; + + *timeValueP = ((totalDays * 24 + + tmP->tm_hour) * 60 + + tmP->tm_min) * 60 + + tmP->tm_sec; + } +} + + + +void +xmlrpc_localtime(time_t const datetime, + struct tm * const tmP) { +/*---------------------------------------------------------------------------- + Convert datetime from standard to broken-down format in the local + time zone. + + For Windows, this is not thread-safe. If you run a version of Abyss + with multiple threads, you can get arbitrary results here. +-----------------------------------------------------------------------------*/ +#if HAVE_LOCALTIME_R + localtime_r(&datetime, tmP); +#else + *tmP = *localtime(&datetime); +#endif +} + + + +void +xmlrpc_gmtime(time_t const datetime, + struct tm * const resultP) { +/*---------------------------------------------------------------------------- + Convert datetime from standard to broken-down UTC format. + + For Windows, this is not thread-safe. If you run a version of Abyss + with multiple threads, you can get arbitrary results here. +-----------------------------------------------------------------------------*/ + +#if HAVE_GMTIME_R + gmtime_r(&datetime, resultP); +#else + *resultP = *gmtime(&datetime); +#endif +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/utf8.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/utf8.c new file mode 100644 index 0000000..e51ae1f --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/libutil/utf8.c @@ -0,0 +1,510 @@ +/* Copyright (C) 2001 by Eric Kidd. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + + +/*========================================================================= +** XML-RPC UTF-8 Utilities +**========================================================================= +** Routines for validating, encoding and decoding UTF-8 data. We try to +** be very, very strict about invalid UTF-8 data. +** +** All of the code in this file assumes that your machine represents +** wchar_t as a 16-bit (or wider) character containing UCS-2 data. If this +** assumption is incorrect, you may need to replace this file. +** +** For lots of information on Unicode and UTF-8 decoding, see: +** http://www.cl.cam.ac.uk/~mgk25/unicode.html +*/ + +#include "int.h" + +#include "xmlrpc_config.h" +#include "bool.h" +#include "xmlrpc-c/base.h" + +/*========================================================================= +** Tables and Constants +**========================================================================= +** We use a variety of tables and constants to help decode and validate +** UTF-8 data. +*/ + +/* The number of bytes in a UTF-8 sequence starting with the character used +** as the array index. A zero entry indicates an illegal initial byte. +** This table was generated using a Perl script and information from the +** UTF-8 standard. +** +** Fredrik Lundh's UTF-8 decoder Python 2.0 uses a similar table. But +** since Python 2.0 has the icky CNRI license, I regenerated this +** table from scratch and wrote my own decoder. */ +static unsigned char utf8_seq_length[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 +}; + +/* The minimum legal character value for a UTF-8 sequence of the given +** length. We have to check this to avoid accepting "overlong" UTF-8 +** sequences, which use more bytes than necessary to encode a given +** character. Such sequences are commonly used by evil people to bypass +** filters and security checks. This table is based on the UTF-8-test.txt +** file by Markus Kuhn . */ +static uint32_t const utf8_min_char_for_length[] = { + 0, /* Length 0: Not used (meaningless) */ + 0x0000, /* Length 1: Not used (special-cased) */ + 0x0080, /* Length 2 */ + 0x0800, /* Length 3 */ + 0x00010000, /* Length 4 */ + 0x00200000, /* Length 5 */ + 0x04000000 /* Length 6 */ +}; + +/* This is the maximum legal 16-byte (UCS-2) character. Again, this +** information is based on UTF-8-test.txt. */ +#define UCS2_MAX_LEGAL_CHARACTER (0xFFFD) + +/* First and last UTF-16 surrogate characters. These are *not* legal UCS-2 +** characters--they're used to code for UCS-4 characters when using +** UTF-16. They should never appear in decoded UTF-8 data! Again, these +** could hypothetically be used to bypass security measures on some machines. +** Based on UTF-8-test.txt. */ +#define UTF16_FIRST_SURROGATE (0xD800) +#define UTF16_LAST_SURROGATE (0xDFFF) + +/* Is the character 'c' a UTF-8 continuation character? */ +#define IS_CONTINUATION(c) (((c) & 0xC0) == 0x80) + +#define MAX_ENCODED_BYTES (3) + /* Maximum number of bytes needed to encode in UTF-8 a character + in the Basic Multilingual Plane. + */ + + +#if HAVE_UNICODE_WCHAR + + +static void +decode_utf8(xmlrpc_env * const envP, + const char * const utf8_data, + size_t const utf8_len, + wchar_t * const ioBuff, + size_t * const outBuffLenP) { +/*---------------------------------------------------------------------------- + Decode to UCS-2 (or validates as UTF-8 that can be decoded to UCS-2) + a UTF-8 string. To validate, set ioBuff and outBuffLenP to NULL. + To decode, allocate a sufficiently large buffer, pass it as ioBuff, + and pass a pointer as as outBuffLenP. The data will be written to + the buffer, and the length to outBuffLenP. + + We assume that wchar_t holds a single UCS-2 character in native-endian + byte ordering. +-----------------------------------------------------------------------------*/ + size_t i, length, out_pos; + char init, con1, con2; + wchar_t wc; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(utf8_data); + XMLRPC_ASSERT((!ioBuff && !outBuffLenP) || + (ioBuff && outBuffLenP)); + + /* Suppress GCC warning about possibly undefined variable. */ + wc = 0; + + i = 0; + out_pos = 0; + while (i < utf8_len) { + init = utf8_data[i]; + if ((init & 0x80) == 0x00) { + /* Convert ASCII character to wide character. */ + wc = init; + i++; + } else { + /* Look up the length of this UTF-8 sequence. */ + length = utf8_seq_length[(unsigned char) init]; + + /* Check to make sure we have enough bytes to convert. */ + if (i + length > utf8_len) + XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR, + "Truncated UTF-8 sequence"); + + /* Decode a multibyte UTF-8 sequence. */ + switch (length) { + case 0: + XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR, + "Invalid UTF-8 initial byte"); + + case 2: + /* 110xxxxx 10xxxxxx */ + con1 = utf8_data[i+1]; + if (!IS_CONTINUATION(con1)) + XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR, + "UTF-8 sequence too short"); + wc = ((((wchar_t) (init & 0x1F)) << 6) | + (((wchar_t) (con1 & 0x3F)))); + break; + + case 3: + /* 1110xxxx 10xxxxxx 10xxxxxx */ + con1 = utf8_data[i+1]; + con2 = utf8_data[i+2]; + if (!IS_CONTINUATION(con1) || !IS_CONTINUATION(con2)) + XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR, + "UTF-8 sequence too short"); + wc = ((((wchar_t) (init & 0x0F)) << 12) | + (((wchar_t) (con1 & 0x3F)) << 6) | + (((wchar_t) (con2 & 0x3F)))); + break; + + case 4: + /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + case 5: + /* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + case 6: + /* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + /* This would require more than 16 bits in UTF-16, so + it can't be represented in UCS-2, so it's beyond + our capability. Characters in the BMP fit in 16 + bits. + */ + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INVALID_UTF8_ERROR, + "UTF-8 string contains a character not in the " + "Basic Multilingual Plane (first byte %08x)", + init); + goto cleanup; + + default: + XMLRPC_ASSERT("Error in UTF-8 decoder tables"); + } + + /* Advance to the end of the sequence. */ + i += length; + + /* Check for illegal UCS-2 characters. */ + if (wc > UCS2_MAX_LEGAL_CHARACTER) + XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR, + "UCS-2 characters > U+FFFD are illegal"); + + /* Check for UTF-16 surrogates. */ + if (UTF16_FIRST_SURROGATE <= wc && wc <= UTF16_LAST_SURROGATE) + XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR, + "UTF-16 surrogates may not appear in UTF-8 data"); + + /* Check for overlong sequences. */ + if ((uint32_t)wc < utf8_min_char_for_length[length]) + XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR, + "Overlong UTF-8 sequence not allowed"); + } + + /* If we have a buffer, write our character to it. */ + if (ioBuff) { + ioBuff[out_pos++] = wc; + } + } + + /* Record the number of characters we found. */ + if (outBuffLenP) + *outBuffLenP = out_pos; + + cleanup: + if (envP->fault_occurred) { + if (outBuffLenP) + *outBuffLenP = 0; + } +} + + + +xmlrpc_mem_block * +xmlrpc_utf8_to_wcs(xmlrpc_env * const envP, + const char * const utf8_data, + size_t const utf8_len) { +/*---------------------------------------------------------------------------- + Decode UTF-8 string to a "wide character string". This function + returns an xmlrpc_mem_block with an element type of wchar_t. Don't + try to intepret the block in a bytewise fashion--it won't work in + any useful or portable fashion. + + For backward compatibility, we return a meaningful value even when we + fail. We return NULL when we fail. +-----------------------------------------------------------------------------*/ + xmlrpc_mem_block * wcsP; + size_t wcs_length; + + /* Allocate a memory block large enough to hold any possible output. + We assume that each byte of the input may decode to a whcar_t. + */ + wcsP = XMLRPC_MEMBLOCK_NEW(wchar_t, envP, utf8_len); + if (!envP->fault_occurred) { + /* Decode the UTF-8 data. */ + decode_utf8(envP, utf8_data, utf8_len, + XMLRPC_MEMBLOCK_CONTENTS(wchar_t, wcsP), + &wcs_length); + if (!envP->fault_occurred) { + /* We can't have overrun our buffer. */ + XMLRPC_ASSERT(wcs_length <= utf8_len); + + /* Correct the length of the memory block. */ + XMLRPC_MEMBLOCK_RESIZE(wchar_t, envP, wcsP, wcs_length); + } + if (envP->fault_occurred) + XMLRPC_MEMBLOCK_FREE(wchar_t, wcsP); + } + if (envP->fault_occurred) + return NULL; + else + return wcsP; +} + + + +xmlrpc_mem_block * +xmlrpc_wcs_to_utf8(xmlrpc_env * const envP, + const wchar_t * const wcs_data, + size_t const wcs_len) { +/*---------------------------------------------------------------------------- + Encode a "wide character string" as UTF-8. + + For backward compatibility, we return a meaningful value even when we + fail. We return NULL when we fail. +-----------------------------------------------------------------------------*/ + size_t const estimate = wcs_len * MAX_ENCODED_BYTES; + /* Our conservative estimate of how big the output will be; + i.e. we know it won't be larger than this. For the estimate, + we assume that every wchar might encode to the maximum length. + */ + xmlrpc_mem_block * utf8P; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(wcs_data); + + utf8P = XMLRPC_MEMBLOCK_NEW(char, envP, estimate); + if (!envP->fault_occurred) { + unsigned char * const buffer = + XMLRPC_MEMBLOCK_CONTENTS(unsigned char, utf8P); + size_t bytesUsed; + size_t i; + + bytesUsed = 0; + for (i = 0; i < wcs_len && !envP->fault_occurred; ++i) { + wchar_t const wc = wcs_data[i]; + if (wc <= 0x007F) + buffer[bytesUsed++] = wc & 0x7F; + else if (wc <= 0x07FF) { + /* 110xxxxx 10xxxxxx */ + buffer[bytesUsed++] = 0xC0 | (wc >> 6); + buffer[bytesUsed++] = 0x80 | (wc & 0x3F); + } else if (wc <= 0xFFFF) { + /* 1110xxxx 10xxxxxx 10xxxxxx */ + buffer[bytesUsed++] = 0xE0 | (wc >> 12); + buffer[bytesUsed++] = 0x80 | ((wc >> 6) & 0x3F); + buffer[bytesUsed++] = 0x80 | (wc & 0x3F); + } else + xmlrpc_faultf(envP, + "Don't know how to encode UCS-4 characters yet"); + } + if (!envP->fault_occurred) { + XMLRPC_ASSERT(bytesUsed <= estimate); + + XMLRPC_MEMBLOCK_RESIZE(char, envP, utf8P, bytesUsed); + } + if (envP->fault_occurred) + XMLRPC_MEMBLOCK_FREE(char, utf8P); + } + + if (envP->fault_occurred) + return NULL; + else + return utf8P; +} + + + +#else /* HAVE_UNICODE_WCHAR */ + +xmlrpc_mem_block * +xmlrpc_utf8_to_wcs(xmlrpc_env * const envP, + const char * const utf8_data ATTR_UNUSED, + size_t const utf8_len ATTR_UNUSED) { + + xmlrpc_faultf(envP, "INTERNAL ERROR: xmlrpc_utf8_to_wcs() called " + "on a system that doesn't do Unicode!"); + + return NULL; +} +#endif /* HAVE_UNICODE_WCHAR */ + + +void +xmlrpc_force_to_utf8(char * const buffer) { +/*---------------------------------------------------------------------------- + Force the contents of 'buffer' to be valid UTF-8, any way possible. + The buffer ends with a NUL character, and the mutation does not make + it longer. + + The most common reason for a string that's supposed to be UTF-8 not + to be UTF-8 is that it was supposed to be ASCII but instead + includes garbage with the high bit on (ASCII characters always have + the high bit off), or maybe a primitive 8-bit ASCII extension. + Therefore, we force it to UTF-8 by replacing some bytes that have + the high bit set with DEL (0x7F). That would leave the other + characters meaningful. +-----------------------------------------------------------------------------*/ + char * p; + + for (p = &buffer[0]; *p;) { + unsigned int const length = utf8_seq_length[(unsigned char) *p]; + + bool forceDel; + uint32_t decoded; + + forceDel = false; + decoded = 0; /* suppress compiler warning; valid when !forceDel */ + + switch (length) { + case 1: + /* One-byte UTF-8 characters are easy. */ + decoded = *p; + break; + case 2: + /* 110xxxxx 10xxxxxx */ + if (!*(p+1) || !(*p+2)) + forceDel = true; + else if (!IS_CONTINUATION(*(p+1))) + forceDel = true; + else + decoded = + ((uint32_t)(*(p+0) & 0x1F) << 6) | + ((uint32_t)(*(p+1) & 0x3F) << 0); + break; + case 3: + /* 1110xxxx 10xxxxxx 10xxxxxx */ + if (!*(p+1) || !(*p+2) || !(*p+3)) + forceDel = true; + else if (!IS_CONTINUATION(*(p+1)) || !IS_CONTINUATION(*(p+2))) + forceDel = true; + else + decoded = + ((uint32_t)(*(p+0) & 0x0F) << 12) | + ((uint32_t)(*(p+1) & 0x3F) << 6) | + ((uint32_t)(*(p+2) & 0x3F) << 0); + break; + default: + forceDel = true; + } + + if (!forceDel) { + if (decoded > UCS2_MAX_LEGAL_CHARACTER) + forceDel = true; + else if (UTF16_FIRST_SURROGATE <= decoded && + decoded <= UTF16_LAST_SURROGATE) + forceDel = true; + else if (decoded < utf8_min_char_for_length[length]) + forceDel = true; + } + + if (forceDel) { + /* Not a valid UTF-8 character, so replace the first byte + with a nice simple ASCII DEL. + */ + *p = 0x7F; + p += 1; + } else + p += length; + } +} + + + +void +xmlrpc_force_to_xml_chars(char * const buffer) { +/*---------------------------------------------------------------------------- + Modify 'buffer' so that it contains nothing but valid XML + characters. The buffer ends with a NUL character, and the mutation + does not make it longer. + + Note that the valid characters in an XML document are all Unicode + codepoints except the ASCII control characters, plus CR, LF, and + Tab. + + We change all non-XML characters to DEL (0x7F). + + Assume input is valid UTF-8. +-----------------------------------------------------------------------------*/ + char * p; + + for (p = &buffer[0]; *p;) { + unsigned int const length = utf8_seq_length[(unsigned char) *p]; + + if (length == 1) { + if (*p < 0x20 && *p != '\r' && *p != '\n' && *p != '\t') + /* Not valid XML. Force to DEL */ + *p = 0x7f; + } else { + /* We assume here that all other UTF-8 characters are + valid XML, but it's apparently not actually true. + */ + } + + { + unsigned int i; + /* Advance to next UTF-8 character */ + for (i = 0; i < length && *p; ++i) + ++p; + } + } +} + + + +void +xmlrpc_validate_utf8(xmlrpc_env * const env, + const char * const utf8_data, + size_t const utf8_len) { +/*---------------------------------------------------------------------------- + Validate that a string is valid UTF-8. +-----------------------------------------------------------------------------*/ +#if HAVE_UNICODE_WCHAR + decode_utf8(env, utf8_data, utf8_len, NULL, NULL); +#else + /* We don't have a convenient way to validate, so we just fake it and + call it valid. + */ +#endif +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/casprintf.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/casprintf.c new file mode 100644 index 0000000..8543281 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/casprintf.c @@ -0,0 +1,93 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include "xmlrpc_config.h" /* For HAVE_ASPRINTF, __inline__ */ +#include "casprintf.h" + + + +static __inline__ void +simpleVasprintf(char ** const retvalP, + const char * const fmt, + va_list varargs) { +/*---------------------------------------------------------------------------- + This is a poor man's implementation of vasprintf(), of GNU fame. +-----------------------------------------------------------------------------*/ + size_t const initialSize = 4096; + char * result; + + result = malloc(initialSize); + if (result != NULL) { + size_t bytesNeeded; + bytesNeeded = XMLRPC_VSNPRINTF(result, initialSize, fmt, varargs); + if (bytesNeeded > initialSize) { + free(result); + result = malloc(bytesNeeded); + if (result != NULL) + XMLRPC_VSNPRINTF(result, bytesNeeded, fmt, varargs); + } else if (bytesNeeded == initialSize) { + if (result[initialSize-1] != '\0') { + /* This is one of those old systems where vsnprintf() + returns the number of bytes it used, instead of the + number that it needed, and it in fact needed more than + we gave it. Rather than mess with this highly unlikely + case (old system and string > 4095 characters), we just + treat this like an out of memory failure. + */ + free(result); + result = NULL; + } + } + } + *retvalP = result; +} + + + +const char * const strsol = "[Insufficient memory to build string]"; + + + +void +cvasprintf(const char ** const retvalP, + const char * const fmt, + va_list varargs) { + + char * string; + +#if HAVE_ASPRINTF + vasprintf(&string, fmt, varargs); +#else + simpleVasprintf(&string, fmt, varargs); +#endif + + if (string == NULL) + *retvalP = strsol; + else + *retvalP = string; +} + + + +void GNU_PRINTF_ATTR(2,3) +casprintf(const char ** const retvalP, const char * const fmt, ...) { + + va_list varargs; /* mysterious structure used by variable arg facility */ + + va_start(varargs, fmt); /* start up the mysterious variable arg facility */ + + cvasprintf(retvalP, fmt, varargs); + + va_end(varargs); +} + + + +void +strfree(const char * const string) { + + if (string != strsol) + free((void *)string); +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/cmdline_parser.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/cmdline_parser.c new file mode 100644 index 0000000..37caadb --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/cmdline_parser.c @@ -0,0 +1,587 @@ +#include "xmlrpc_config.h" /* prereq for mallocvar.h -- defines __inline__ */ + +#include +#include +#include +#include +#include + +#include "bool.h" +#include "int.h" +#include "mallocvar.h" +#include "casprintf.h" +#include "getoptx.h" +#include "string_parser.h" + +#include "cmdline_parser.h" + +#define MAXOPTS 100 + +struct optionDesc { + const char * name; + enum optiontype type; + bool present; + union { + unsigned int u; + int i; + const char * s; + uint64_t llu; + double d; + } value; +}; + + + +struct cmdlineParserCtl { + struct optionDesc * optionDescArray; + unsigned int numOptions; + const char ** argumentArray; + unsigned int numArguments; +}; + + + +static struct optionx * +createLongOptsArray(struct optionDesc * const optionDescArray, + unsigned int const numOptions) { + + struct optionx * longopts; + + MALLOCARRAY(longopts, numOptions+1); + if (longopts != NULL) { + unsigned int i; + + for (i = 0; i < numOptions; ++i) { + longopts[i].name = optionDescArray[i].name; + /* If the option takes a value, we say it is optional even + though it never is. That's because if we say it is + mandatory, getopt_long_only() pretends it doesn't even + recognize the option if the user doesn't give a value. + We prefer to generate a meaningful error message when + the user omits a required option value. + */ + longopts[i].has_arg = + optionDescArray[i].type == OPTTYPE_FLAG ? + no_argument : optional_argument; + longopts[i].flag = NULL; + longopts[i].val = i; + } + longopts[numOptions].name = 0; + longopts[numOptions].has_arg = 0; + longopts[numOptions].flag = 0; + longopts[numOptions].val = 0; + } + return longopts; +} + + + +static void +parseInt(enum optiontype const type, + const char * const optarg, + unsigned int * const valueUintP, + int * const valueIntP, + const char ** const errorP) { + + if (optarg == NULL) + casprintf(errorP, "Option requires a value"); + else if (strlen(optarg) == 0) + casprintf(errorP, "Numeric option value is null string"); + else { + char * tailptr; + long const longvalue = strtol(optarg, &tailptr, 10); + + if (*tailptr != '\0') + casprintf(errorP, "Non-numeric value " + "for numeric option value: '%s'", optarg); + else if (errno == ERANGE || longvalue > INT_MAX) + casprintf(errorP, "Numeric value out of range: %s", optarg); + else { + if (type == OPTTYPE_UINT) { + if (longvalue < 0) + casprintf(errorP, "Unsigned numeric value is " + "negative: %ld", longvalue); + else { + *errorP = NULL; + *valueUintP = (unsigned int) longvalue; + } + } else { + *errorP = NULL; + *valueIntP = (int) longvalue; + } + } + } +} + + + +static void +parseBinUint(const char * const optarg, + uint64_t * const valueP, + const char ** const errorP) { + + if (optarg == NULL) + casprintf(errorP, "Option requires a value"); + else if (strlen(optarg) == 0) + casprintf(errorP, "Numeric option value is null string"); + else { + const char * error; + interpretBinUint(optarg, valueP, &error); + + if (error) { + casprintf(errorP, "Invalid numeric option value '%s'. %s", + optarg, error); + strfree(error); + } + } +} + + + +static void +parseFloat(const char * const optarg, + double * const valueP, + const char ** const errorP) { + + if (optarg == NULL) + casprintf(errorP, "Option requires a value"); + else if (strlen(optarg) == 0) + casprintf(errorP, "Numeric option value is null string"); + else { + char * tailptr; + double const doublevalue = strtod(optarg, &tailptr); + + if (*tailptr != '\0') + casprintf(errorP, "Non-numeric value " + "for numeric option value: '%s'", optarg); + else if (errno == ERANGE) + casprintf(errorP, "Numeric value out of range: %s", optarg); + else { + *errorP = NULL; + *valueP = doublevalue; + } + } +} + + + +static void +parseOptionValue(const char * const optarg, + struct optionDesc * const optionP, + const char ** const errorP) { + + switch (optionP->type) { + case OPTTYPE_FLAG: + *errorP = NULL; + break; + case OPTTYPE_INT: + case OPTTYPE_UINT: + parseInt(optionP->type, optarg, &optionP->value.u, &optionP->value.i, + errorP); + break; + case OPTTYPE_STRING: + if (optarg == NULL) + casprintf(errorP, "Option requires a value"); + else { + *errorP = NULL; + optionP->value.s = strdup(optarg); + } + break; + case OPTTYPE_BINUINT: + parseBinUint(optarg, &optionP->value.llu, errorP); + break; + case OPTTYPE_FLOAT: + parseFloat(optarg, &optionP->value.d, errorP); + break; + } +} + + + +static void +processOption(struct optionDesc * const optionP, + const char * const optarg, + const char ** const errorP) { + + const char * error; + + parseOptionValue(optarg, optionP, &error); + if (error) + casprintf(errorP, "Error in '%s' option: %s", optionP->name, error); + else + optionP->present = true; +} + + + +static void +extractArguments(struct cmdlineParserCtl * const cpP, + unsigned int const argc, + const char ** const argv) { + + cpP->numArguments = argc - getopt_argstart(); + MALLOCARRAY(cpP->argumentArray, cpP->numArguments); + + if (cpP->argumentArray == NULL) { + fprintf(stderr, "Unable to allocate memory for argument array " + "(%u arguments)\n", cpP->numArguments); + abort(); + } else { + unsigned int i; + + for (i = 0; i < cpP->numArguments; ++i) { + cpP->argumentArray[i] = strdup(argv[getopt_argstart() + i]); + if (cpP->argumentArray[i] == NULL) { + fprintf(stderr, "Unable to allocate memory for Argument %u\n", + i); + abort(); + } + } + } +} + + + +void +cmd_processOptions(cmdlineParser const cpP, + int const argc, + const char ** const argv, + const char ** const errorP) { + + struct optionx * longopts; + + longopts = createLongOptsArray(cpP->optionDescArray, cpP->numOptions); + + if (longopts == NULL) + casprintf(errorP, "Unable to get memory for longopts array"); + else { + int endOfOptions; + unsigned int i; + + *errorP = NULL; + + /* Set up initial assumption: No options present */ + + for (i = 0; i < cpP->numOptions; ++i) + cpP->optionDescArray[i].present = false; + + endOfOptions = false; /* initial value */ + + while (!endOfOptions && !*errorP) { + int const opterr0 = 0; + /* Don't let getopt_long_only() print an error message */ + unsigned int longoptsIndex; + const char * unrecognizedOption; + const char * optarg; + + getopt_long_onlyx(argc, (char**) argv, "", longopts, + &longoptsIndex, opterr0, + &endOfOptions, &optarg, &unrecognizedOption); + + if (unrecognizedOption) + casprintf(errorP, "Unrecognized option: '%s'", + unrecognizedOption); + else { + if (!endOfOptions) + processOption(&cpP->optionDescArray[longoptsIndex], optarg, + errorP); + } + } + if (!*errorP) + extractArguments(cpP, argc, argv); + + free(longopts); + } +} + + + +cmdlineParser +cmd_createOptionParser(void) { + + struct cmdlineParserCtl * cpP; + + MALLOCVAR(cpP); + + if (cpP != NULL) { + struct optionDesc * optionDescArray; + + cpP->numOptions = 0; + MALLOCARRAY(optionDescArray, MAXOPTS); + if (optionDescArray == NULL) { + free(cpP); + cpP = NULL; + } else + cpP->optionDescArray = optionDescArray; + } + return cpP; +} + + + +void +cmd_destroyOptionParser(cmdlineParser const cpP) { + + unsigned int i; + + for (i = 0; i < cpP->numOptions; ++i) { + struct optionDesc const option = cpP->optionDescArray[i]; + if (option.type == OPTTYPE_STRING && option.present) + strfree(option.value.s); + strfree(option.name); + } + + for (i = 0; i < cpP->numArguments; ++i) + strfree(cpP->argumentArray[i]); + + free(cpP->optionDescArray); + free(cpP); +} + + + +void +cmd_defineOption(cmdlineParser const cpP, + const char * const name, + enum optiontype const type) { + + if (cpP->numOptions < MAXOPTS) { + cpP->optionDescArray[cpP->numOptions].name = strdup(name); + cpP->optionDescArray[cpP->numOptions].type = type; + + ++cpP->numOptions; + } +} + + + +static struct optionDesc * +findOptionDesc(struct cmdlineParserCtl * const cpP, + const char * const name) { + + struct optionDesc * retval; + unsigned int i; + + retval = NULL; + + for (i = 0; i < cpP->numOptions && !retval; ++i) + if (strcmp(cpP->optionDescArray[i].name, name) == 0) + retval = &cpP->optionDescArray[i]; + + return retval; +} + + + +int +cmd_optionIsPresent(cmdlineParser const cpP, + const char * const name) { + + struct optionDesc * const optionDescP = findOptionDesc(cpP, name); + + bool present; + + if (!optionDescP) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "optionIsPresent() called for undefined option '%s'\n", + name); + abort(); + } else + present = optionDescP->present; + + return present; +} + + + +unsigned int +cmd_getOptionValueUint(cmdlineParser const cpP, + const char * const name) { + + struct optionDesc * const optionDescP = findOptionDesc(cpP, name); + + unsigned int retval; + + if (!optionDescP) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueUint() called for undefined option '%s'\n", + name); + abort(); + } else { + if (optionDescP->type != OPTTYPE_UINT) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueUint() called for non-unsigned integer " + "option '%s'\n", optionDescP->name); + abort(); + } else { + if (optionDescP->present) + retval = optionDescP->value.u; + else + retval = 0; + } + } + return retval; +} + + + +int +cmd_getOptionValueInt(cmdlineParser const cpP, + const char * const name) { + + struct optionDesc * const optionDescP = findOptionDesc(cpP, name); + + int retval; + + if (!optionDescP) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueInt() called for undefined option '%s'\n", + name); + abort(); + } else { + if (optionDescP->type != OPTTYPE_INT) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueInt() called for non-integer " + "option '%s'\n", optionDescP->name); + abort(); + } else { + if (optionDescP->present) + retval = optionDescP->value.i; + else + retval = 0; + } + } + + return retval; +} + + + +const char * +cmd_getOptionValueString(cmdlineParser const cpP, + const char * const name) { + + struct optionDesc * const optionDescP = findOptionDesc(cpP, name); + + const char * retval; + + if (!optionDescP) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueString() called for " + "undefined option '%s'\n", + name); + abort(); + } else { + if (optionDescP->type != OPTTYPE_STRING) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "getOptionValueString() called for non-string " + "option '%s'\n", optionDescP->name); + abort(); + } else { + if (optionDescP->present) { + retval = strdup(optionDescP->value.s); + if (retval == NULL) { + fprintf(stderr, + "out of memory in cmd_getOptionValueString()\n"); + abort(); + } + } else + retval = NULL; + } + } + return retval; +} + + + +uint64_t +cmd_getOptionValueBinUint(cmdlineParser const cpP, + const char * const name) { + + struct optionDesc * const optionDescP = findOptionDesc(cpP, name); + + uint64_t retval; + + if (!optionDescP) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueUint() called for undefined option '%s'\n", + name); + abort(); + } else { + if (optionDescP->type != OPTTYPE_BINUINT) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueBinUint() called for " + "non-OPTTYPE_BINUINT " + "option '%s'\n", optionDescP->name); + abort(); + } else { + if (optionDescP->present) + retval = optionDescP->value.llu; + else + retval = 0; + } + } + return retval; +} + + + +double +cmd_getOptionValueFloat(cmdlineParser const cpP, + const char * const name) { + + struct optionDesc * const optionDescP = findOptionDesc(cpP, name); + + double retval; + + if (!optionDescP) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueInt() called for undefined option '%s'\n", + name); + abort(); + } else { + if (optionDescP->type != OPTTYPE_FLOAT) { + fprintf(stderr, "cmdlineParser called incorrectly. " + "cmd_getOptionValueInt() called for non-float " + "option '%s'\n", optionDescP->name); + abort(); + } else { + if (optionDescP->present) + retval = optionDescP->value.d; + else + retval = 0.0; + } + } + return retval; +} + + + +unsigned int +cmd_argumentCount(cmdlineParser const cpP) { + + return cpP->numArguments; + +} + + + +const char * +cmd_getArgument(cmdlineParser const cpP, + unsigned int const argNumber) { + + const char * retval; + + if (argNumber >= cpP->numArguments) + retval = NULL; + else { + retval = strdup(cpP->argumentArray[argNumber]); + + if (retval == NULL) { + fprintf(stderr, + "out of memory in cmd_getArgument()\n"); + abort(); + } + } + return retval; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/cmdline_parser_cpp.cpp b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/cmdline_parser_cpp.cpp new file mode 100644 index 0000000..0fc951e --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/cmdline_parser_cpp.cpp @@ -0,0 +1,157 @@ +#include +#include + +#include "girstring.h" +#include "casprintf.h" +#include "cmdline_parser.h" + +#include "cmdline_parser.hpp" + +using namespace std; + + + +static enum optiontype +optTypeConvert( + CmdlineParser::optType const arg) { + + enum optiontype retval; + + retval = OPTTYPE_FLAG; // defeat compiler warning + + switch (arg) { + case CmdlineParser::FLAG: retval = OPTTYPE_FLAG; break; + case CmdlineParser::INT: retval = OPTTYPE_INT; break; + case CmdlineParser::UINT: retval = OPTTYPE_UINT; break; + case CmdlineParser::STRING: retval = OPTTYPE_STRING; break; + case CmdlineParser::BINUINT: retval = OPTTYPE_BINUINT; break; + case CmdlineParser::FLOAT: retval = OPTTYPE_FLOAT; break; + } + return retval; +} + + + +CmdlineParser::CmdlineParser() { + + this->cp = cmd_createOptionParser(); +} + + + +CmdlineParser::~CmdlineParser() { + cmd_destroyOptionParser(this->cp); +} + + + +void +CmdlineParser::defineOption( + string const optionName, + optType const optionType) { + + cmd_defineOption(this->cp, optionName.c_str(), + optTypeConvert(optionType)); +} + + + +void +CmdlineParser::processOptions( + int const argc, + const char ** const argv) { + + const char * error; + + cmd_processOptions(this->cp, argc, argv, &error); + if (error) { + string const errorS(error); + strfree(error); + throw(runtime_error(errorS)); + } +} + + + +bool +CmdlineParser::optionIsPresent( + string const optionName) const { + + return (cmd_optionIsPresent(this->cp, optionName.c_str()) ? true : false); +} + + + +int +CmdlineParser::getOptionValueInt( + string const optionName) const { + + return cmd_getOptionValueInt(this->cp, optionName.c_str()); +} + + + +unsigned int +CmdlineParser::getOptionValueUint( + string const optionName) const { + + return cmd_getOptionValueUint(this->cp, optionName.c_str()); +} + + + +unsigned long long +CmdlineParser::getOptionValueBinUint( + string const optionName) const { + + return cmd_getOptionValueBinUint(this->cp, optionName.c_str()); +} + + + +double +CmdlineParser::getOptionValueFloat( + string const optionName) const { + + return cmd_getOptionValueFloat(this->cp, optionName.c_str()); +} + + + +string +CmdlineParser::getOptionValueString( + string const optionName) const { + + const char * const value = + cmd_getOptionValueString(this->cp, optionName.c_str()); + + string retval; + + if (value) { + retval = string(value); + strfree(value); + } else + retval = ""; + + return retval; +} + + + +unsigned int +CmdlineParser::argumentCount() const { + + return cmd_argumentCount(this->cp); +} + + + +string +CmdlineParser::getArgument( + unsigned int const argNumber) const { + + const char * const value = cmd_getArgument(this->cp, argNumber); + string const retval(value); + strfree(value); + return retval; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/getoptx.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/getoptx.c new file mode 100644 index 0000000..114bacc --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/getoptx.c @@ -0,0 +1,466 @@ +/* This version of `getopt' appears to the caller like standard Unix getopt() + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As getopt() works, it permutes the elements of `argv' so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable _POSIX_OPTION_ORDER disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. +*/ + +#include +#include +#include + +#include "getoptx.h" + +/* Note that on some systems, the header files above declare variables + for use with their native getopt facilities, and those variables have + the same names as we'd like to use. So we use things like optargx + instead of optarg to avoid the collision. +*/ + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. +*/ +static char *optargx = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to getoptx(). + + On entry to getoptx(), zero means this is the first call; initialize. + + When getoptx() returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optindx' communicates from one call to the next + how much of ARGV has been scanned so far. +*/ + +static int optindx = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. +*/ + +static int opterrx; + +/* Index in _GETOPT_LONG_OPTIONS of the long-named option actually found. + Only valid when a long-named option was found. */ + +static int option_index; + +struct optionx * _getopt_long_options; + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optindx), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange(char ** const argv) { + unsigned int const nonopts_size = + (last_nonopt - first_nonopt) * sizeof (char *); + char **temp = (char **) malloc (nonopts_size); + + if (temp == NULL) + abort(); + + /* Interchange the two blocks of data in argv. */ + + memcpy (temp, &argv[first_nonopt], nonopts_size); + memcpy (&argv[first_nonopt], &argv[last_nonopt], + (optindx - last_nonopt) * sizeof (char *)); + memcpy (&argv[first_nonopt + optindx - last_nonopt], temp, + nonopts_size); + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optindx - last_nonopt); + last_nonopt = optindx; + + free(temp); +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If getoptx() + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If getoptx() finds another option character, it returns that character, + updating `optindx' and `nextchar' so that the next call to getoptx() can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, getoptx() returns `EOF'. + Then `optindx' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterrx' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optargx'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optargx', otherwise `optargx' is set to zero. + + If OPTSTRING starts with `-', it requests a different method of handling the + non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. + + Long-named options begin with `+' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + getoptx() returns 0 when it finds a long-named option. */ + +static int +getoptx(int const argc, + char ** const argv, + const char * const optstring) { + + optargx = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optindx == 0) + { + first_nonopt = last_nonopt = optindx = 1; + + nextchar = 0; + + } + + if (nextchar == 0 || *nextchar == 0) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optindx) + exchange (argv); + else if (last_nonopt != optindx) + first_nonopt = optindx; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optindx < argc + && (argv[optindx][0] != '-'|| argv[optindx][1] == 0) + && (argv[optindx][0] != '+'|| argv[optindx][1] == 0)) + optindx++; + last_nonopt = optindx; + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optindx != argc && !strcmp (argv[optindx], "--")) + { + optindx++; + + if (first_nonopt != last_nonopt && last_nonopt != optindx) + exchange (argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optindx; + last_nonopt = argc; + + optindx = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optindx == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optindx = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass + it by. + */ + + if ((argv[optindx][0] != '-' || argv[optindx][1] == 0) + && (argv[optindx][0] != '+' || argv[optindx][1] == 0)) + { + optargx = argv[optindx++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = argv[optindx] + 1; + } + + if ((argv[optindx][0] == '+' || (argv[optindx][0] == '-')) + ) + { + struct optionx *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + struct optionx * pfound; + int indfound; + + while (*s && *s != '=') s++; + + indfound = 0; /* quite compiler warning */ + + /* Test all options for either exact match or abbreviated matches. */ + for (p = _getopt_long_options, option_index = 0, pfound = NULL; + p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if ((unsigned int)(s - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (!pfound) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optindx]); + nextchar += strlen (nextchar); + return '?'; + } + + if (pfound) + { + option_index = indfound; + optindx++; + if (*s) + { + if (pfound->has_arg > 0) + optargx = s + 1; + else + { + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optindx - 1][0], pfound->name); + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg) + { + if (optindx < argc) + optargx = argv[optindx++]; + else if (pfound->has_arg != 2) + { + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optindx - 1]); + nextchar += strlen (nextchar); + return '?'; + } + } + nextchar += strlen (nextchar); + if (pfound->flag) + *(pfound->flag) = pfound->val; + return 0; + } + if (argv[optindx][0] == '+' || strchr (optstring, *nextchar) == 0) + { + if (opterrx != 0) + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optindx][0], nextchar); + nextchar += strlen (nextchar); + return '?'; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = strchr (optstring, c); + + /* Increment `optindx' when we start to process its last character. */ + if (*nextchar == 0) + optindx++; + + if (temp == 0 || c == ':') + { + if (opterrx != 0) + { + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, " + "character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", + argv[0], c); + } + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != 0) + { + optargx = nextchar; + optindx++; + } + else + optargx = 0; + nextchar = 0; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != 0) + { + optargx = nextchar; + /* If we end this ARGV-element by taking the rest + as an arg, we must advance to the next element + now. + */ + optindx++; + } + else if (optindx == argc) + { + if (opterrx != 0) + fprintf (stderr, + "%s: option `-%c' requires an argument\n", + argv[0], c); + c = '?'; + } + else + /* We already incremented `optindx' once; + increment it again when taking next ARGV-elt as + argument. + */ + optargx = argv[optindx++]; + nextchar = 0; + } + } + return c; + } +} + + + +void +getopt_long_onlyx(int const argc, + char ** const argv, + const char * const options, + struct optionx * const long_options, + unsigned int * const opt_index, + int const opterrArg, + int * const end_of_options, + const char ** const optarg_arg, + const char ** const unrecognized_option) { + + int rc; + + opterrx = opterrArg; + _getopt_long_options = long_options; + rc = getoptx(argc, argv, options); + if (rc == 0) + *opt_index = option_index; + + if (rc == '?') + *unrecognized_option = argv[optindx]; + else + *unrecognized_option = NULL; + + if (rc < 0) + *end_of_options = 1; + else + *end_of_options = 0; + + *optarg_arg = optargx; +} + + +unsigned int +getopt_argstart(void) { +/*---------------------------------------------------------------------------- + This is a replacement for what traditional getopt does with global + variables. + + You call this after getopt_long_onlyx() has returned "end of + options" +-----------------------------------------------------------------------------*/ + return optindx; +} + + +/* Getopt for GNU. + Copyright (C) 1987, 1989 Free Software Foundation, Inc. + + 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/getoptx.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/getoptx.h new file mode 100644 index 0000000..c688331 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/getoptx.h @@ -0,0 +1,51 @@ +/* Interface to getopt_long_onlyx() */ + + +enum argreq {no_argument, required_argument, optional_argument}; + +struct optionx { + /* This describes an option. If the field `flag' is nonzero, it + points to a variable that is to be set to the value given in + the field `val' when the option is found, but left unchanged if + the option is not found. + */ + const char * name; + enum argreq has_arg; + int * flag; + int val; +}; + +/* long_options[] is a list terminated by an element that contains + a NULL 'name' member. +*/ +void +getopt_long_onlyx(int const argc, + char ** const argv, + const char * const options, + struct optionx * const long_options, + unsigned int * const opt_index, + int const opterrArg, + int * const end_of_options, + const char ** const optarg_arg, + const char ** const unrecognized_option); + +unsigned int +getopt_argstart(void); + +/* + Copyright (C) 1989 Free Software Foundation, Inc. + + 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/assertx.hpp b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/assertx.hpp new file mode 100644 index 0000000..64e57fa --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/assertx.hpp @@ -0,0 +1,27 @@ +#ifndef ASSERTX_HPP_INCLUDED +#define ASSERTX_HPP_INCLUDED + +#include + +/* The compiler often warns you if you give a function formal parameter a + name, but don't use it. But because assert() disappears when doing an + optimized build, the compiler doesn't recognize your reference to the + parameter in the assert() argument. To avoid the bogus warning in + this case, we have ASSERT_ONLY_ARG(), which declares a name for a + formal parameter for purposes of assert() only. In cases where an + assert() would disappear, ASSERT_ONLY_ARG() disappears too. + + E.g. + + void foo(int const ASSERT_ONLY_ARG(arg1)) { + + assert(arg1 > 0); + } +*/ +#ifdef NDEBUG + #define ASSERT_ONLY_ARG(x) +#else + #define ASSERT_ONLY_ARG(x) x +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/bool.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/bool.h new file mode 100644 index 0000000..312477c --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/bool.h @@ -0,0 +1,18 @@ +/* This takes the place of C99 stdbool.h, which at least some Windows + compilers don't have. (October 2005). + + One must not also include , because it might cause a name + collision. +*/ + +#ifndef __cplusplus +/* At least the GNU compiler defines __bool_true_false_are_defined */ +#ifndef __bool_true_false_are_defined +#define __bool_true_false_are_defined +typedef enum { + false = 0, + true = 1 +} bool; +#endif +#endif + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/c_util.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/c_util.h new file mode 100644 index 0000000..5386b13 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/c_util.h @@ -0,0 +1,19 @@ +#ifndef C_UTIL_H_INCLUDED +#define C_UTIL_H_INCLUDED + +/* C language stuff. Doesn't involve any libraries that aren't part of + the compiler. +*/ + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type + calls to be sure the arguments match the format string, thus preventing + runtime segmentation faults and incorrect messages. +*/ +#ifdef __GNUC__ +#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b))) +#else +#define GNU_PRINTF_ATTR(a,b) +#endif +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/casprintf.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/casprintf.h new file mode 100644 index 0000000..61098dc --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/casprintf.h @@ -0,0 +1,29 @@ +#ifndef CASPRINTF_H_INCLUDED +#define CASPRINTF_H_INCLUDED + +#include + +#include "c_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char * const strsol; + +void +cvasprintf(const char ** const retvalP, + const char * const fmt, + va_list varargs); + +void GNU_PRINTF_ATTR(2,3) +casprintf(const char ** const retvalP, const char * const fmt, ...); + +void +strfree(const char * const string); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/cmdline_parser.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/cmdline_parser.h new file mode 100644 index 0000000..cc87625 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/cmdline_parser.h @@ -0,0 +1,86 @@ +#ifndef CMDLINE_PARSER_H +#define CMDLINE_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} /* to fake out automatic code indenters */ +#endif + +#include "int.h" + +/* + + NOTE NOTE NOTE: cmd_getOptionValueString() and + cmd_getArgument() return malloc'ed memory (and abort the program if + out of memory). You must free it. + +*/ + +enum optiontype { + OPTTYPE_FLAG, + OPTTYPE_INT, + OPTTYPE_UINT, + OPTTYPE_STRING, + OPTTYPE_BINUINT, + OPTTYPE_FLOAT +}; + +struct cmdlineParserCtl; + +typedef struct cmdlineParserCtl * cmdlineParser; + +void +cmd_processOptions(cmdlineParser const cpP, + int const argc, + const char ** const argv, + const char ** const errorP); + +cmdlineParser +cmd_createOptionParser(void); + +void +cmd_destroyOptionParser(cmdlineParser const cpP); + +void +cmd_defineOption(cmdlineParser const cpP, + const char * const name, + enum optiontype const type); + +int +cmd_optionIsPresent(cmdlineParser const cpP, + const char * const name); + +int +cmd_getOptionValueInt(cmdlineParser const cpP, + const char * const name); + +unsigned int +cmd_getOptionValueUint(cmdlineParser const cpP, + const char * const name); + +const char * +cmd_getOptionValueString(cmdlineParser const cpP, + const char * const name); + +uint64_t +cmd_getOptionValueBinUint(cmdlineParser const cpP, + const char * const name); + +double +cmd_getOptionValueFloat(cmdlineParser const cpP, + const char * const name); + +unsigned int +cmd_argumentCount(cmdlineParser const cpP); + +const char * +cmd_getArgument(cmdlineParser const cpP, + unsigned int const argNumber); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/cmdline_parser.hpp b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/cmdline_parser.hpp new file mode 100644 index 0000000..af93487 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/cmdline_parser.hpp @@ -0,0 +1,59 @@ +#ifndef CMDLINE_PARSER_HPP_INCLUDED +#define CMDLINE_PARSER_HPP_INCLUDED + +#include + +struct cmdlineParserCtl; + +class CmdlineParser { +public: + CmdlineParser(); + + ~CmdlineParser(); + + enum optType {FLAG, INT, UINT, STRING, BINUINT, FLOAT}; + + void + defineOption(std::string const optionName, + optType const optionType); + + void + processOptions(int const argc, + const char ** const argv); + + bool + optionIsPresent(std::string const optionName) const; + + int + getOptionValueInt(std::string const optionName) const; + + unsigned int + getOptionValueUint(std::string const optionName) const; + + std::string + getOptionValueString(std::string const optionName) const; + + unsigned long long + getOptionValueBinUint(std::string const optionName) const; + + double + getOptionValueFloat(std::string const optionName) const; + + unsigned int + argumentCount() const; + + std::string + getArgument(unsigned int const argNumber) const; + +private: + struct cmdlineParserCtl * cp; + + // Make sure no one can copy this object, because if there are two + // copies, there will be two attempts to destroy *cp. + CmdlineParser(CmdlineParser const&) {}; + + CmdlineParser& + operator=(CmdlineParser const&) {return *this;} +}; + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/girmath.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/girmath.h new file mode 100644 index 0000000..0ced9c8 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/girmath.h @@ -0,0 +1,8 @@ +#ifndef __GIRMATH_H +#define __GIRMATH_H + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +#endif + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/girstring.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/girstring.h new file mode 100644 index 0000000..174910b --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/girstring.h @@ -0,0 +1,51 @@ +#ifndef GIRSTRING_H_INCLUDED +#define GIRSTRING_H_INCLUDED + +#include + +#include "xmlrpc_config.h" +#include "bool.h" + +bool +stripcaseeq(const char * const comparand, + const char * const comparator); + +static __inline__ bool +streq(const char * const comparator, + const char * const comparand) { + + return (strcmp(comparand, comparator) == 0); +} + +static __inline__ bool +memeq(const void * const comparator, + const void * const comparand, + size_t const size) { + + return (memcmp(comparator, comparand, size) == 0); +} + +#define MEMEQ(a,b,c) (memcmp(a, b, c) == 0) + +#define MEMSSET(a,b) (memset(a, b, sizeof(*a))) + +#define MEMSCPY(a,b) (memcpy(a, b, sizeof(*a))) + +#define MEMSZERO(a) (MEMSSET(a, 0)) + +static __inline__ const char * +sdup(const char * const input) { + return (const char *) strdup(input); +} + +/* Copy string pointed by B to array A with size checking. */ +#define STRSCPY(A,B) \ + (strncpy((A), (B), sizeof(A)), *((A)+sizeof(A)-1) = '\0') +#define STRSCMP(A,B) \ + (strncmp((A), (B), sizeof(A))) + +/* Concatenate string B onto string in array A with size checking */ +#define STRSCAT(A,B) \ + (strncat((A), (B), sizeof(A)-strlen(A)), *((A)+sizeof(A)-1) = '\0') + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/inline.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/inline.h new file mode 100644 index 0000000..f90032b --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/inline.h @@ -0,0 +1,19 @@ +#ifndef XMLRPC_INLINE_H_INCLUDED +#define XMLRPC_INLINE_H_INCLUDED + +/* Xmlrpc-c uses __inline__ to declare functions that should be + compiled as inline code. Some compilers, e.g. GNU, recognize the + __inline__ keyword. +*/ +#ifndef __GNUC__ +#ifndef __inline__ +#ifdef __sgi +#define __inline__ __inline +#else +#define __inline__ +#endif +#endif +#endif + + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/int.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/int.h new file mode 100644 index 0000000..0d654e2 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/int.h @@ -0,0 +1,58 @@ +/* This takes the place of C99 inttypes.h, which at least some Windows + compilers don't have. (October 2007). +*/ + +/* PRId64 is the printf-style format specifier for a long long type, as in + long long mynumber = 5; + printf("My number is %" PRId64 ".\n", mynumber); + + The LL/ULL macro is for 64 bit integer literals, like this: + + long long mask= ULL(1) << 33; +*/ + +/* 'uint' is quite convenient, but there's no simple way have it everywhere. + Some systems have it in the base system (e.g. GNU C library has it in + , and others (e.g. Solaris - 08.12.02) don't. Since we + can't define it unless we know it's not defined already, and we don't + want to burden the reader with a special Xmlrpc-c name such as xuint, + we just use standard "unsigned int" instead. +*/ + +#ifdef _MSC_VER +# define PRId64 "I64d" +# define PRIu64 "I64u" + +#ifndef int16_t +typedef short int16_t; +#endif +#ifndef uint16_t +typedef unsigned short uint16_t; +#endif +#ifndef int32_t +typedef int int32_t; +#endif +#ifndef uint32_t +typedef unsigned int uint32_t; +#endif +#ifndef int64_t +typedef __int64 int64_t; +#endif +#ifndef uint64_t +typedef unsigned __int64 uint64_t; +#endif +#ifndef uint8_t +typedef unsigned char uint8_t; +#endif + +/* Older Microsoft compilers don't know the standard ll/ull suffixes */ +#define LL(x) x ## i64 +#define ULL(x) x ## u64 + +#else + /* Not Microsoft compiler */ + #include + #define LL(x) x ## ll + #define ULL(x) x ## ull +#endif + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/linklist.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/linklist.h new file mode 100644 index 0000000..f6f2641 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/linklist.h @@ -0,0 +1,193 @@ +#ifndef LINKLIST_H_INCLUDED +#define LINKLIST_H_INCLUDED + +#include "inline.h" + +struct list_head { +/*---------------------------------------------------------------------------- + This is a header for an element of a doubly linked list, or an anchor + for such a list. + + itemP == NULL means it's an anchor; otherwise it's a header. + + Initialize a list header with list_init_header(). You don't have to + do anything to terminate a list header. + + Initialize an anchor with list_make_emtpy(). You don't have to do anything + to terminate a list header. +-----------------------------------------------------------------------------*/ + struct list_head * nextP; + /* For a header, this is the address of the list header for + the next element in the list. If there is no next element, + it points to the anchor. If the header is not in a list at + all, it is NULL. + + For an anchor, it is the address of the list header of the + first element. If the list is empty, it points to the + anchor itself. + */ + struct list_head * prevP; + /* For a header, this is the address of the list header for + the previous element in the list. If there is no previous element, + it points to the anchor. If the header is not in a list at + all, it is NULL. + + For an anchor, it is the address of the list header of the + last element. If the list is empty, it points to the + anchor itself. + */ + void * itemP; + /* For a header, this is the address of the list element to which it + belongs. For an anchor, this is NULL. + */ +}; + +static __inline__ void +list_init_header(struct list_head * const headerP, + void * const itemP) { + + headerP->prevP = NULL; + headerP->nextP = NULL; + headerP->itemP = itemP; +} + + + +static __inline__ int +list_is_linked(struct list_head * headerP) { + return headerP->prevP != NULL; +} + + + +static __inline__ int +list_is_empty(struct list_head * const anchorP) { + return anchorP->nextP == anchorP; +} + + + +static __inline__ unsigned int +list_count(struct list_head * const anchorP) { + unsigned int count; + + struct list_head * p; + + for (p = anchorP->nextP, count = 0; + p != anchorP; + p = p->nextP, ++count); + + return count; +} + + + +static __inline__ void +list_make_empty(struct list_head * const anchorP) { + anchorP->prevP = anchorP; + anchorP->nextP = anchorP; + anchorP->itemP = NULL; +} + +static __inline__ void +list_insert_after(struct list_head * const beforeHeaderP, + struct list_head * const newHeaderP) { + newHeaderP->prevP = beforeHeaderP; + newHeaderP->nextP = beforeHeaderP->nextP; + + beforeHeaderP->nextP = newHeaderP; + newHeaderP->nextP->prevP = newHeaderP; +} + + + +static __inline__ void +list_add_tail(struct list_head * const anchorP, + struct list_head * const headerP) { + list_insert_after(anchorP->prevP, headerP); +} + + + +static __inline__ void +list_add_head(struct list_head * const anchorP, + struct list_head * const headerP) { + list_insert_after(anchorP, headerP); +} + + + +static __inline__ void +list_remove(struct list_head * const headerP) { + headerP->prevP->nextP = headerP->nextP; + headerP->nextP->prevP = headerP->prevP; + headerP->prevP = NULL; + headerP->nextP = NULL; +} + + + +static __inline__ struct list_head * +list_remove_head(struct list_head * const anchorP) { + struct list_head * retval; + + if (list_is_empty(anchorP)) + retval = NULL; + else { + retval = anchorP->nextP; + list_remove(retval); + } + return retval; +} + + + +static __inline__ struct list_head * +list_remove_tail(struct list_head * const anchorP) { + struct list_head * retval; + + if (list_is_empty(anchorP)) + retval = NULL; + else { + retval = anchorP->prevP; + list_remove(retval); + } + return retval; +} + + + +static __inline__ void * +list_foreach(struct list_head * const anchorP, + void * functionP(struct list_head *, void *), + void * const context) { + + struct list_head * p; + struct list_head * nextP; + void * result; + + for (p = anchorP->nextP, nextP = p->nextP, result=NULL; + p != anchorP && result == NULL; + p = nextP, nextP = p->nextP) + result = (*functionP)(p, context); + + return result; +} + + + +static __inline__ void +list_append(struct list_head * const newAnchorP, + struct list_head * const baseAnchorP) { + + if (!list_is_empty(newAnchorP)) { + baseAnchorP->prevP->nextP = newAnchorP->nextP; + newAnchorP->nextP->prevP = baseAnchorP->prevP; + newAnchorP->prevP->nextP = baseAnchorP; + baseAnchorP->prevP = newAnchorP->prevP; + } +} + +#endif + + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/mallocvar.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/mallocvar.h new file mode 100644 index 0000000..9048ec4 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/mallocvar.h @@ -0,0 +1,111 @@ +/* These are some dynamic memory allocation facilities. They are essentially + an extension to C, as they do allocations with a cognizance of C + variables. You can use them to make C read more like a high level + language. + + Before including this, you must define an __inline__ macro if your + compiler doesn't recognize it as a keyword. +*/ + +#ifndef MALLOCVAR_INCLUDED +#define MALLOCVAR_INCLUDED + +#include "xmlrpc_config.h" + +#include +#include + +static __inline__ void +mallocProduct(void ** const resultP, + unsigned int const factor1, + unsigned int const factor2) { +/*---------------------------------------------------------------------------- + malloc a space whose size in bytes is the product of 'factor1' and + 'factor2'. But if that size cannot be represented as an unsigned int, + return NULL without allocating anything. Also return NULL if the malloc + fails. + + If either factor is zero, malloc a single byte. + + Note that malloc() actually takes a size_t size argument, so the + proper test would be whether the size can be represented by size_t, + not unsigned int. But there is no reliable indication available to + us, like UINT_MAX, of what the limitations of size_t are. We + assume size_t is at least as expressive as unsigned int and that + nobody really needs to allocate more than 4GB of memory. +-----------------------------------------------------------------------------*/ + if (factor1 == 0 || factor2 == 0) + *resultP = malloc(1); + else { + if (UINT_MAX / factor2 < factor1) + *resultP = NULL; + else + *resultP = malloc(factor1 * factor2); + } +} + + + +static __inline__ void +reallocProduct(void ** const blockP, + unsigned int const factor1, + unsigned int const factor2) { + + void * const oldBlockP = *blockP; + + void * newBlockP; + + if (UINT_MAX / factor2 < factor1) + newBlockP = NULL; + else + newBlockP = realloc(oldBlockP, factor1 * factor2); + + if (newBlockP) + *blockP = newBlockP; + else { + free(oldBlockP); + *blockP = NULL; + } +} + + +/* IMPLEMENTATION NOTE: There are huge strict aliasing pitfalls here + if you cast pointers, e.g. (void **) +*/ + +#define MALLOCARRAY(arrayName, nElements) do { \ + void * array; \ + mallocProduct(&array, nElements, sizeof(arrayName[0])); \ + arrayName = array; \ +} while (0) + +#define REALLOCARRAY(arrayName, nElements) do { \ + void * array = arrayName; \ + reallocProduct(&array, nElements, sizeof(arrayName[0])); \ + arrayName = array; \ +} while (0) + + +#define MALLOCARRAY_NOFAIL(arrayName, nElements) \ +do { \ + MALLOCARRAY(arrayName, nElements); \ + if ((arrayName) == NULL) \ + abort(); \ +} while(0) + +#define REALLOCARRAY_NOFAIL(arrayName, nElements) \ +do { \ + REALLOCARRAY(arrayName, nElements); \ + if ((arrayName) == NULL) \ + abort(); \ +} while(0) + + +#define MALLOCVAR(varName) \ + varName = malloc(sizeof(*varName)) + +#define MALLOCVAR_NOFAIL(varName) \ + do {if ((varName = malloc(sizeof(*varName))) == NULL) abort();} while(0) + +#endif + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/pthreadx.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/pthreadx.h new file mode 100644 index 0000000..3ec8f2a --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/pthreadx.h @@ -0,0 +1,80 @@ +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#ifndef PTHREADX_H_INCLUDED +#define PTHREADX_H_INCLUDED + +#ifndef WIN32 +# define _REENTRANT +# include +#elif defined (WIN32) +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef HANDLE pthread_t; +typedef CRITICAL_SECTION pthread_mutex_t; + +#define PTHREAD_MUTEX_INITIALIZER NULL + /* usage: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; */ + +typedef +struct { + int attrs; /* currently unused. placeholder. */ +} pthread_attr_t; + +typedef +struct { + int attrs; /* currently unused. placeholder. */ +} pthread_mutexattr_t; + +/* We make pthread_func identical to a Windows thread start function + so we can use Windows thread functions to implement these pthread + functions directly. +*/ +typedef unsigned (WINAPI pthread_func)(void *); + +extern int pthread_create(pthread_t * const new_thread_ID, + const pthread_attr_t * const attr, + pthread_func * start_func, + void * const arg); +extern int pthread_cancel(pthread_t target_thread); +extern int pthread_join(pthread_t target_thread, void **status); +extern int pthread_detach(pthread_t target_thread); + +extern int pthread_mutex_init(pthread_mutex_t * const mp, + const pthread_mutexattr_t * const attr); +extern int pthread_mutex_lock(pthread_mutex_t * const mp); +extern int pthread_mutex_unlock(pthread_mutex_t * const mp); +extern int pthread_mutex_destroy(pthread_mutex_t * const mp); + +#ifdef __cplusplus +} +#endif +#endif /* WIN32 */ + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/stdargx.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/stdargx.h new file mode 100644 index 0000000..ee54464 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/stdargx.h @@ -0,0 +1,67 @@ +#ifndef STDARGX_H_INCLUDED +#define STDARGX_H_INCLUDED + +#include "xmlrpc_config.h" +#include +#include + +/*---------------------------------------------------------------------------- + We need a special version of va_list in order to pass around the + variable argument heap by reference, thus allowing a subroutine to + advance the heap's pointer. + + On some systems (e.g. Gcc for PPC or AMD64), va_list is an array. + That invites the scourge of array-to-pointer degeneration if you try + to take its address. Burying it inside a struct as we do with out + va_listx type makes it immune. + + Example of what would happen if we used va_list instead of va_listx, + on a system where va_list is an array: + + void sub2(va_list * argsP) [ + ... + } + + void sub1(va_list args) { + sub2(&args); + } + + This doesn't work. '&args' is the same thing as 'args', so is + va_list, not va_list *. The compiler will even warn you about the + pointer type mismatch. + + To use va_listx: + + void sub1_va(char * format, va_list args) { + va_listx argsx; + init_va_listx(&argsx, args); + sub2(format, &argsx); + } + +-----------------------------------------------------------------------------*/ + + +typedef struct { +/*---------------------------------------------------------------------------- + Same thing as va_list, but in a form that works everywhere. See above. +-----------------------------------------------------------------------------*/ + va_list v; +} va_listx; + + + +static __inline__ void +init_va_listx(va_listx * const argsxP, + va_list const args) { +#if VA_LIST_IS_ARRAY + /* 'args' is NOT a va_list. It is a pointer to the first element of a + 'va_list', which is the same address as a pointer to the va_list + itself. + */ + memcpy(&argsxP->v, args, sizeof(argsxP->v)); +#else + argsxP->v = args; +#endif +} + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/string_parser.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/string_parser.h new file mode 100644 index 0000000..290d749 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/string_parser.h @@ -0,0 +1,31 @@ +#ifndef STRING_PARSER_H_INCLUDED +#define STRING_PARSER_H_INCLUDED + +#include "int.h" + +void +interpretUll(const char * const string, + uint64_t * const ullP, + const char ** const errorP); + +void +interpretLl(const char * const string, + int64_t * const llP, + const char ** const errorP); + +void +interpretUint(const char * const string, + unsigned int * const uintP, + const char ** const errorP); + +void +interpretInt(const char * const string, + int * const uintP, + const char ** const errorP); + +void +interpretBinUint(const char * const string, + uint64_t * const valueP, + const char ** const errorP); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/unistdx.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/unistdx.h new file mode 100644 index 0000000..69f1f6b --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/include/unistdx.h @@ -0,0 +1,14 @@ +#ifndef UNISTDX_H_INCLUDED +#define UNISTDX_H_INCLUDED + +/* Xmlrpc-c code #includes "unistdx.h" instead of because + does not exist on WIN32. +*/ + +#ifndef WIN32 +# include +#else + +#endif /* WIN32 */ + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/pthreadx_win32.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/pthreadx_win32.c new file mode 100644 index 0000000..6a8446a --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/pthreadx_win32.c @@ -0,0 +1,123 @@ +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#include "xmlrpc_config.h" + +#ifdef WIN32 + +#include "pthreadx.h" + +#include + +#undef PACKAGE +#undef VERSION + +int +pthread_create(pthread_t * const new_thread_ID, + const pthread_attr_t * const attr, + pthread_func * func, + void * const arg) { + + HANDLE hThread; + DWORD dwThreadID; + + hThread = (HANDLE) _beginthreadex ( + NULL, 0, func, (LPVOID)arg, CREATE_SUSPENDED, &dwThreadID); + + SetThreadPriority (hThread, THREAD_PRIORITY_NORMAL); + ResumeThread (hThread); + + *new_thread_ID = hThread; + + return hThread ? 0 : -1; +} + + + +/* Just kill it. */ +int +pthread_cancel(pthread_t const target_thread) { + + CloseHandle(target_thread); + return 0; +} + + + +/* Waits for the thread to exit before continuing. */ +int +pthread_join(pthread_t const target_thread, + void ** const statusP) { + + DWORD dwResult = WaitForSingleObject(target_thread, INFINITE); + *statusP = (void *)dwResult; + return 0; +} + + + +int +pthread_detach(pthread_t const target_thread) { + return 0; +} + + + +int +pthread_mutex_init(pthread_mutex_t * const mp, + const pthread_mutexattr_t * const attr) { + + InitializeCriticalSection(mp); + return 0; +} + + + +int +pthread_mutex_lock(pthread_mutex_t * const mp) { + + EnterCriticalSection(mp); + return 0; +} + + + +int +pthread_mutex_unlock(pthread_mutex_t * const mp) { + + LeaveCriticalSection(mp); + return 0; +} + + + +int +pthread_mutex_destroy(pthread_mutex_t * const mp) { + + DeleteCriticalSection(mp); + return 0; +} + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/string_parser.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/string_parser.c new file mode 100644 index 0000000..7ce6a79 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/string_parser.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "int.h" +#include "girstring.h" +#include "casprintf.h" + +#include "string_parser.h" + +static const char * +strippedSubstring(const char * const string) { + + const char * p; + + for (p = &string[0]; isspace(*p); ++p); + + return p; +} + + + +void +interpretUll(const char * const string, + uint64_t * const ullP, + const char ** const errorP) { + + /* strtoull() has the same disappointing weaknesses of strtoul(). + See interpretUint(). + */ + + const char * const strippedString = strippedSubstring(string); + + if (strippedString[0] == '\0') + casprintf(errorP, "Null (or all whitespace) string."); + else if (!isdigit(strippedString[0])) + casprintf(errorP, "First non-blank character is '%c', not a digit.", + strippedString[0]); + else { + /* strtoull() does a bizarre thing where if the number is out + of range, it returns a clamped value but tells you about it + by setting errno = ERANGE. If it is not out of range, + strtoull() leaves errno alone. + */ + char * tail; + + errno = 0; /* So we can tell if strtoull() overflowed */ + + *ullP = strtoull(strippedString, &tail, 10); + + if (tail[0] != '\0') + casprintf(errorP, "Non-digit stuff in string: %s", tail); + else if (errno == ERANGE) + casprintf(errorP, "Number too large"); + else + *errorP = NULL; + } +} + + + +void +interpretLl(const char * const string, + int64_t * const llP, + const char ** const errorP) { + + if (string[0] == '\0') + casprintf(errorP, "Null string."); + else { + /* strtoll() does a bizarre thing where if the number is out + of range, it returns a clamped value but tells you about it + by setting errno = ERANGE. If it is not out of range, + strtoll() leaves errno alone. + */ + char * tail; + + errno = 0; /* So we can tell if strtoll() overflowed */ + + *llP = strtoll(string, &tail, 10); + + if (tail[0] != '\0') + casprintf(errorP, "Non-digit stuff in string: %s", tail); + else if (errno == ERANGE) + casprintf(errorP, "Number too large"); + else + *errorP = NULL; + } +} + + + +void +interpretUint(const char * const string, + unsigned int * const uintP, + const char ** const errorP) { + + /* strtoul() does a lousy job of dealing with invalid numbers. A null + string is just zero; a negative number is a large positive one; a + positive (cf unsigned) number is accepted. strtoul is inconsistent + in its treatment of the tail; if there is no valid number at all, + it returns the entire string as the tail, including leading white + space and sign, which are not themselves invalid. + */ + + const char * const strippedString = strippedSubstring(string); + + if (strippedString[0] == '\0') + casprintf(errorP, "Null (or all whitespace) string."); + else if (!isdigit(strippedString[0])) + casprintf(errorP, "First non-blank character is '%c', not a digit.", + strippedString[0]); + else { + /* strtoul() does a bizarre thing where if the number is out + of range, it returns a clamped value but tells you about it + by setting errno = ERANGE. If it is not out of range, + strtoul() leaves errno alone. + */ + char * tail; + unsigned long ulongValue; + + errno = 0; /* So we can tell if strtoul() overflowed */ + + ulongValue = strtoul(strippedString, &tail, 10); + + if (tail[0] != '\0') + casprintf(errorP, "Non-digit stuff in string: %s", tail); + else if (errno == ERANGE) + casprintf(errorP, "Number too large"); + else if (ulongValue > UINT_MAX) + casprintf(errorP, "Number too large"); + else { + *uintP = ulongValue; + *errorP = NULL; + } + } +} + + + +void +interpretInt(const char * const string, + int * const intP, + const char ** const errorP) { + + if (string[0] == '\0') + casprintf(errorP, "Null string."); + else { + /* strtol() does a bizarre thing where if the number is out + of range, it returns a clamped value but tells you about it + by setting errno = ERANGE. If it is not out of range, + strtol() leaves errno alone. + */ + char * tail; + long longValue; + + errno = 0; /* So we can tell if strtol() overflowed */ + + longValue = strtol(string, &tail, 10); + + if (tail[0] != '\0') + casprintf(errorP, "Non-digit stuff in string: %s", tail); + else if (errno == ERANGE) + casprintf(errorP, "Number too large"); + else if (longValue > INT_MAX) + casprintf(errorP, "Number too large"); + else if (longValue < INT_MIN) + casprintf(errorP, "Number too negative"); + else { + *intP = longValue; + *errorP = NULL; + } + } +} + + + +void +interpretBinUint(const char * const string, + uint64_t * const valueP, + const char ** const errorP) { + + char * tailptr; + long const mantissa_long = strtol(string, &tailptr, 10); + + if (errno == ERANGE) + casprintf(errorP, + "Numeric value out of range for computation: '%s'. " + "Try a smaller number with a K, M, G, etc. suffix.", + string); + else { + int64_t const mantissa = mantissa_long; + + int64_t argNumber; + + *errorP = NULL; /* initial assumption */ + + if (*tailptr == '\0') + /* There's no suffix. A pure number */ + argNumber = mantissa * 1; + else if (stripcaseeq(tailptr, "K")) + argNumber = mantissa * 1024; + else if (stripcaseeq(tailptr, "M")) + argNumber = mantissa * 1024 * 1024; + else if (stripcaseeq(tailptr, "G")) + argNumber = mantissa * 1024 * 1024 * 1024; + else if (stripcaseeq(tailptr, "T")) + argNumber = mantissa * 1024 * 1024 * 1024 * 1024; + else if (stripcaseeq(tailptr, "P")) + argNumber = mantissa * 1024 * 1024 * 1024 * 1024 * 1024; + else { + argNumber = 0; /* quiet compiler warning */ + casprintf(errorP, "Garbage suffix '%s' on number", tailptr); + } + if (!*errorP) { + if (argNumber < 0) + casprintf(errorP, "Unsigned numeric value is " + "negative: %" PRId64, argNumber); + else + *valueP = (uint64_t) argNumber; + } + } +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/stripcaseeq.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/stripcaseeq.c new file mode 100644 index 0000000..324a1d8 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/deps/util/stripcaseeq.c @@ -0,0 +1,69 @@ +#define _GNU_SOURCE +#include + +#include "bool.h" +#include "girstring.h" + + + +bool +stripcaseeq(const char * const comparand, + const char * const comparator) { +/*---------------------------------------------------------------------------- + Compare two strings, ignoring leading and trailing blanks and case. + + Return true if the strings are identical, false otherwise. +-----------------------------------------------------------------------------*/ + const char *p, *q, *px, *qx; + bool equal; + + /* Make p and q point to the first non-blank character in each string. + If there are no non-blank characters, make them point to the terminating + NULL. + */ + + p = &comparand[0]; + while (*p == ' ') + ++p; + q = &comparator[0]; + while (*q == ' ') + ++q; + + /* Make px and qx point to the last non-blank character in each string. + If there are no nonblank characters (which implies the string is + null), make them point to the terminating NULL. + */ + + if (*p == '\0') + px = p; + else { + px = p + strlen(p) - 1; + while (*px == ' ') + --px; + } + + if (*q == '\0') + qx = q; + else { + qx = q + strlen(q) - 1; + while (*qx == ' ') + --qx; + } + + equal = true; /* initial assumption */ + + /* If the stripped strings aren't the same length, + we know they aren't equal + */ + if (px - p != qx - q) + equal = false; + + + while (p <= px) { + if (toupper(*p) != toupper(*q)) + equal = false; + ++p; ++q; + } + return equal; +} + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/base.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/base.h new file mode 100644 index 0000000..4778f80 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/base.h @@ -0,0 +1,757 @@ +/* Copyright and license information is at the end of the file */ + +#ifndef XMLRPC_H_INCLUDED +#define XMLRPC_H_INCLUDED + +#include +#include +#include +#include +#include + /* Defines XMLRPC_HAVE_WCHAR, XMLRPC_INT64, XMLRPC_HAVE_TIMEVAL */ + +#if XMLRPC_HAVE_WCHAR +#include +#endif + +#if XMLRPC_HAVE_TIMEVAL +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/*========================================================================= +** Version of libxmlrpc +**=======================================================================*/ +extern unsigned int const xmlrpc_version_major; +extern unsigned int const xmlrpc_version_minor; +extern unsigned int const xmlrpc_version_point; + +/*========================================================================= +** C types equivalent to XML-RPC types +**=======================================================================*/ + +/* We define names for these types, because they may change from platform + to platform. +*/ + +typedef signed int xmlrpc_int; + /* An integer of the type defined by XML-RPC ; i.e. 32 bit */ +typedef XMLRPC_INT32 xmlrpc_int32; + /* An integer of the type defined by XML-RPC ; i.e. 32 bit */ +typedef XMLRPC_INT64 xmlrpc_int64; + /* An integer of the type defined by "XML-RPC" ; i.e. 64 bit */ +typedef int xmlrpc_bool; + /* A boolean (of the type defined by XML-RPC , but there's + really only one kind) + */ +typedef double xmlrpc_double; + /* A double precision floating point number as defined by + XML-RPC . But the C "double" type is universally the same, + so it's probably clearer just to use that. This typedef is here + for mathematical completeness. + */ + +/* xmlrpc_socket is just for backward compatibility, in case someone decided + to use this in user code. New code should use the native type for a + socket (e.g. int or SOCKET). (We stopped using this because for winsock + users, we would have to #include in every file that + #includes and we don't want that). +*/ +typedef int xmlrpc_socket; + +#define XMLRPC_INT32_MAX 0x7fffffff +#define XMLRPC_INT32_MIN (-XMLRPC_INT32_MAX - 1) + +#define XMLRPC_INT64_MAX 0x7fffffffffffffffll +#define XMLRPC_INT64_MIN (-XMLRPC_INT64_MAX - 1) + + +/*========================================================================= +** xmlrpc_value +**========================================================================= +** An XML-RPC value (of any type). +*/ + +typedef enum { + XMLRPC_TYPE_INT = 0, + XMLRPC_TYPE_BOOL = 1, + XMLRPC_TYPE_DOUBLE = 2, + XMLRPC_TYPE_DATETIME = 3, + XMLRPC_TYPE_STRING = 4, + XMLRPC_TYPE_BASE64 = 5, + XMLRPC_TYPE_ARRAY = 6, + XMLRPC_TYPE_STRUCT = 7, + XMLRPC_TYPE_C_PTR = 8, + XMLRPC_TYPE_NIL = 9, + XMLRPC_TYPE_I8 = 10, + XMLRPC_TYPE_DEAD = 0xDEAD +} xmlrpc_type; + +#define XMLRPC_HAVE_I8 1 + +/* These are *always* allocated on the heap. No exceptions. */ +typedef struct _xmlrpc_value xmlrpc_value; + +const char * +xmlrpc_type_name(xmlrpc_type const type); + +void +xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP); + +#define XMLRPC_ASSERT_ARRAY_OK(val) \ + xmlrpc_abort_if_array_bad(val) + +/* Increment the reference count of an xmlrpc_value. */ +extern void xmlrpc_INCREF (xmlrpc_value* const value); + +/* Decrement the reference count of an xmlrpc_value. If there +** are no more references, free it. */ +extern void xmlrpc_DECREF (xmlrpc_value* const value); + +/* Get the type of an XML-RPC value. */ +extern xmlrpc_type xmlrpc_value_type (xmlrpc_value* const value); + +xmlrpc_value * +xmlrpc_int_new(xmlrpc_env * const envP, + int const intValue); + +xmlrpc_value * +xmlrpc_i8_new(xmlrpc_env * const envP, + xmlrpc_int64 const value); + +void +xmlrpc_read_int(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + int * const intValueP); + +xmlrpc_value * +xmlrpc_bool_new(xmlrpc_env * const envP, + xmlrpc_bool const boolValue); + +void +xmlrpc_read_bool(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_bool * const boolValueP); + +xmlrpc_value * +xmlrpc_double_new(xmlrpc_env * const envP, + double const doubleValue); + +void +xmlrpc_read_double(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_double * const doubleValueP); + +xmlrpc_value * +xmlrpc_datetime_new_str(xmlrpc_env * const envP, + const char * const value); + +xmlrpc_value * +xmlrpc_datetime_new_sec(xmlrpc_env * const envP, + time_t const value); + +xmlrpc_value* +xmlrpc_datetime_new_usec(xmlrpc_env * const envP, + time_t const secs, + unsigned int const usecs); + +#if XMLRPC_HAVE_TIMEVAL +xmlrpc_value * +xmlrpc_datetime_new_timeval(xmlrpc_env * const envP, + struct timeval const value); +#endif + +#if XMLRPC_HAVE_TIMESPEC +xmlrpc_value * +xmlrpc_datetime_new_timespec(xmlrpc_env * const envP, + struct timespec const value); +#endif + +void +xmlrpc_read_datetime_str(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP); + +void +xmlrpc_read_datetime_sec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + time_t * const timeValueP); + +void +xmlrpc_read_datetime_usec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + time_t * const secsP, + unsigned int * const usecsP); + +#if XMLRPC_HAVE_TIMEVAL +void +xmlrpc_read_datetime_timeval(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + struct timeval * const timeValueP); +#endif + +#if XMLRPC_HAVE_TIMESPEC +void +xmlrpc_read_datetime_timespec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + struct timespec * const timeValueP); +#endif + +xmlrpc_value * +xmlrpc_string_new(xmlrpc_env * const envP, + const char * const stringValue); + +xmlrpc_value * +xmlrpc_string_new_lp(xmlrpc_env * const envP, + size_t const length, + const char * const stringValue); + +xmlrpc_value * +xmlrpc_string_new_va(xmlrpc_env * const envP, + const char * const format, + va_list args); + +xmlrpc_value * +xmlrpc_string_new_f(xmlrpc_env * const envP, + const char * const format, + ...); + +xmlrpc_value * +xmlrpc_string_new_lp_cr(xmlrpc_env * const envP, + size_t const length, + const char * const value); + +xmlrpc_value * +xmlrpc_string_new_cr(xmlrpc_env * const envP, + const char * const value); + +void +xmlrpc_read_string(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP); + + +void +xmlrpc_read_string_crlf(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP); + +void +xmlrpc_read_string_lp_crlf(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const char ** const stringValueP); + +void +xmlrpc_read_string_lp(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const char ** const stringValueP); + +#if XMLRPC_HAVE_WCHAR +xmlrpc_value * +xmlrpc_string_w_new(xmlrpc_env * const envP, + const wchar_t * const stringValue); + +xmlrpc_value * +xmlrpc_string_w_new_lp(xmlrpc_env * const envP, + size_t const length, + const wchar_t * const stringValue); + +void +xmlrpc_read_string_w(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const wchar_t ** const stringValueP); + +void +xmlrpc_read_string_w_crlf(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const wchar_t ** const stringValueP); + +void +xmlrpc_read_string_w_lp(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + size_t * const lengthP, + const wchar_t ** const stringValueP); + +void +xmlrpc_read_string_w_lp_crlf(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + size_t * const lengthP, + const wchar_t ** const stringValueP); + +xmlrpc_value * +xmlrpc_string_w_new_lp_cr(xmlrpc_env * const envP, + size_t const length, + const wchar_t * const value); + +xmlrpc_value * +xmlrpc_string_w_new_cr(xmlrpc_env * const envP, + const wchar_t * const value); + +#endif /* XMLRPC_HAVE_WCHAR */ + +xmlrpc_value * +xmlrpc_base64_new(xmlrpc_env * const envP, + size_t const length, + const unsigned char * const value); + +void +xmlrpc_read_base64(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const unsigned char ** const bytestringValueP); + +void +xmlrpc_read_base64_size(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP); + +xmlrpc_value * +xmlrpc_array_new(xmlrpc_env * const envP); + +/* Return the number of elements in an XML-RPC array. +** Sets XMLRPC_TYPE_ERROR if 'array' is not an array. */ +int +xmlrpc_array_size(xmlrpc_env * const env, + const xmlrpc_value * const array); + +/* Append an item to an XML-RPC array. +** Sets XMLRPC_TYPE_ERROR if 'array' is not an array. */ +extern void +xmlrpc_array_append_item (xmlrpc_env * const envP, + xmlrpc_value * const arrayP, + xmlrpc_value * const valueP); + +void +xmlrpc_array_read_item(xmlrpc_env * const envP, + const xmlrpc_value * const arrayP, + unsigned int const index, + xmlrpc_value ** const valuePP); + +/* Deprecated. Use xmlrpc_array_read_item() instead. + + Get an item from an XML-RPC array. + Does not increment the reference count of the returned value. + Sets XMLRPC_TYPE_ERROR if 'array' is not an array. + Sets XMLRPC_INDEX_ERROR if 'index' is out of bounds. +*/ +xmlrpc_value * +xmlrpc_array_get_item(xmlrpc_env * const envP, + const xmlrpc_value * const arrayP, + int const index); + +/* Not implemented--we don't need it yet. +extern +int xmlrpc_array_set_item (xmlrpc_env* env, +xmlrpc_value* array, +int index, + xmlrpc_value* value); +*/ + +xmlrpc_value * +xmlrpc_struct_new(xmlrpc_env * const env); + +/* Return the number of key/value pairs in a struct. +** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */ +int +xmlrpc_struct_size (xmlrpc_env * env, + xmlrpc_value * strct); + +/* Returns true iff 'strct' contains 'key'. +** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */ +int +xmlrpc_struct_has_key(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key); + +/* The same as the above, but the key may contain zero bytes. + Deprecated. xmlrpc_struct_get_value_v() is more general, and this + case is not common enough to warrant a shortcut. +*/ +int +xmlrpc_struct_has_key_n(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key, + size_t const key_len); + +#if 0 +/* Not implemented yet, but needed for completeness. */ +int +xmlrpc_struct_has_key_v(xmlrpc_env * env, + xmlrpc_value * strct, + xmlrpc_value * const keyval); +#endif + + +void +xmlrpc_struct_find_value(xmlrpc_env * const envP, + xmlrpc_value * const structP, + const char * const key, + xmlrpc_value ** const valuePP); + + +void +xmlrpc_struct_find_value_v(xmlrpc_env * const envP, + xmlrpc_value * const structP, + xmlrpc_value * const keyP, + xmlrpc_value ** const valuePP); + +void +xmlrpc_struct_read_value(xmlrpc_env * const envP, + xmlrpc_value * const structP, + const char * const key, + xmlrpc_value ** const valuePP); + +void +xmlrpc_struct_read_value_v(xmlrpc_env * const envP, + xmlrpc_value * const structP, + xmlrpc_value * const keyP, + xmlrpc_value ** const valuePP); + +/* The "get_value" functions are deprecated. Use the "find_value" + and "read_value" functions instead. +*/ +xmlrpc_value * +xmlrpc_struct_get_value(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key); + +/* The same as above, but the key may contain zero bytes. + Deprecated. xmlrpc_struct_get_value_v() is more general, and this + case is not common enough to warrant a shortcut. +*/ +xmlrpc_value * +xmlrpc_struct_get_value_n(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key, + size_t const key_len); + +/* Set the value associated with 'key' in 'strct' to 'value'. + Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. +*/ +void +xmlrpc_struct_set_value(xmlrpc_env * const env, + xmlrpc_value * const strct, + const char * const key, + xmlrpc_value * const value); + +/* The same as above, but the key may contain zero bytes. Deprecated. + The general way to set a structure value is xmlrpc_struct_set_value_v(), + and this case is not common enough to deserve a shortcut. +*/ +void +xmlrpc_struct_set_value_n(xmlrpc_env * const env, + xmlrpc_value * const strct, + const char * const key, + size_t const key_len, + xmlrpc_value * const value); + +/* The same as above, but the key must be an XML-RPC string. +** Fails with XMLRPC_TYPE_ERROR if 'keyval' is not a string. */ +void +xmlrpc_struct_set_value_v(xmlrpc_env * const env, + xmlrpc_value * const strct, + xmlrpc_value * const keyval, + xmlrpc_value * const value); + +/* Given a zero-based index, return the matching key and value. This +** is normally used in conjunction with xmlrpc_struct_size. +** Fails with XMLRPC_TYPE_ERROR if 'struct' is not a struct. +** Fails with XMLRPC_INDEX_ERROR if 'index' is out of bounds. */ + +void +xmlrpc_struct_read_member(xmlrpc_env * const envP, + xmlrpc_value * const structP, + unsigned int const index, + xmlrpc_value ** const keyvalP, + xmlrpc_value ** const valueP); + +/* The same as above, but does not increment the reference count of the + two values it returns, and return NULL for both if it fails, and + takes a signed integer for the index (but fails if it is negative). + + Deprecated. Use xmlrpc_struct_read_member() instead. +*/ +void +xmlrpc_struct_get_key_and_value(xmlrpc_env * const env, + xmlrpc_value * const strct, + int const index, + xmlrpc_value ** const out_keyval, + xmlrpc_value ** const out_value); + +void +xmlrpc_read_cptr(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + void ** const ptrValueP); + +void +xmlrpc_read_nil(xmlrpc_env * const envP, + xmlrpc_value * const valueP); + + +void +xmlrpc_read_i8(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_int64 * const intValueP); + + +xmlrpc_value * +xmlrpc_cptr_new(xmlrpc_env * const envP, + void * const value); + +xmlrpc_value * +xmlrpc_nil_new(xmlrpc_env * const envP); + + +/* Build an xmlrpc_value from a format string. */ + +xmlrpc_value * +xmlrpc_build_value(xmlrpc_env * const env, + const char * const format, + ...); + +/* The same as the above, but using a va_list and more general */ +void +xmlrpc_build_value_va(xmlrpc_env * const env, + const char * const format, + va_list const args, + xmlrpc_value ** const valPP, + const char ** const tailP); + +void +xmlrpc_decompose_value(xmlrpc_env * const envP, + xmlrpc_value * const value, + const char * const format, + ...); + +void +xmlrpc_decompose_value_va(xmlrpc_env * const envP, + xmlrpc_value * const value, + const char * const format, + va_list const args); + +/* xmlrpc_parse_value... is the same as xmlrpc_decompose_value... except + that it doesn't do proper memory management -- it returns xmlrpc_value's + without incrementing the reference count and returns pointers to data + inside an xmlrpc_value structure. + + These are deprecated. Use xmlrpc_decompose_value... instead. +*/ +void +xmlrpc_parse_value(xmlrpc_env * const envP, + xmlrpc_value * const value, + const char * const format, + ...); + +/* The same as the above, but using a va_list. */ +void +xmlrpc_parse_value_va(xmlrpc_env * const envP, + xmlrpc_value * const value, + const char * const format, + va_list const args); + +/*========================================================================= +** Encoding XML +**=======================================================================*/ + +typedef enum xmlrpc_dialect { + xmlrpc_dialect_i8, + xmlrpc_dialect_apache +} xmlrpc_dialect; + +void +xmlrpc_serialize_value2(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP, + xmlrpc_dialect const dialect); + +void +xmlrpc_serialize_value(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP); + +void +xmlrpc_serialize_params2(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const paramArrayP, + xmlrpc_dialect const dialect); + +void +xmlrpc_serialize_params(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const paramArrayP); + +void +xmlrpc_serialize_call2(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_dialect const dialect); + +void +xmlrpc_serialize_call(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const char * const methodName, + xmlrpc_value * const paramArrayP); + +void +xmlrpc_serialize_response2(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP, + xmlrpc_dialect const dialect); + +void +xmlrpc_serialize_response(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP); + +void +xmlrpc_serialize_fault(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const xmlrpc_env * const faultP); + + +/*========================================================================= +** Decoding XML +**=======================================================================*/ + +/* Parse an XML-RPC call. If an error occurs, set a fault and set +** the output variables to NULL. +** The caller is responsible for calling free(*out_method_name) and +** xmlrpc_DECREF(*out_param_array). */ +void +xmlrpc_parse_call(xmlrpc_env * const envP, + const char * const xml_data, + size_t const xml_len, + const char ** const out_method_name, + xmlrpc_value ** const out_param_array); + +void +xmlrpc_parse_response2(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen, + xmlrpc_value ** const resultPP, + int * const faultCodeP, + const char ** const faultStringP); + + +/* xmlrpc_parse_response() is for backward compatibility */ + +xmlrpc_value * +xmlrpc_parse_response(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen); + + +/*========================================================================= +** XML-RPC Base64 Utilities +**========================================================================= +** Here are some lightweight utilities which can be used to encode and +** decode Base64 data. These are exported mainly for testing purposes. +*/ + +/* This routine inserts newlines every 76 characters, as required by the +** Base64 specification. */ +xmlrpc_mem_block * +xmlrpc_base64_encode(xmlrpc_env * env, + unsigned char * bin_data, + size_t bin_len); + +/* This routine encodes everything in one line. This is needed for HTTP +** authentication and similar tasks. */ +xmlrpc_mem_block * +xmlrpc_base64_encode_without_newlines(xmlrpc_env * env, + unsigned char * bin_data, + size_t bin_len); + +/* This decodes Base64 data with or without newlines. */ +extern xmlrpc_mem_block * +xmlrpc_base64_decode(xmlrpc_env * const envP, + const char * const ascii_data, + size_t const ascii_len); + + +/*========================================================================= +** Authorization Cookie Handling +**========================================================================= +** Routines to get and set values for authorizing via authorization +** cookies. Both the client and server use HTTP_COOKIE_AUTH to store +** the representation of the authorization value, which is actually +** just a base64 hash of username:password. (This entire method is +** a cookie replacement of basic authentication.) +**/ + +extern void xmlrpc_authcookie_set(xmlrpc_env * const env, + const char * const username, + const char * const password); + +char *xmlrpc_authcookie(void); + +/*========================================================================= + Resource Limits + + Ideally, there would be enough resource limits to ensure that + XML-RPC partners cannot cause libxmlrpc objects and routines to use + more resource than is available for them (either by accident or + malice). We have a long way to go to get there. + +=========================================================================*/ +/* These functions are _not_ re-entrant and the limits are per-process + (i.e. their values live in static global variables). +*/ + +/* Limit IDs. There will be more of these as time goes on. */ +#define XMLRPC_NESTING_LIMIT_ID (0) +#define XMLRPC_XML_SIZE_LIMIT_ID (1) +#define XMLRPC_LAST_LIMIT_ID (XMLRPC_XML_SIZE_LIMIT_ID) + +/* By default, deserialized data may be no more than 64 levels deep. */ +#define XMLRPC_NESTING_LIMIT_DEFAULT (64) + +/* By default, XML data from the network may be no larger than 512K. +** Some client and server modules may fail to enforce this properly. */ +#define XMLRPC_XML_SIZE_LIMIT_DEFAULT (512*1024) + +/* Set a specific limit to the specified value. */ +extern void xmlrpc_limit_set (int const limit_id, size_t const value); + +/* Get the value of a specified limit. */ +extern size_t xmlrpc_limit_get (int const limit_id); + + +#ifdef __cplusplus +} +#endif + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#endif + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/base_int.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/base_int.h new file mode 100644 index 0000000..be45cfd --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/base_int.h @@ -0,0 +1,198 @@ +/*============================================================================ + base_int.h +============================================================================== + This header file defines the interface between modules inside + xmlrpc-c. + + Use this in addition to xmlrpc.h, which defines the external + interface. + + Copyright information is at the end of the file. +============================================================================*/ + + +#ifndef XMLRPC_C_BASE_INT_H_INCLUDED +#define XMLRPC_C_BASE_INT_H_INCLUDED + +#include "xmlrpc_config.h" +#include "bool.h" +#include "int.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +struct _xmlrpc_value { + xmlrpc_type _type; + int _refcount; + + /* Certain data types store their data directly in the xmlrpc_value. */ + union { + xmlrpc_int32 i; + xmlrpc_int64 i8; + xmlrpc_bool b; + double d; + /* time_t t */ + void * c_ptr; + } _value; + + /* Other data types use a memory block. + + For a string, this is the characters of the lines of the string + in UTF-8, with lines delimited by either CR, LF, or CRLF, plus + a NUL added to the end. The characters of the lines may be any + character representable in UTF-8, even the ones that are not + legal XML (XML doesn't allow ASCII control characters except + tab, CR, LF). But note that a line can't contain CR or LF + because that would form a line delimiter. To disambiguate: + CRLF together is always one line delimiter. + + This format for string is quite convenient because it is also + the format of that part of an XML document which is the + contents of a element (except of course that for the + non-XML characters, we have to stretch the definition of XML). + + For base64, this is bytes of the byte string, directly. + + For datetime, this is in the same format as the contents of + a XML element. That really ought to be changed + to time_t some day. + */ + xmlrpc_mem_block _block; + + xmlrpc_mem_block *_wcs_block; + /* This is a copy of the string value in _block, but in UTF-16 + instead of UTF-8. This member is not always present. If NULL, + it is not present. + + We keep this copy for convenience. The value is totally + redundant with _block. + + This member is always NULL when the data type is not string. + + This member is always NULL on a system that does not have + Unicode wchar functions. + */ +}; + +#define XMLRPC_ASSERT_VALUE_OK(val) \ + XMLRPC_ASSERT((val) != NULL && (val)->_type != XMLRPC_TYPE_DEAD) + +/* A handy type-checking routine. */ +#define XMLRPC_TYPE_CHECK(env,v,t) \ + do \ + if ((v)->_type != (t)) \ + XMLRPC_FAIL(env, XMLRPC_TYPE_ERROR, "Expected " #t); \ + while (0) + + +typedef struct { + uint32_t keyHash; + xmlrpc_value * key; + xmlrpc_value * value; +} _struct_member; + + +void +xmlrpc_createXmlrpcValue(xmlrpc_env * const envP, + xmlrpc_value ** const valPP); + +const char * +xmlrpc_typeName(xmlrpc_type const type); + +void +xmlrpc_traceXml(const char * const label, + const char * const xml, + unsigned int const xmlLength); + +void +xmlrpc_destroyString(xmlrpc_value * const stringP); + +void +xmlrpc_destroyStruct(xmlrpc_value * const structP); + +void +xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP); + +/*---------------------------------------------------------------------------- + The following are for use by the legacy xmlrpc_parse_value(). They don't + do proper memory management, so they aren't appropriate for general use, + but there are old users that do xmlrpc_parse_value() and compensate for + the memory management, so we have to continue to offer this style of + memory management. + + In particular, the functions that return xmlrpc_values don't increment + the reference count, and the functions that return strings don't allocate + new memory for them. +-----------------------------------------------------------------------------*/ + +void +xmlrpc_read_datetime_str_old(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP); + +void +xmlrpc_read_string_old(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP); + +void +xmlrpc_read_string_lp_old(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const char ** const stringValueP); + +#if XMLRPC_HAVE_WCHAR +void +xmlrpc_read_string_w_old(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const wchar_t ** const stringValueP); + +void +xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + size_t * const lengthP, + const wchar_t ** const stringValueP); +#endif + +void +xmlrpc_read_base64_old(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const unsigned char ** const byteStringValueP); + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/c_util.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/c_util.h new file mode 100644 index 0000000..a1ede08 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/c_util.h @@ -0,0 +1,20 @@ +#ifndef XMLRPC_C_C_UTIL_H_INCLUDED +#define XMLRPC_C_C_UTIL_H_INCLUDED + +/* C language stuff. Doesn't involve any libraries that aren't part of + the compiler. +*/ + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type + calls to be sure the arguments match the format string, thus preventing + runtime segmentation faults and incorrect messages. +*/ +#ifdef __GNUC__ +#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b))) +#else +#define GNU_PRINTF_ATTR(a,b) +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client.h new file mode 100644 index 0000000..c2e2e61 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client.h @@ -0,0 +1,316 @@ +/*============================================================================ + xmlrpc_client.h +============================================================================== + This header file defines the interface between xmlrpc.c and its users, + related to clients. + + Copyright information is at the end of the file. +============================================================================*/ + +#ifndef XMLRPC_CLIENT_H_INCLUDED +#define XMLRPC_CLIENT_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct xmlrpc_client; +struct xmlrpc_client_transport; +struct xmlrpc_client_transport_ops; +#ifndef __cplusplus +typedef struct xmlrpc_client xmlrpc_client; +typedef struct xmlrpc_client_transport xmlrpc_client_transport; +typedef struct xmlrpc_client_transport_ops xmlrpc_client_transport_ops; +#endif + +/* libxmlrpc_client typically does _not_ actually include all of the + XML transports declared here by xmlrpc_*_transport_ops. + + Use 'xmlrpc-c-config --features' to determine which features are + installed. +*/ + +/* Before Xmlrpc-c 1.13 (December 2007), we declared struct + xmlrpc_xportparms, as a sort of "base class." The struct was never + complete -- you just cast pointer to it it to pointers to other + types. It turned out not to be really helpful and casts are ugly, + so now we just use void * as a base class pointer. +*/ + +extern struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops; +extern struct xmlrpc_client_transport_ops xmlrpc_wininet_transport_ops; +extern struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops; + +enum xmlrpc_sslversion { + XMLRPC_SSLVERSION_DEFAULT, + XMLRPC_SSLVERSION_TLSv1, + XMLRPC_SSLVERSION_SSLv2, + XMLRPC_SSLVERSION_SSLv3 +}; + +struct xmlrpc_curl_xportparms { + /* This is designed so that zero values are always the defaults. */ + const char * network_interface; + xmlrpc_bool no_ssl_verifypeer; + xmlrpc_bool no_ssl_verifyhost; + const char * user_agent; + const char * ssl_cert; + const char * sslcerttype; + const char * sslcertpasswd; + const char * sslkey; + const char * sslkeytype; + const char * sslkeypasswd; + const char * sslengine; + xmlrpc_bool sslengine_default; + enum xmlrpc_sslversion sslversion; + const char * cainfo; + const char * capath; + const char * randomfile; + const char * egdsocket; + const char * ssl_cipher_list; + unsigned int timeout; +}; + + +#define XMLRPC_CXPSIZE(mbrname) \ + XMLRPC_STRUCTSIZE(struct xmlrpc_curl_xportparms, mbrname) + +/* XMLRPC_CXPSIZE(xyz) is analogous to XMLRPC_CPSIZE, below */ + +struct xmlrpc_wininet_xportparms { + int allowInvalidSSLCerts; +}; + +#define XMLRPC_WXPSIZE(mbrname) \ + XMLRPC_STRUCTSIZE(struct xmlrpc_wininet_xportparms, mbrname) + +/* XMLRPC_WXPSIZE(xyz) is analogous to XMLRPC_CPSIZE, below */ + +struct xmlrpc_clientparms { + /* (transport, transportparmsP, transportparm_size) and + (transportOpsP, transportP) are mutually exclusive. + */ + const char * transport; + const void * transportparmsP; + /* This should be type "const struct ..._xportparms *" */ + size_t transportparm_size; + + const struct xmlrpc_client_transport_ops * transportOpsP; + xmlrpc_client_transport * transportP; + xmlrpc_dialect dialect; +}; + +#define XMLRPC_CPSIZE(mbrname) \ + XMLRPC_STRUCTSIZE(struct xmlrpc_clientparms, mbrname) + +/* XMLRPC_CPSIZE(xyz) is the minimum size a struct xmlrpc_clientparms + must be to include the 'xyz' member. This is essential to forward and + backward compatbility, as new members will be added to the end of the + struct in future releases. This is how the callee knows whether or + not the caller is new enough to have supplied a certain parameter. +*/ + +const char * +xmlrpc_client_get_default_transport(xmlrpc_env * const env); + +/* A callback function to handle the response to an asynchronous call. +** If 'fault->fault_occurred' is true, then response will be NULL. All +** arguments except 'user_data' will be deallocated internally; please do +** not free any of them yourself. +** WARNING: param_array may (or may not) be NULL if fault->fault_occurred +** is true, and you set up the call using xmlrpc_client_call_asynch. +** WARNING: If asynchronous calls are still pending when the library is +** shut down, your handler may (or may not) be called with a fault. */ +typedef void (*xmlrpc_response_handler) (const char *server_url, + const char *method_name, + xmlrpc_value *param_array, + void *user_data, + xmlrpc_env *fault, + xmlrpc_value *result); + + +/*========================================================================= + xmlrpc_server_info +=========================================================================== + We normally refer to servers by URL. But sometimes we need to do extra + setup for particular servers. In that case, we can create an + xmlrpc_server_info object, configure it in various ways, and call the + remote server. + + (This interface is also designed to discourage further multiplication + of xmlrpc_client_call APIs. We have enough of those already. Please + add future options and flags using xmlrpc_server_info.) +=========================================================================*/ + +typedef struct _xmlrpc_server_info xmlrpc_server_info; + +/* Create a new server info record, pointing to the specified server. */ +xmlrpc_server_info * +xmlrpc_server_info_new(xmlrpc_env * const envP, + const char * const serverUrl); + +/* Create a new server info record, with a copy of the old server. */ +extern xmlrpc_server_info * +xmlrpc_server_info_copy(xmlrpc_env * const envP, + xmlrpc_server_info * const srcP); + +void +xmlrpc_server_info_free(xmlrpc_server_info * const serverP); + + +void +xmlrpc_server_info_set_user(xmlrpc_env * const envP, + xmlrpc_server_info * const serverInfoP, + const char * const username, + const char * const password); + +void +xmlrpc_server_info_set_basic_auth(xmlrpc_env * const envP, + xmlrpc_server_info * const serverP, + const char * const username, + const char * const password); + +void +xmlrpc_server_info_allow_auth_basic(xmlrpc_env * const envP, + xmlrpc_server_info * const sP); + +void +xmlrpc_server_info_disallow_auth_basic(xmlrpc_env * const envP, + xmlrpc_server_info * const sP); + +void +xmlrpc_server_info_allow_auth_digest(xmlrpc_env * const envP, + xmlrpc_server_info * const sP); + +void +xmlrpc_server_info_disallow_auth_digest(xmlrpc_env * const envP, + xmlrpc_server_info * const sP); + +void +xmlrpc_server_info_allow_auth_negotiate(xmlrpc_env * const envP, + xmlrpc_server_info * const sP); + +void +xmlrpc_server_info_disallow_auth_negotiate(xmlrpc_env * const envP, + xmlrpc_server_info * const sP); + +void +xmlrpc_server_info_allow_auth_ntlm(xmlrpc_env * const envP, + xmlrpc_server_info * const sP); + +void +xmlrpc_server_info_disallow_auth_ntlm(xmlrpc_env * const envP, + xmlrpc_server_info * const sP); + +extern unsigned int const xmlrpc_client_version_major; +extern unsigned int const xmlrpc_client_version_minor; +extern unsigned int const xmlrpc_client_version_point; + +void +xmlrpc_client_setup_global_const(xmlrpc_env * const envP); + +void +xmlrpc_client_teardown_global_const(void); + +void +xmlrpc_client_create(xmlrpc_env * const envP, + int const flags, + const char * const appname, + const char * const appversion, + const struct xmlrpc_clientparms * const clientparmsP, + unsigned int const parmSize, + xmlrpc_client ** const clientPP); + +void +xmlrpc_client_destroy(xmlrpc_client * const clientP); + +void +xmlrpc_client_transport_call2( + xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block ** const respXmlPP); + +void +xmlrpc_client_call2(xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_value ** const resultPP); + +void +xmlrpc_client_call2f(xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const char * const serverUrl, + const char * const methodName, + xmlrpc_value ** const resultPP, + const char * const format, + ...); + +void +xmlrpc_client_event_loop_finish(xmlrpc_client * const clientP); + +void +xmlrpc_client_event_loop_finish_timeout(xmlrpc_client * const clientP, + unsigned long const milliseconds); + +void +xmlrpc_client_start_rpc(xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_value * const argP, + xmlrpc_response_handler responseHandler, + void * const userData); + +void +xmlrpc_client_start_rpcf(xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const char * const serverUrl, + const char * const methodName, + xmlrpc_response_handler callback, + void * const userData, + const char * const format, + ...); + +void +xmlrpc_client_set_interrupt(xmlrpc_client * const clientP, + int * const interruptP); + +#include + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _XMLRPC_CLIENT_H_ */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client_global.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client_global.h new file mode 100644 index 0000000..4f388fc --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client_global.h @@ -0,0 +1,141 @@ +#ifndef CLIENT_GLOBAL_H_INCLUDED +#define CLIENT_GLOBAL_H_INCLUDED + +/*========================================================================= +** Initialization and Shutdown +**========================================================================= +** These routines initialize and terminate the XML-RPC client. If you're +** already using libwww on your own, you can pass +** XMLRPC_CLIENT_SKIP_LIBWWW_INIT to avoid initializing it twice. +*/ + +#define XMLRPC_CLIENT_NO_FLAGS (0) +#define XMLRPC_CLIENT_SKIP_LIBWWW_INIT (1) + +extern void +xmlrpc_client_init(int const flags, + const char * const appname, + const char * const appversion); + +void +xmlrpc_client_init2(xmlrpc_env * const env, + int const flags, + const char * const appname, + const char * const appversion, + const struct xmlrpc_clientparms * const clientparms, + unsigned int const parm_size); + +extern void +xmlrpc_client_cleanup(void); + +/*========================================================================= +** xmlrpc_client_call +**========================================================================= +** A synchronous XML-RPC client. Do not attempt to call any of these +** functions from inside an asynchronous callback! +*/ + +xmlrpc_value * +xmlrpc_client_call(xmlrpc_env * const envP, + const char * const server_url, + const char * const method_name, + const char * const format, + ...); + +xmlrpc_value * +xmlrpc_client_call_params(xmlrpc_env * const envP, + const char * const serverUrl, + const char * const methodName, + xmlrpc_value * const paramArrayP); + +xmlrpc_value * +xmlrpc_client_call_server(xmlrpc_env * const envP, + const xmlrpc_server_info * const server, + const char * const method_name, + const char * const format, + ...); + +xmlrpc_value * +xmlrpc_client_call_server_params( + xmlrpc_env * const envP, + const xmlrpc_server_info * const serverP, + const char * const method_name, + xmlrpc_value * const paramArrayP); + +void +xmlrpc_client_transport_call( + xmlrpc_env * const envP, + void * const reserved, /* for client handle */ + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block ** const respXmlPP); + + +/*========================================================================= +** xmlrpc_client_call_asynch +**========================================================================= +** An asynchronous XML-RPC client. +*/ + +/* Make an asynchronous XML-RPC call. We make internal copies of all +** arguments except user_data, so you can deallocate them safely as soon +** as you return. Errors will be passed to the callback. You will need +** to run the event loop somehow; see below. +** WARNING: If an error occurs while building the argument, the +** response handler will be called with a NULL param_array. */ +void +xmlrpc_client_call_asynch(const char * const server_url, + const char * const method_name, + xmlrpc_response_handler callback, + void * const user_data, + const char * const format, + ...); + +/* As above, but use an xmlrpc_server_info object. The server object can be +** safely destroyed as soon as this function returns. */ +void +xmlrpc_client_call_server_asynch(xmlrpc_server_info * const server, + const char * const method_name, + xmlrpc_response_handler callback, + void * const user_data, + const char * const format, + ...); + +/* As above, but the parameter list is supplied as an xmlrpc_value +** containing an array. +*/ +void +xmlrpc_client_call_asynch_params(const char * const server_url, + const char * const method_name, + xmlrpc_response_handler callback, + void * const user_data, + xmlrpc_value * const paramArrayP); + +/* As above, but use an xmlrpc_server_info object. The server object can be +** safely destroyed as soon as this function returns. */ +void +xmlrpc_client_call_server_asynch_params( + xmlrpc_server_info * const server, + const char * const method_name, + xmlrpc_response_handler callback, + void * const user_data, + xmlrpc_value * const paramArrayP); + +/*========================================================================= +** Event Loop Interface +**========================================================================= +** These functions can be used to run the XML-RPC event loop. If you +** don't like these, you can also run the libwww event loop directly. +*/ + +/* Finish all outstanding asynchronous calls. Alternatively, the loop +** will exit if someone calls xmlrpc_client_event_loop_end. */ +extern void +xmlrpc_client_event_loop_finish_asynch(void); + + +/* Finish all outstanding asynchronous calls. */ +extern void +xmlrpc_client_event_loop_finish_asynch_timeout(unsigned long const milliseconds); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client_int.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client_int.h new file mode 100644 index 0000000..dabdcaf --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/client_int.h @@ -0,0 +1,121 @@ +/*============================================================================ + xmlrpc_client_int.h +============================================================================== + This header file defines the interface between client modules inside + xmlrpc-c. + + Use this in addition to xmlrpc_client.h, which defines the external + interface. + + Copyright information is at the end of the file. +============================================================================*/ + + +#ifndef XMLRPC_CLIENT_INT_H_INCLUDED +#define XMLRPC_CLIENT_INT_H_INCLUDED + +#include "xmlrpc-c/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _xmlrpc_server_info { + const char * serverUrl; + struct { + bool basic; + bool digest; + bool gssnegotiate; + bool ntlm; + } allowedAuth; + const char * userNamePw; + /* The username/password value for HTTP, i.e. in + "user:password" form + + This can be NULL to indicate "none", but only if 'allowedAuth' + doesn't allow any form of authentication. + */ + const char * basicAuthHdrValue; + /* A complete value for an HTTP Authorization: header that + requests HTTP basic authentication. This exists whether + or not 'allowedAuth' allows basic authentication, and is + completely redundant with 'userNamePw'. It exists mainly + for historical reasons, and may also save some computation + when the same xmrpc_server_info is used for multiple + HTTP connections. + + This is NULL exactly when 'userNamePw' is NULL. + */ +}; + +/*========================================================================= +** Transport Implementation functions. +**========================================================================= */ +#include "xmlrpc-c/transport.h" + +/* The generalized event loop. This uses the above flags. For more details, +** see the wrapper functions below. If you're not using the timeout, the +** 'milliseconds' parameter will be ignored. +** Note that ANY event loop call will return immediately if there are +** no outstanding XML-RPC calls. */ +extern void +xmlrpc_client_event_loop_run_general (int flags, xmlrpc_timeout milliseconds); + +/* Run the event loop forever. The loop will exit if someone calls +** xmlrpc_client_event_loop_end. */ +extern void +xmlrpc_client_event_loop_run (void); + +/* Run the event loop forever. The loop will exit if someone calls +** xmlrpc_client_event_loop_end or the timeout expires. +** (Note that ANY event loop call will return immediately if there are +** no outstanding XML-RPC calls.) */ +extern void +xmlrpc_client_event_loop_run_timeout (xmlrpc_timeout milliseconds); + +/* End the running event loop immediately. This can also be accomplished +** by calling the corresponding function in libwww. +** (Note that ANY event loop call will return immediately if there are +** no outstanding XML-RPC calls.) */ +extern void +xmlrpc_client_event_loop_end (void); + + +/* Return true if there are uncompleted asynchronous calls. +** The exact value of this during a response callback is undefined. */ +extern int +xmlrpc_client_asynch_calls_are_unfinished (void); + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + + + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/config.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/config.h new file mode 100644 index 0000000..1c1b6b6 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/config.h @@ -0,0 +1,37 @@ +#ifndef XMLRPC_C_CONFIG_H_INCLUDED +#define XMLRPC_C_CONFIG_H_INCLUDED + +/* This file, part of XML-RPC For C/C++, is meant to + define characteristics of this particular installation + that the other header files need in + order to compile correctly when #included in Xmlrpc-c + user code. + + Those header files #include this one. + + This file was created by a make rule. +*/ +#define XMLRPC_HAVE_WCHAR 1 +#ifdef WIN32 + /* SOCKET is a type defined by . Anyone who + uses XMLRPC_SOCKET on a WIN32 system must #include + + */ + #define XMLRPC_SOCKET SOCKET + #define XMLRPC_HAVE_TIMEVAL 0 + #define XMLRPC_HAVE_TIMESPEC 0 +#else + #define XMLRPC_SOCKET int + #define XMLRPC_HAVE_TIMEVAL 1 + #define XMLRPC_HAVE_TIMESPEC 1 +#endif + +#if defined(_MSC_VER) + /* Newer MSVC has long long, but MSVC 6 does not */ + #define XMLRPC_INT64 __int64 + #define XMLRPC_INT32 __int32 +#else + #define XMLRPC_INT64 long long + #define XMLRPC_INT32 int +#endif +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/inttypes.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/inttypes.h new file mode 100644 index 0000000..fe1feb5 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/inttypes.h @@ -0,0 +1,19 @@ +#ifndef XMLRPC_INTTYPES_H_INCLUDED +#define XMLRPC_INTTYPES_H_INCLUDED + +#ifdef _MSC_VER + +typedef unsigned short xmlrpc_uint16_t; +typedef unsigned int xmlrpc_uint32_t; +typedef unsigned __int64 xmlrpc_uint64_t; + +#else +#include + +typedef uint16_t xmlrpc_uint16_t; +typedef uint32_t xmlrpc_uint32_t; +typedef uint64_t xmlrpc_uint64_t; + +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/oldxmlrpc.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/oldxmlrpc.h new file mode 100644 index 0000000..2a5d3bf --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/oldxmlrpc.h @@ -0,0 +1,2 @@ +#include +#include diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/select_int.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/select_int.h new file mode 100644 index 0000000..3b42a1d --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/select_int.h @@ -0,0 +1,24 @@ +#ifndef SELECT_INT_H_INCLUDED +#define SELECT_INT_H_INCLUDED + +#ifndef WIN32 +#include +#endif +#include + +#include "xmlrpc-c/time_int.h" +#ifdef WIN32 +#ifndef sigset_t +typedef int sigset_t; +#endif +#endif + +int +xmlrpc_pselect(int const n, + fd_set * const readfdsP, + fd_set * const writefdsP, + fd_set * const exceptfdsP, + const xmlrpc_timespec * const timeoutP, + sigset_t * const sigmaskP); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server.h new file mode 100644 index 0000000..28773c6 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server.h @@ -0,0 +1,173 @@ +/* Copyright and license information is at the end of the file */ + +#ifndef XMLRPC_SERVER_H_INCLUDED +#define XMLRPC_SERVER_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct xmlrpc_registry xmlrpc_registry; + +typedef void +(*xmlrpc_preinvoke_method)(xmlrpc_env * const envP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + void * const userData); + +typedef xmlrpc_value * +(*xmlrpc_method1)(xmlrpc_env * const envP, + xmlrpc_value * const paramArrayP, + void * const serverInfo); + +typedef xmlrpc_value * +(*xmlrpc_method2)(xmlrpc_env * const envP, + xmlrpc_value * const paramArrayP, + void * const serverInfo, + void * const callInfo); + +typedef xmlrpc_method1 xmlrpc_method; /* backward compatibility */ + +typedef xmlrpc_value * +(*xmlrpc_default_method)(xmlrpc_env * const envP, + const char * const callInfoP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + void * const serverInfo); + +extern unsigned int const xmlrpc_server_version_major; +extern unsigned int const xmlrpc_server_version_minor; +extern unsigned int const xmlrpc_server_version_point; + +xmlrpc_registry * +xmlrpc_registry_new(xmlrpc_env * const envP); + +void +xmlrpc_registry_free(xmlrpc_registry * const registryP); + +void +xmlrpc_registry_disable_introspection(xmlrpc_registry * const registryP); + +void +xmlrpc_registry_add_method(xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + const char * const host, + const char * const methodName, + xmlrpc_method const method, + void * const serverInfo); + +void +xmlrpc_registry_add_method_w_doc(xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + const char * const host, + const char * const methodName, + xmlrpc_method const method, + void * const serverInfo, + const char * const signatureString, + const char * const help); + +void +xmlrpc_registry_add_method2(xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + const char * const methodName, + xmlrpc_method2 method, + const char * const signatureString, + const char * const help, + void * const serverInfo); + +struct xmlrpc_method_info3 { + const char * methodName; + xmlrpc_method2 methodFunction; + void * serverInfo; + size_t stackSize; + const char * signatureString; + const char * help; +}; + +void +xmlrpc_registry_add_method3( + xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + const struct xmlrpc_method_info3 * const infoP); + +void +xmlrpc_registry_set_default_method(xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + xmlrpc_default_method const handler, + void * const userData); + +void +xmlrpc_registry_set_preinvoke_method(xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + xmlrpc_preinvoke_method const method, + void * const userData); + + +typedef void xmlrpc_server_shutdown_fn(xmlrpc_env * const envP, + void * const context, + const char * const comment, + void * const callInfo); + +void +xmlrpc_registry_set_shutdown(xmlrpc_registry * const registryP, + xmlrpc_server_shutdown_fn * const shutdownFn, + void * const context); + +void +xmlrpc_registry_set_dialect(xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + xmlrpc_dialect const dialect); + +/*---------------------------------------------------------------------------- + Lower interface -- services to be used by an HTTP request handler +-----------------------------------------------------------------------------*/ + +void +xmlrpc_registry_process_call2(xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + const char * const xmlData, + size_t const xmlLen, + void * const callInfo, + xmlrpc_mem_block ** const outputPP); + +xmlrpc_mem_block * +xmlrpc_registry_process_call(xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + const char * const host, + const char * const xmlData, + size_t const xmlLen); + +size_t +xmlrpc_registry_max_stackSize(xmlrpc_registry * const registryP); + +#ifdef __cplusplus +} +#endif + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server_cgi.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server_cgi.h new file mode 100644 index 0000000..ad926aa --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server_cgi.h @@ -0,0 +1,49 @@ +/* Interface header file for libxmlrpc_server_cgi. + + By Bryan Henderson, 05.04.27. Contributed to the public domain. +*/ + +#ifndef XMLRPC_CGI_H_INCLUDED +#define XMLRPC_CGI_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +void +xmlrpc_server_cgi_process_call(xmlrpc_registry * const registryP); + +#define XMLRPC_CGI_NO_FLAGS (0) + +extern void +xmlrpc_cgi_init (int flags); + +extern xmlrpc_registry * +xmlrpc_cgi_registry (void); + +void +xmlrpc_cgi_add_method(const char * const method_name, + xmlrpc_method const method, + void * const user_data); + +void +xmlrpc_cgi_add_method_w_doc(const char * const method_name, + xmlrpc_method const method, + void * const user_data, + const char * const signature, + const char * const help); +extern void +xmlrpc_cgi_process_call (void); + +extern void +xmlrpc_cgi_cleanup (void); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server_w32httpsys.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server_w32httpsys.h new file mode 100644 index 0000000..085f6e3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/server_w32httpsys.h @@ -0,0 +1,95 @@ +/* Copyright (C) 2005 by Steven A. Bone, sbone@pobox.com. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +/* COMPILATION NOTE: + Note that the Platform SDK headers and + link libraries for Windows XP SP2 or newer are required to compile + xmlrpc-c for this module. If you are not using this server, it is + safe to exclude the xmlrpc_server_w32httpsys.c file from the xmlrpc + project and these dependencies will not be required. You can get the + latest platform SDK at + http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ + Be sure after installation to choose the program to "register the PSDK + directories with Visual Studio" so the newer headers are found. +*/ + +#ifndef _XMLRPC_SERVER_HTTPSYS_H_ +#define _XMLRPC_SERVER_HTTPSYS_H_ 1 + +#include "transport_config.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*========================================================================= +** XML-RPC Server (based on HTTP.SYS) +**========================================================================= +** A simple XML-RPC server based on the "built-in" Windows web server, +** HTTP.SYS. This is provided by Microsoft in Windows XP SP2 and +** Windows Server 2003. If errors occur during server setup, the server +** will exit. In general, if you want to use this API, you do not really +** need to be familiar with the HTTP.SYS API. +*/ + +typedef void (*authorization_function)( + xmlrpc_env * envP, + char * userid, + char * password); + +typedef struct { + xmlrpc_registry * registryP; + unsigned int portNum; + unsigned int useSSL; + /* useSSL, 0 = no SSL, 1 = use SSL */ + unsigned int logLevel; + /* logLevel, 0 = none, 1 = file, 2 = file+OutputDebugString() */ + const char * logFile; + /* logFile, NULL or filename */ + authorization_function authfn; +} xmlrpc_server_httpsys_parms; + +#define XMLRPC_HSSIZE(MBRNAME) \ + XMLRPC_STRUCTSIZE(xmlrpc_server_httpsys_parms, MBRNAME) + +/* XMLRPC_HSSIZE(xyz) is the minimum size a struct xmlrpc_server_httpsys_parms + must be to include the 'xyz' member. This is essential for forward and + backward compatbility, as new members will be added to the end of the + struct in future releases. This is how the callee knows whether or + not the caller is new enough to have supplied a certain parameter. +*/ + +void +xmlrpc_server_httpsys( + xmlrpc_env * const envP, + const xmlrpc_server_httpsys_parms * const parmsP, + unsigned int const parm_size + ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/sleep_int.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/sleep_int.h new file mode 100644 index 0000000..be18e8f --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/sleep_int.h @@ -0,0 +1,7 @@ +#ifndef SLEEP_INT_H_INCLUDED +#define SLEEP_INT_H_INCLUDED + +void +xmlrpc_millisecond_sleep(unsigned int const milliseconds); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/string_int.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/string_int.h new file mode 100644 index 0000000..70d9139 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/string_int.h @@ -0,0 +1,113 @@ +#ifndef XMLRPC_C_STRING_INT_H_INCLUDED +#define XMLRPC_C_STRING_INT_H_INCLUDED + + +#include +#include + +#include "xmlrpc_config.h" +#include "c_util.h" +#include "bool.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char * const xmlrpc_strsol; + +void +xmlrpc_vasprintf(const char ** const retvalP, + const char * const fmt, + va_list varargs); + +void GNU_PRINTF_ATTR(2,3) +xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...); + +const char * +xmlrpc_strdupnull(const char * const string); + +void +xmlrpc_strfree(const char * const string); + +void +xmlrpc_strfreenull(const char * const string); + +static __inline__ bool +xmlrpc_streq(const char * const a, + const char * const b) { + return (strcmp(a, b) == 0); +} + +static __inline__ bool +xmlrpc_memeq(const void * const a, + const void * const b, + size_t const size) { + + return (memcmp(a, b, size) == 0); +} + +/* strcasecmp doesn't exist on some systems without _BSD_SOURCE, so + xmlrpc_strcaseeq() can't either. +*/ +#ifdef _BSD_SOURCE + +static __inline__ bool +xmlrpc_strcaseeq(const char * const a, + const char * const b) { +#if HAVE_STRCASECMP + return (strcasecmp(a, b) == 0); +#elif HAVE__STRICMP + return (_stricmp(a, b) == 0); +#elif HAVE_STRICMP + return (stricmp(a, b) == 0); +#else + #error "This platform has no known case-independent string compare fn" +#endif +} +#endif + +static __inline__ bool +xmlrpc_strneq(const char * const a, + const char * const b, + size_t const len) { + return (strncmp(a, b, len) == 0); +} + +const char * +xmlrpc_makePrintable(const char * const input); + +const char * +xmlrpc_makePrintable_lp(const char * const input, + size_t const inputLength); + +const char * +xmlrpc_makePrintableChar(char const input); + +/*----------------------------------------------------------------*/ +/* Standard string functions with destination array size checking */ +/*----------------------------------------------------------------*/ +#define STRSCPY(A,B) \ + (strncpy((A), (B), sizeof(A)), *((A)+sizeof(A)-1) = '\0') +#define STRSCMP(A,B) \ + (strncmp((A), (B), sizeof(A))) +#define STRSCAT(A,B) \ + (strncat((A), (B), sizeof(A)-strlen(A)), *((A)+sizeof(A)-1) = '\0') + +/* We could do this, but it works only in GNU C +#define SSPRINTF(TARGET, REST...) \ + (snprintf(TARGET, sizeof(TARGET) , ## REST)) + +Or this, but it works only in C99 compilers, which leaves out MSVC +before 2005 and can't handle the zero variable argument case except +by an MSVC extension: + +#define SSPRINTF(TARGET, ...) \ + (snprintf(TARGET, sizeof(TARGET) , __VA_ARGS__)) + +*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/time_int.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/time_int.h new file mode 100644 index 0000000..4db4537 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/time_int.h @@ -0,0 +1,35 @@ +#ifndef TIME_H_INCLUDED +#define TIME_H_INCLUDED + +#include + +#include "xmlrpc_config.h" +#include "xmlrpc-c/util.h" +#include "int.h" + +#if HAVE_TIMESPEC + typedef struct timespec xmlrpc_timespec; +#else + typedef struct { + uint32_t tv_sec; + uint32_t tv_nsec; + } xmlrpc_timespec; +#endif + +void +xmlrpc_gettimeofday(xmlrpc_timespec * const todP); + +void +xmlrpc_timegm(const struct tm * const brokenTime, + time_t * const timeValueP, + const char ** const errorP); + +void +xmlrpc_localtime(time_t const datetime, + struct tm * const tmP); + +void +xmlrpc_gmtime(time_t const datetime, + struct tm * const resultP); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/transport.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/transport.h new file mode 100644 index 0000000..13d901f --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/transport.h @@ -0,0 +1,86 @@ +/* Copyright information is at the end of the file */ +#ifndef XMLRPC_TRANSPORT_H_INCLUDED +#define XMLRPC_TRANSPORT_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct xmlrpc_call_info; + +struct xmlrpc_client_transport; + +/*========================================================================= +** Transport function type declarations. +**========================================================================= +*/ +typedef void (*xmlrpc_transport_setup)(xmlrpc_env * const envP); + +typedef void (*xmlrpc_transport_teardown)(void); + +typedef void (*xmlrpc_transport_create)( + xmlrpc_env * const envP, + int const flags, + const char * const appname, + const char * const appversion, + const void * const transportparmsP, + size_t const transportparm_size, + struct xmlrpc_client_transport ** const handlePP); + +typedef void (*xmlrpc_transport_destroy)( + struct xmlrpc_client_transport * const clientTransportP); + +typedef void (*xmlrpc_transport_asynch_complete)( + struct xmlrpc_call_info * const callInfoP, + xmlrpc_mem_block * const responseXmlP, + xmlrpc_env const env); + +typedef void (*xmlrpc_transport_send_request)( + xmlrpc_env * const envP, + struct xmlrpc_client_transport * const clientTransportP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const xmlP, + xmlrpc_transport_asynch_complete complete, + struct xmlrpc_call_info * const callInfoP); + +typedef void (*xmlrpc_transport_call)( + xmlrpc_env * const envP, + struct xmlrpc_client_transport * const clientTransportP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const xmlP, + xmlrpc_mem_block ** const responsePP); + +typedef enum {timeout_no, timeout_yes} xmlrpc_timeoutType; + +typedef unsigned long xmlrpc_timeout; + /* A timeout in milliseconds. */ + +typedef void (*xmlrpc_transport_finish_asynch)( + struct xmlrpc_client_transport * const clientTransportP, + xmlrpc_timeoutType const timeoutType, + xmlrpc_timeout const timeout); + +typedef void (*xmlrpc_transport_set_interrupt)( + struct xmlrpc_client_transport * const clientTransportP, + int * const interruptP); + +struct xmlrpc_client_transport_ops { + + xmlrpc_transport_setup setup_global_const; + xmlrpc_transport_teardown teardown_global_const; + xmlrpc_transport_create create; + xmlrpc_transport_destroy destroy; + xmlrpc_transport_send_request send_request; + xmlrpc_transport_call call; + xmlrpc_transport_finish_asynch finish_asynch; + xmlrpc_transport_set_interrupt set_interrupt; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/util.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/util.h new file mode 100644 index 0000000..5b6e4f5 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/util.h @@ -0,0 +1,328 @@ +/*============================================================================= + xmlrpc-c/util.h +=============================================================================== + + This is the interface to the libxmlrpc_util library, which contains + utility routines that have nothing to do with XML-RPC. The library + exists because other Xmlrpc-c libraries use the utilities. + + By Bryan Henderson, San Jose, CA 05.09.21. + + Contributed to the public domain by its author. +=============================================================================*/ + +#ifndef XMLRPC_C_UTIL_H_INCLUDED +#define XMLRPC_C_UTIL_H_INCLUDED + +#include +#include + +#include /* Defines XMLRPC_HAVE_WCHAR */ +#include /* for GNU_PRINTF_ATTR */ + +#if XMLRPC_HAVE_WCHAR +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/*========================================================================= +** C struct size computations +**=======================================================================*/ + +/* Use XMLRPC_STRUCT_MEMBER_SIZE() to determine how big a structure is + up to and including a specified member. E.g. if you have + struct mystruct {int red; int green; int blue};, then + XMLRPC_STRUCT_MEMBER_SIZE(mystruct, green) is (8). +*/ + +#define _XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) \ + ((size_t)(char*)&((TYPE *)0)->MBRNAME) +#define _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME) \ + sizeof(((TYPE *)0)->MBRNAME) +#define XMLRPC_STRUCTSIZE(TYPE, MBRNAME) \ + (_XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) + \ + _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME)) + +/*========================================================================= +** Assertions and Debugging +**========================================================================= +** Note that an assertion is _not_ a directive to check a condition and +** crash if it isn't true. It is an assertion that the condition _is_ +** true. This assertion helps people to read the code. The program +** may also check the assertion as it runs, and if it conflicts with reality, +** recognize that the program is incorrect and abort it. In practice, +** it does this checking when the program was compiled without the NDEBUG +** macro defined. +*/ + +#ifndef NDEBUG + +#define XMLRPC_ASSERT(cond) \ + do \ + if (!(cond)) \ + xmlrpc_assertion_failed(__FILE__, __LINE__); \ + while (0) + +#else +#define XMLRPC_ASSERT(cond) while (0) {} +#endif + +void +xmlrpc_assertion_failed(const char * const fileName, + int const lineNumber); + +/* Validate a pointer. */ +#define XMLRPC_ASSERT_PTR_OK(ptr) \ + XMLRPC_ASSERT((ptr) != NULL) + + +/*========================================================================= +** xmlrpc_env +**========================================================================= +** XML-RPC represents runtime errors as elements. These contain +** and elements. +** +** Since we need as much thread-safety as possible, we borrow an idea from +** CORBA--we store exception information in an "environment" object. +** You'll pass this to many different functions, and it will get filled +** out appropriately. +** +** For example: +** +** xmlrpc_env env; +** +** xmlrpc_env_init(&env); +** +** xmlrpc_do_something(&env); +** if (env.fault_occurred) +** report_error_appropriately(); +** +** xmlrpc_env_clean(&env); +*/ + +#define XMLRPC_INTERNAL_ERROR (-500) +#define XMLRPC_TYPE_ERROR (-501) +#define XMLRPC_INDEX_ERROR (-502) +#define XMLRPC_PARSE_ERROR (-503) +#define XMLRPC_NETWORK_ERROR (-504) +#define XMLRPC_TIMEOUT_ERROR (-505) +#define XMLRPC_NO_SUCH_METHOD_ERROR (-506) +#define XMLRPC_REQUEST_REFUSED_ERROR (-507) +#define XMLRPC_INTROSPECTION_DISABLED_ERROR (-508) +#define XMLRPC_LIMIT_EXCEEDED_ERROR (-509) +#define XMLRPC_INVALID_UTF8_ERROR (-510) + +typedef struct _xmlrpc_env { + int fault_occurred; + int fault_code; + char * fault_string; +} xmlrpc_env; + +/* Initialize and destroy the contents of the provided xmlrpc_env object. +** These functions will never fail. */ +void xmlrpc_env_init (xmlrpc_env* env); +void xmlrpc_env_clean (xmlrpc_env* const env); + +/* Fill out an xmlrpc_fault with the specified values, and set the +** fault_occurred flag. This function will make a private copy of 'string', +** so you retain responsibility for your copy. */ +void +xmlrpc_env_set_fault(xmlrpc_env * const env, + int const faultCode, + const char * const faultDescription); + +/* The same as the above, but using varargs */ +void +xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP, + int const code, + const char * const format, + va_list const args); + +/* The same as the above, but using a printf-style format string. */ +void +xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP, + int const code, + const char * const format, + ...) GNU_PRINTF_ATTR(3,4); + +/* This one infers XMLRPC_INTERNAL_ERROR and has a shorter name. + So a call takes up less source code space. +*/ +void +xmlrpc_faultf(xmlrpc_env * const envP, + const char * const format, + ...) GNU_PRINTF_ATTR(2,3); + +/* A simple debugging assertion. */ +#define XMLRPC_ASSERT_ENV_OK(envP) \ + XMLRPC_ASSERT((envP) != NULL && \ + (envP->fault_string == NULL) && \ + !(envP)->fault_occurred) + +/* This version must *not* interpret 'str' as a format string, to avoid +** several evil attacks. */ +#define XMLRPC_FAIL(env,code,str) \ + do { xmlrpc_env_set_fault((env),(code),(str)); goto cleanup; } while (0) + +#define XMLRPC_FAIL1(env,code,str,arg1) \ + do { \ + xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1)); \ + goto cleanup; \ + } while (0) + +#define XMLRPC_FAIL2(env,code,str,arg1,arg2) \ + do { \ + xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1),(arg2)); \ + goto cleanup; \ + } while (0) + +#define XMLRPC_FAIL3(env,code,str,arg1,arg2,arg3) \ + do { \ + xmlrpc_env_set_fault_formatted((env),(code), \ + (str),(arg1),(arg2),(arg3)); \ + goto cleanup; \ + } while (0) + +#if !defined(__cplusplus) +#if defined(__GNUC__) +#define XMLRPC_FAILF( env, code, fmt, ... ) \ + do { \ + xmlrpc_env_set_fault_formatted((env), (code), (fmt), \ + ##__VA_ARGS__ ); \ + goto cleanup; \ + } while (0) +#endif +#endif + +#define XMLRPC_FAIL_IF_NULL(ptr,env,code,str) \ + do { \ + if ((ptr) == NULL) \ + XMLRPC_FAIL((env),(code),(str)); \ + } while (0) + +#define XMLRPC_FAIL_IF_FAULT(env) \ + do { if ((env)->fault_occurred) goto cleanup; } while (0) + + +/*========================================================================= +** xmlrpc_mem_block +**========================================================================= +** A resizable chunk of memory. This is mostly used internally, but it is +** also used by the public API in a few places. +** The struct fields are private! +*/ + +typedef struct _xmlrpc_mem_block { + size_t _size; + size_t _allocated; + void* _block; +} xmlrpc_mem_block; + +/* Allocate a new xmlrpc_mem_block. */ +xmlrpc_mem_block* xmlrpc_mem_block_new (xmlrpc_env* const env, size_t const size); + +/* Destroy an existing xmlrpc_mem_block, and everything it contains. */ +void xmlrpc_mem_block_free (xmlrpc_mem_block* const block); + +/* Initialize the contents of the provided xmlrpc_mem_block. */ +void xmlrpc_mem_block_init + (xmlrpc_env* const env, xmlrpc_mem_block* const block, size_t const size); + +/* Deallocate the contents of the provided xmlrpc_mem_block, but not the +** block itself. */ +void xmlrpc_mem_block_clean (xmlrpc_mem_block* const block); + +/* Get the size and contents of the xmlrpc_mem_block. */ +size_t +xmlrpc_mem_block_size(const xmlrpc_mem_block * const block); + +void * +xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block); + +/* Resize an xmlrpc_mem_block, preserving as much of the contents as +** possible. */ +void xmlrpc_mem_block_resize + (xmlrpc_env* const env, xmlrpc_mem_block* const block, size_t const size); + +/* Append data to an existing xmlrpc_mem_block. */ +void xmlrpc_mem_block_append + (xmlrpc_env* const env, xmlrpc_mem_block* const block, const void * const data, size_t const len); + +#define XMLRPC_MEMBLOCK_NEW(type,env,size) \ + xmlrpc_mem_block_new((env), sizeof(type) * (size)) +#define XMLRPC_MEMBLOCK_FREE(type,block) \ + xmlrpc_mem_block_free(block) +#define XMLRPC_MEMBLOCK_INIT(type,env,block,size) \ + xmlrpc_mem_block_init((env), (block), sizeof(type) * (size)) +#define XMLRPC_MEMBLOCK_CLEAN(type,block) \ + xmlrpc_mem_block_clean(block) +#define XMLRPC_MEMBLOCK_SIZE(type,block) \ + (xmlrpc_mem_block_size(block) / sizeof(type)) +#define XMLRPC_MEMBLOCK_CONTENTS(type,block) \ + ((type*) xmlrpc_mem_block_contents(block)) +#define XMLRPC_MEMBLOCK_RESIZE(type,env,block,size) \ + xmlrpc_mem_block_resize(env, block, sizeof(type) * (size)) +#define XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size) \ + xmlrpc_mem_block_append(env, block, data, sizeof(type) * (size)) + +/* Here are some backward compatibility definitions. These longer names + used to be the only ones and typed memory blocks were considered + special. +*/ +#define XMLRPC_TYPED_MEM_BLOCK_NEW(type,env,size) \ + XMLRPC_MEMBLOCK_NEW(type,env,size) +#define XMLRPC_TYPED_MEM_BLOCK_FREE(type,block) \ + XMLRPC_MEMBLOCK_FREE(type,block) +#define XMLRPC_TYPED_MEM_BLOCK_INIT(type,env,block,size) \ + XMLRPC_MEMBLOCK_INIT(type,env,block,size) +#define XMLRPC_TYPED_MEM_BLOCK_CLEAN(type,block) \ + XMLRPC_MEMBLOCK_CLEAN(type,block) +#define XMLRPC_TYPED_MEM_BLOCK_SIZE(type,block) \ + XMLRPC_MEMBLOCK_SIZE(type,block) +#define XMLRPC_TYPED_MEM_BLOCK_CONTENTS(type,block) \ + XMLRPC_MEMBLOCK_CONTENTS(type,block) +#define XMLRPC_TYPED_MEM_BLOCK_RESIZE(type,env,block,size) \ + XMLRPC_MEMBLOCK_RESIZE(type,env,block,size) +#define XMLRPC_TYPED_MEM_BLOCK_APPEND(type,env,block,data,size) \ + XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size) + + +/*========================================================================= +** UTF-8 Encoding and Decoding +**=======================================================================*/ + +void +xmlrpc_validate_utf8(xmlrpc_env * const envP, + const char * const utf8Data, + size_t const utf8Len); + +/* Decode a UTF-8 string. */ +xmlrpc_mem_block * +xmlrpc_utf8_to_wcs(xmlrpc_env * const envP, + const char * const utf8_data, + size_t const utf8_len); + +/* Encode a UTF-8 string. */ + +#if XMLRPC_HAVE_WCHAR +xmlrpc_mem_block * +xmlrpc_wcs_to_utf8(xmlrpc_env * const envP, + const wchar_t * const wcsData, + size_t const wcsLen); +#endif + +void +xmlrpc_force_to_utf8(char * const buffer); + +void +xmlrpc_force_to_xml_chars(char * const buffer); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/util_int.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/util_int.h new file mode 100644 index 0000000..4ac3e14 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/util_int.h @@ -0,0 +1,13 @@ +#ifndef XMLRPC_C_UTIL_INT_H_INCLUDED +#define XMLRPC_C_UTIL_INT_H_INCLUDED + +#include "util.h" + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +/* When we deallocate a pointer in a struct, we often replace it with +** this and throw in a few assertions here and there. */ +#define XMLRPC_BAD_POINTER ((void*) 0xDEADBEEF) + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/xmlparser.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/xmlparser.h new file mode 100644 index 0000000..542e6c4 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/xmlparser.h @@ -0,0 +1,97 @@ +/* Copyright and license information is at the end of the file */ + +#ifndef XMLRPC_XMLPARSER_H_INCLUDED +#define XMLRPC_XMLPARSER_H_INCLUDED + +/*========================================================================= +** Abstract XML Parser Interface +**========================================================================= +** This file provides an abstract interface to the XML parser. For now, +** this interface is implemented by expat, but feel free to change it +** if necessary. +*/ + + +/*========================================================================= +** xml_element +**========================================================================= +** This data structure represents an XML element. We provide no more API +** than we'll need in xmlrpc_parse.c. +** +** The pointers returned by the various accessor methods belong to the +** xml_element structure. Do not free them, and do not use them after +** the xml_element has been destroyed. +*/ + +/* You'll need to finish defining struct _xml_element elsewhere. */ +typedef struct _xml_element xml_element; + +/* Destroy an xml_element. */ +void xml_element_free (xml_element * const elem); + +/* Return a pointer to the element's name. Do not free this pointer! +** This pointer should point to standard ASCII or UTF-8 data. */ +const char * +xml_element_name(const xml_element * const elemP); + +/* Return the xml_element's CDATA. Do not free this pointer! +** This pointer should point to standard ASCII or UTF-8 data. +** The implementation is allowed to concatenate all the CDATA in the +** element regardless of child elements. Alternatively, if there are +** any child elements, the implementation is allowed to dispose +** of whitespace characters. +** The value returned by xml_element_cdata should be '\0'-terminated +** (although it may contain other '\0' characters internally). +** xml_element_cdata_size should not include the final '\0'. */ +size_t xml_element_cdata_size (xml_element *elem); +char *xml_element_cdata (xml_element *elem); + +/* Return the xml_element's child elements. Do not free this pointer! */ +size_t +xml_element_children_size(const xml_element * const elemP); + +xml_element ** +xml_element_children(const xml_element * const elemP); + + +/*========================================================================= +** xml_parse +**========================================================================= +** Parse a chunk of XML data and return the top-level element. If this +** routine fails, it will return NULL and set up the env appropriately. +** You are responsible for calling xml_element_free on the returned pointer. +*/ + +void +xml_parse(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen, + xml_element ** const resultPP); + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/double.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/double.c new file mode 100644 index 0000000..8de8555 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/double.c @@ -0,0 +1,234 @@ +#include +#include +#include + +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/util_int.h" + +#include "double.h" + +typedef struct { + char * bytes; + char * next; + char * end; +} buffer; + + +static void +bufferInit(buffer * const bufferP) { + + unsigned int const initialSize = 64; + + bufferP->bytes = malloc(initialSize); + + if (bufferP->bytes) { + bufferP->next = bufferP->bytes; + bufferP->end = bufferP->bytes + initialSize; + } +} + + + +static void +bufferConcat(buffer * const bufferP, + char const newChar) { + + if (bufferP->bytes) { + if (bufferP->next >= bufferP->end) { + unsigned int const oldSize = bufferP->end - bufferP->bytes; + unsigned int const newSize = oldSize + 64; + bufferP->bytes = realloc(bufferP->bytes, newSize); + bufferP->next = bufferP->bytes + oldSize; + bufferP->end = bufferP->bytes + newSize; + } + + if (bufferP->bytes) + *(bufferP->next++) = newChar; + } +} + + + +static char +digitChar(unsigned int const digitValue) { + + assert(digitValue < 10); + + return '0' + digitValue; +} + + + +static unsigned int +leadDigit(double const arg, + double const precision) { +/*---------------------------------------------------------------------------- + Assuming 'arg' has one digit before the decimal point (which may be zero), + return that digit. + + We assume the precision of 'arg' is plus or minus 'precision', and bias our + estimation of the first digit up. We do that bias in order to bias toward + shorter decimal ciphers: It's cleaner to consider 2.9999999 to be 3 than to + consider 3 to be 2.999999. +-----------------------------------------------------------------------------*/ + return MIN(9, (unsigned int)(arg + precision)); +} + + + +static void +floatWhole(double const value, + buffer * const formattedP, + double * const formattedAmountP, + double * const precisionP) { + + if (value < 1.0) { + /* No digits to add to the whole part */ + *formattedAmountP = 0; + *precisionP = DBL_EPSILON; + } else { + double nonLeastAmount; + double nonLeastPrecision; + unsigned int leastValue; + + /* Add all digits but the least significant to *formattedP */ + + floatWhole(value/10.0, formattedP, &nonLeastAmount, + &nonLeastPrecision); + + /* Add the least significant digit to *formattedP */ + + if (nonLeastPrecision > 0.1) { + /* We're down in the noise now; no point in showing any more + significant digits (and we couldn't if we wanted to, because + nonLeastPrecision * 10 might be more than 10 less than + 'value'). + */ + leastValue = 0; + } else + leastValue = leadDigit(value - nonLeastAmount * 10, + nonLeastPrecision * 10); + + bufferConcat(formattedP, digitChar(leastValue)); + + *formattedAmountP = nonLeastAmount * 10 + leastValue; + *precisionP = nonLeastPrecision * 10; + } +} + + + +static void +floatFractionPart(double const value, + double const wholePrecision, + buffer * const formattedP) { +/*---------------------------------------------------------------------------- + Serialize the part that comes after the decimal point, assuming there + is something (nonzero) before the decimal point that uses up all but + 'wholePrecision' of the available precision. +-----------------------------------------------------------------------------*/ + double precision; + double d; + + assert(value < 1.0); + + for (d = value, precision = wholePrecision; + d > precision; + precision *= 10) { + + unsigned int digitValue; + + d *= 10; + digitValue = leadDigit(d, precision); + + d -= digitValue; + + assert(d < 1.0); + + bufferConcat(formattedP, digitChar(digitValue)); + } +} + + + +static void +floatFraction(double const value, + buffer * const formattedP) { +/*---------------------------------------------------------------------------- + Serialize the part that comes after the decimal point, assuming there + is nothing before the decimal point. +-----------------------------------------------------------------------------*/ + double precision; + double d; + + assert(0.0 < value && value < 1.0); + + /* Do the leading zeroes, which eat no precision */ + + for (d = value * 10; d < 1.0; d *= 10) + bufferConcat(formattedP, '0'); + + /* Now the significant digits */ + + precision = DBL_EPSILON; + + while (d > precision) { + unsigned int const digitValue = leadDigit(d, precision); + + bufferConcat(formattedP, digitChar(digitValue)); + + d -= digitValue; + + assert(d < 1.0); + + d *= 10; + precision *= 10; + } +} + + + +void +xmlrpc_formatFloat(xmlrpc_env * const envP, + double const value, + const char ** const formattedP) { + + double absvalue; + buffer formatted; + + bufferInit(&formatted); + + if (value < 0.0) { + bufferConcat(&formatted, '-'); + absvalue = - value; + } else + absvalue = value; + + if (absvalue >= 1.0) { + double wholePart, fractionPart; + double wholePrecision; + + floatWhole(absvalue, &formatted, &wholePart, &wholePrecision); + + fractionPart = absvalue - wholePart; + + if (fractionPart > wholePrecision) { + bufferConcat(&formatted, '.'); + + floatFractionPart(fractionPart, wholePrecision, &formatted); + } + } else { + bufferConcat(&formatted, '0'); + + if (absvalue > 0.0) { + bufferConcat(&formatted, '.'); + floatFraction(absvalue, &formatted); + } + } + bufferConcat(&formatted, '\0'); + + if (formatted.bytes == NULL) + xmlrpc_faultf(envP, "Couldn't allocate memory to format %g", value); + else + *formattedP = formatted.bytes; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/double.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/double.h new file mode 100644 index 0000000..dc563c2 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/double.h @@ -0,0 +1,11 @@ +#ifndef DOUBLE_H_INCLUDED +#define DOUBLE_H_INCLUDED + +#include "xmlrpc-c/util.h" + +void +xmlrpc_formatFloat(xmlrpc_env * const envP, + double const value, + const char ** const formattedP); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/parse_value.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/parse_value.c new file mode 100644 index 0000000..9b3990c --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/parse_value.c @@ -0,0 +1,757 @@ +#include "xmlrpc_config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "bool.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/xmlparser.h" + +#include "parse_value.h" + + + +static void +setParseFault(xmlrpc_env * const envP, + const char * const format, + ...) { + + va_list args; + va_start(args, format); + xmlrpc_set_fault_formatted_v(envP, XMLRPC_PARSE_ERROR, format, args); + va_end(args); +} + + + +static void +parseArrayDataChild(xmlrpc_env * const envP, + xml_element * const childP, + unsigned int const maxRecursion, + xmlrpc_value * const arrayP) { + + const char * const elemName = xml_element_name(childP); + + if (!xmlrpc_streq(elemName, "value")) + setParseFault(envP, " element has <%s> child. " + "Only makes sense.", elemName); + else { + xmlrpc_value * itemP; + + xmlrpc_parseValue(envP, maxRecursion-1, childP, &itemP); + + if (!envP->fault_occurred) { + xmlrpc_array_append_item(envP, arrayP, itemP); + + xmlrpc_DECREF(itemP); + } + } +} + + + +static void +parseArray(xmlrpc_env * const envP, + unsigned int const maxRecursion, + xml_element * const arrayElemP, + xmlrpc_value ** const arrayPP) { + + xmlrpc_value * arrayP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(arrayElemP != NULL); + + arrayP = xmlrpc_array_new(envP); + if (!envP->fault_occurred) { + unsigned int const childCount = xml_element_children_size(arrayElemP); + + if (childCount != 1) + setParseFault(envP, + " element has %u children. Only one " + "makes sense.", childCount); + else { + xml_element * const dataElemP = + xml_element_children(arrayElemP)[0]; + const char * const elemName = xml_element_name(dataElemP); + + if (!xmlrpc_streq(elemName, "data")) + setParseFault(envP, + " element has <%s> child. Only " + "makes sense.", elemName); + else { + xml_element ** const values = xml_element_children(dataElemP); + unsigned int const size = xml_element_children_size(dataElemP); + + unsigned int i; + + for (i = 0; i < size && !envP->fault_occurred; ++i) + parseArrayDataChild(envP, values[i], maxRecursion, arrayP); + } + } + if (envP->fault_occurred) + xmlrpc_DECREF(arrayP); + else + *arrayPP = arrayP; + } +} + + + +static void +parseName(xmlrpc_env * const envP, + xml_element * const nameElemP, + xmlrpc_value ** const valuePP) { + + unsigned int const childCount = xml_element_children_size(nameElemP); + + if (childCount > 0) + setParseFault(envP, " element has %u children. " + "Should have none.", childCount); + else { + const char * const cdata = xml_element_cdata(nameElemP); + size_t const cdataSize = xml_element_cdata_size(nameElemP); + + *valuePP = xmlrpc_string_new_lp(envP, cdataSize, cdata); + } +} + + + +static void +getNameChild(xmlrpc_env * const envP, + xml_element * const parentP, + xml_element * * const childPP) { + + xml_element ** const children = xml_element_children(parentP); + size_t const childCount = xml_element_children_size(parentP); + + xml_element * childP; + unsigned int i; + + for (i = 0, childP = NULL; i < childCount && !childP; ++i) { + if (xmlrpc_streq(xml_element_name(children[i]), "name")) + childP = children[i]; + } + if (!childP) + xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR, + " has no child"); + else + *childPP = childP; +} + + + +static void +getValueChild(xmlrpc_env * const envP, + xml_element * const parentP, + xml_element * * const childPP) { + + xml_element ** const children = xml_element_children(parentP); + size_t const childCount = xml_element_children_size(parentP); + + xml_element * childP; + unsigned int i; + + for (i = 0, childP = NULL; i < childCount && !childP; ++i) { + if (xmlrpc_streq(xml_element_name(children[i]), "value")) + childP = children[i]; + } + if (!childP) + xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR, + " has no child"); + else + *childPP = childP; +} + + + +static void +parseMember(xmlrpc_env * const envP, + xml_element * const memberP, + unsigned int const maxRecursion, + xmlrpc_value ** const keyPP, + xmlrpc_value ** const valuePP) { + + unsigned int const childCount = xml_element_children_size(memberP); + + if (childCount != 2) + setParseFault(envP, + " element has %u children. Only one and " + "one make sense.", childCount); + else { + xml_element * nameElemP; + + getNameChild(envP, memberP, &nameElemP); + + if (!envP->fault_occurred) { + parseName(envP, nameElemP, keyPP); + + if (!envP->fault_occurred) { + xml_element * valueElemP; + + getValueChild(envP, memberP, &valueElemP); + + if (!envP->fault_occurred) + xmlrpc_parseValue(envP, maxRecursion-1, valueElemP, + valuePP); + + if (envP->fault_occurred) + xmlrpc_DECREF(*keyPP); + } + } + } +} + + + +static void +parseStruct(xmlrpc_env * const envP, + unsigned int const maxRecursion, + xml_element * const elemP, + xmlrpc_value ** const structPP) { +/*---------------------------------------------------------------------------- + Parse the element 'elemP'. +-----------------------------------------------------------------------------*/ + xmlrpc_value * structP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(elemP != NULL); + + structP = xmlrpc_struct_new(envP); + if (!envP->fault_occurred) { + /* Iterate over our children, extracting key/value pairs. */ + + xml_element ** const members = xml_element_children(elemP); + unsigned int const size = xml_element_children_size(elemP); + + unsigned int i; + + for (i = 0; i < size && !envP->fault_occurred; ++i) { + const char * const elemName = xml_element_name(members[i]); + + if (!xmlrpc_streq(elemName, "member")) + setParseFault(envP, "<%s> element found where only " + "makes sense", elemName); + else { + xmlrpc_value * keyP; + xmlrpc_value * valueP; + + parseMember(envP, members[i], maxRecursion, &keyP, &valueP); + + if (!envP->fault_occurred) { + xmlrpc_struct_set_value_v(envP, structP, keyP, valueP); + + xmlrpc_DECREF(keyP); + xmlrpc_DECREF(valueP); + } + } + } + if (envP->fault_occurred) + xmlrpc_DECREF(structP); + else + *structPP = structP; + } +} + + + +static void +parseInt(xmlrpc_env * const envP, + const char * const str, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Parse the content of a XML-RPC XML element, e.g. "34". + + 'str' is that content. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(str); + + if (str[0] == '\0') + setParseFault(envP, " XML element content is empty"); + else if (isspace(str[0])) + setParseFault(envP, " content '%s' starts with white space", + str); + else { + long i; + char * tail; + + errno = 0; + i = strtol(str, &tail, 10); + + /* Look for ERANGE. */ + if (errno == ERANGE) + setParseFault(envP, " XML element value '%s' represents a " + "number beyond the range that " + "XML-RPC allows (%d - %d)", str, + XMLRPC_INT32_MIN, XMLRPC_INT32_MAX); + else if (errno != 0) + setParseFault(envP, "unexpected error parsing XML element " + "value '%s'. strtol() failed with errno %d (%s)", + str, errno, strerror(errno)); + else { + /* Look for out-of-range errors which didn't produce ERANGE. */ + if (i < XMLRPC_INT32_MIN) + setParseFault(envP, + " value %d is below the range allowed " + "by XML-RPC (minimum is %d)", + i, XMLRPC_INT32_MIN); + else if (i > XMLRPC_INT32_MAX) + setParseFault(envP, + " value %d is above the range allowed " + "by XML-RPC (maximum is %d)", + i, XMLRPC_INT32_MAX); + else { + if (tail[0] != '\0') + setParseFault(envP, + " value '%s' contains non-numerical " + "junk: '%s'", str, tail); + else + *valuePP = xmlrpc_int_new(envP, i); + } + } + } +} + + + +static void +parseBoolean(xmlrpc_env * const envP, + const char * const str, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Parse the content of a XML-RPC XML element, e.g. "1". + + 'str' is that content. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(str); + + if (xmlrpc_streq(str, "0") || xmlrpc_streq(str, "1")) + *valuePP = xmlrpc_bool_new(envP, xmlrpc_streq(str, "1") ? 1 : 0); + else + setParseFault(envP, " XML element content must be either " + "'0' or '1' according to XML-RPC. This one has '%s'", + str); +} + + + +static void +scanAndValidateDoubleString(xmlrpc_env * const envP, + const char * const string, + const char ** const mantissaP, + const char ** const mantissaEndP, + const char ** const fractionP, + const char ** const fractionEndP) { + + const char * mantissa; + const char * dp; + const char * p; + + if (string[0] == '-' || string[0] == '+') + mantissa = &string[1]; + else + mantissa = &string[0]; + + for (p = mantissa, dp = NULL; *p; ++p) { + char const c = *p; + if (c == '.') { + if (dp) { + setParseFault(envP, "Two decimal points"); + return; + } else + dp = p; + } else if (c < '0' || c > '9') { + setParseFault(envP, "Garbage (not sign, digit, or period) " + "starting at '%s'", p); + return; + } + } + *mantissaP = mantissa; + if (dp) { + *mantissaEndP = dp; + *fractionP = dp+1; + *fractionEndP = p; + } else { + *mantissaEndP = p; + *fractionP = p; + *fractionEndP = p; + } +} + + + +static bool +isInfinite(double const value) { + + return value > DBL_MAX; +} + + + +static void +parseDoubleString(xmlrpc_env * const envP, + const char * const string, + double * const valueP) { +/*---------------------------------------------------------------------------- + Turn e.g. "4.3" into 4.3 . +-----------------------------------------------------------------------------*/ + /* strtod() is no good for this because it is designed for human + interfaces; it parses according to locale. As a practical + matter that sometimes means that it does not recognize "." as a + decimal point. In XML-RPC, "." is a decimal point. + + Design note: in my experiments, using strtod() was 10 times + slower than using this function. + */ + const char * mantissa; + const char * mantissaEnd; + const char * fraction; + const char * fractionEnd; + + scanAndValidateDoubleString(envP, string, &mantissa, &mantissaEnd, + &fraction, &fractionEnd); + + if (!envP->fault_occurred) { + double accum; + + accum = 0.0; + + if (mantissa == mantissaEnd && fraction == fractionEnd) { + setParseFault(envP, "No digits"); + return; + } + { + /* Add in the whole part */ + const char * p; + + for (p = mantissa; p < mantissaEnd; ++p) { + accum *= 10; + accum += (*p - '0'); + } + } + { + /* Add in the fractional part */ + double significance; + const char * p; + for (significance = 0.1, p = fraction; + p < fractionEnd; + ++p, significance *= 0.1) { + + accum += (*p - '0') * significance; + } + } + if (isInfinite(accum)) + setParseFault(envP, "Value exceeds the size allowed by XML-RPC"); + else + *valueP = string[0] == '-' ? (- accum) : accum; + } +} + + + +static void +parseDoubleStringStrtod(const char * const str, + bool * const failedP, + double * const valueP) { + + if (strlen(str) == 0) { + /* strtod() happily interprets empty string as 0.0. We don't think + the user will appreciate that XML-RPC extension. + */ + *failedP = true; + } else { + char * tail; + + errno = 0; + + *valueP = strtod(str, &tail); + + if (errno != 0) + *failedP = true; + else { + if (tail[0] != '\0') + *failedP = true; + else + *failedP = false; + } + } +} + + + +static void +parseDouble(xmlrpc_env * const envP, + const char * const str, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Parse the content of a XML-RPC XML element, e.g. "34.5". + + 'str' is that content. +-----------------------------------------------------------------------------*/ + xmlrpc_env parseEnv; + double valueDouble; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(str); + + xmlrpc_env_init(&parseEnv); + + parseDoubleString(&parseEnv, str, &valueDouble); + + if (parseEnv.fault_occurred) { + /* As an alternative, try a strtod() parsing. strtod() + accepts other forms, e.g. "3.4E6"; "3,4"; " 3.4". These + are not permitted by XML-RPC, but an almost-XML-RPC partner + might use one. In fact, for many years, Xmlrpc-c generated + such alternatives (by mistake). + */ + bool failed; + parseDoubleStringStrtod(str, &failed, &valueDouble); + if (failed) + setParseFault(envP, " element value '%s' is not a valid " + "floating point number. %s", + str, parseEnv.fault_string); + } + + if (!envP->fault_occurred) + *valuePP = xmlrpc_double_new(envP, valueDouble); + + xmlrpc_env_clean(&parseEnv); +} + + + +static void +parseBase64(xmlrpc_env * const envP, + const char * const str, + size_t const strLength, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Parse the content of a XML-RPC XML element, e.g. "FD32YY". + + 'str' is that content. +-----------------------------------------------------------------------------*/ + xmlrpc_mem_block * decoded; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(str); + + decoded = xmlrpc_base64_decode(envP, str, strLength); + if (!envP->fault_occurred) { + unsigned char * const bytes = + XMLRPC_MEMBLOCK_CONTENTS(unsigned char, decoded); + size_t const byteCount = + XMLRPC_MEMBLOCK_SIZE(unsigned char, decoded); + + *valuePP = xmlrpc_base64_new(envP, byteCount, bytes); + + XMLRPC_MEMBLOCK_FREE(unsigned char, decoded); + } +} + + + +static void +parseI8(xmlrpc_env * const envP, + const char * const str, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Parse the content of a XML-RPC XML element, e.g. "34". + + 'str' is that content. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(str); + + if (str[0] == '\0') + setParseFault(envP, " XML element content is empty"); + else if (isspace(str[0])) + setParseFault(envP, + " content '%s' starts with white space", str); + else { + xmlrpc_int64 i; + char * tail; + + errno = 0; + i = strtoll(str, &tail, 10); + + if (errno == ERANGE) + setParseFault(envP, " XML element value '%s' represents a " + "number beyond the range that " + "XML-RPC allows (%d - %d)", str, + XMLRPC_INT64_MIN, XMLRPC_INT64_MAX); + else if (errno != 0) + setParseFault(envP, "unexpected error parsing XML element " + "value '%s'. strtoll() failed with errno %d (%s)", + str, errno, strerror(errno)); + else { + /* Look for out-of-range errors which didn't produce ERANGE. */ + if (i < XMLRPC_INT64_MIN) + setParseFault(envP, " value %d is below the range allowed " + "by XML-RPC (minimum is %d)", + i, XMLRPC_INT64_MIN); + else if (i > XMLRPC_INT64_MAX) + setParseFault(envP, " value %d is above the range allowed " + "by XML-RPC (maximum is %d)", + i, XMLRPC_INT64_MAX); + else { + if (tail[0] != '\0') + setParseFault(envP, + " value '%s' contains non-numerical " + "junk: '%s'", str, tail); + else + *valuePP = xmlrpc_i8_new(envP, i); + } + } + } +} + + + +static void +parseSimpleValueCdata(xmlrpc_env * const envP, + const char * const elementName, + const char * const cdata, + size_t const cdataLength, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Parse an XML element is supposedly a data type element such as + . Its name is 'elementName', and it has no children, but + contains cdata 'cdata', which is 'dataLength' characters long. +-----------------------------------------------------------------------------*/ + /* We need to straighten out the whole character set / encoding thing + some day. What is 'cdata', and what should it be? Does it have + embedded NUL? Some of the code here assumes it doesn't. Is it + text? + + The parser assumes it's UTF 8 with embedded NULs. + But the parser will get terribly confused if there are any + UTF-8 multibyte sequences or NUL characters. So will most of the + others. + + The "ex:XXX" element names are what the Apache XML-RPC facility + uses: http://ws.apache.org/xmlrpc/types.html. (Technically, it + isn't "ex" but an arbitrary prefix that identifies a namespace + declared earlier in the XML document -- this is an XML thing. + But we aren't nearly sophisticated enough to use real XML + namespaces, so we exploit the fact that XML-RPC actually uses + "ex"). + + "i1" and "i2" are just from my imagination. + */ + + if (xmlrpc_streq(elementName, "int") || + xmlrpc_streq(elementName, "i4") || + xmlrpc_streq(elementName, "i1") || + xmlrpc_streq(elementName, "i2") || + xmlrpc_streq(elementName, "ex:i1") || + xmlrpc_streq(elementName, "ex:i2")) + parseInt(envP, cdata, valuePP); + else if (xmlrpc_streq(elementName, "boolean")) + parseBoolean(envP, cdata, valuePP); + else if (xmlrpc_streq(elementName, "double")) + parseDouble(envP, cdata, valuePP); + else if (xmlrpc_streq(elementName, "dateTime.iso8601")) + *valuePP = xmlrpc_datetime_new_str(envP, cdata); + else if (xmlrpc_streq(elementName, "string")) + *valuePP = xmlrpc_string_new_lp(envP, cdataLength, cdata); + else if (xmlrpc_streq(elementName, "base64")) + parseBase64(envP, cdata, cdataLength, valuePP); + else if (xmlrpc_streq(elementName, "nil") || + xmlrpc_streq(elementName, "ex:nil")) + *valuePP = xmlrpc_nil_new(envP); + else if (xmlrpc_streq(elementName, "i8") || + xmlrpc_streq(elementName, "ex:i8")) + parseI8(envP, cdata, valuePP); + else + setParseFault(envP, "Unknown value type -- XML element is named " + "<%s>", elementName); +} + + + +static void +parseSimpleValue(xmlrpc_env * const envP, + xml_element * const elemP, + xmlrpc_value ** const valuePP) { + + unsigned int const childCount = xml_element_children_size(elemP); + + if (childCount > 0) + setParseFault(envP, "The child of a element " + "is neither nor , " + "but has %u child elements of its own.", + childCount); + else { + const char * const elemName = xml_element_name(elemP); + const char * const cdata = xml_element_cdata(elemP); + size_t const cdataSize = xml_element_cdata_size(elemP); + + parseSimpleValueCdata(envP, elemName, cdata, cdataSize, valuePP); + } +} + + + +void +xmlrpc_parseValue(xmlrpc_env * const envP, + unsigned int const maxRecursion, + xml_element * const elemP, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Compute the xmlrpc_value represented by the XML element 'elem'. + Return that xmlrpc_value. + + We call convert_array() and convert_struct(), which may ultimately + call us recursively. Don't recurse any more than 'maxRecursion' + times. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(elemP != NULL); + + /* Assume we'll need to recurse, make sure we're allowed */ + if (maxRecursion < 1) + xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR, + "Nested data structure too deep."); + else { + if (!xmlrpc_streq(xml_element_name(elemP), "value")) + setParseFault(envP, + "<%s> element where expected", + xml_element_name(elemP)); + else { + unsigned int const childCount = xml_element_children_size(elemP); + + if (childCount == 0) { + /* We have no type element, so treat the value as a string. */ + char * const cdata = xml_element_cdata(elemP); + size_t const cdata_size = xml_element_cdata_size(elemP); + *valuePP = xmlrpc_string_new_lp(envP, cdata_size, cdata); + } else if (childCount > 1) + setParseFault(envP, " has %u child elements. " + "Only zero or one make sense.", childCount); + else { + /* We should have a type tag inside our value tag. */ + xml_element * const childP = xml_element_children(elemP)[0]; + const char * const childName = xml_element_name(childP); + + if (xmlrpc_streq(childName, "struct")) + parseStruct(envP, maxRecursion, childP, valuePP); + else if (xmlrpc_streq(childName, "array")) + parseArray(envP, maxRecursion, childP, valuePP); + else + parseSimpleValue(envP, childP, valuePP); + } + } + } +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/parse_value.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/parse_value.h new file mode 100644 index 0000000..9cf3719 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/parse_value.h @@ -0,0 +1,13 @@ +#ifndef PARSE_VALUE_H_INCLUDED +#define PARSE_VALUE_H_INCLUDED + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/xmlparser.h" + +void +xmlrpc_parseValue(xmlrpc_env * const envP, + unsigned int const maxRecursion, + xml_element * const elemP, + xmlrpc_value ** const valuePP); + +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/resource.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/resource.c new file mode 100644 index 0000000..bed48a0 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/resource.c @@ -0,0 +1,31 @@ +#include "xmlrpc_config.h" + +#include "xmlrpc-c/base.h" + + +/*========================================================================= +** Resource Limits +**========================================================================= +*/ + +static size_t limits[XMLRPC_LAST_LIMIT_ID + 1] = { + XMLRPC_NESTING_LIMIT_DEFAULT, + XMLRPC_XML_SIZE_LIMIT_DEFAULT +}; + +void +xmlrpc_limit_set (int const limit_id, + size_t const value) { + + XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID); + limits[limit_id] = value; +} + + + +size_t +xmlrpc_limit_get(int const limit_id) { + + XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID); + return limits[limit_id]; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/trace.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/trace.c new file mode 100644 index 0000000..53d54f3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/trace.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" + + +static size_t +nextLineSize(const char * const string, + size_t const startPos, + size_t const stringSize) { +/*---------------------------------------------------------------------------- + Return the length of the line that starts at offset 'startPos' in the + string 'string', which is 'stringSize' characters long. + + 'string' in not NUL-terminated. + + A line begins at beginning of string or after a newline character and + runs through the next newline character or end of string. The line + includes the newline character at the end, if any. +-----------------------------------------------------------------------------*/ + size_t i; + + for (i = startPos; i < stringSize && string[i] != '\n'; ++i); + + if (i < stringSize) + ++i; /* Include the newline */ + + return i - startPos; +} + + + +void +xmlrpc_traceXml(const char * const label, + const char * const xml, + unsigned int const xmlLength) { + + if (getenv("XMLRPC_TRACE_XML")) { + size_t cursor; /* Index into xml[] */ + + fprintf(stderr, "%s:\n\n", label); + + for (cursor = 0; cursor < xmlLength; ) { + /* Print one line of XML */ + + size_t const lineSize = nextLineSize(xml, cursor, xmlLength); + const char * const xmlPrintableLine = + xmlrpc_makePrintable_lp(&xml[cursor], lineSize); + + fprintf(stderr, "%s\n", xmlPrintableLine); + + cursor += lineSize; + + xmlrpc_strfree(xmlPrintableLine); + } + fprintf(stderr, "\n"); + } +} + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/version.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/version.c new file mode 100644 index 0000000..c286966 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/version.c @@ -0,0 +1,7 @@ +#include "version.h" + +#include "xmlrpc-c/base.h" + +unsigned int const xmlrpc_version_major = XMLRPC_VERSION_MAJOR; +unsigned int const xmlrpc_version_minor = XMLRPC_VERSION_MINOR; +unsigned int const xmlrpc_version_point = XMLRPC_VERSION_POINT; diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_array.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_array.c new file mode 100644 index 0000000..a474546 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_array.c @@ -0,0 +1,227 @@ +/* Copyright information is at the end of the file */ + +/*========================================================================= +** XML-RPC Array Functions +**========================================================================= +*/ + +#include "xmlrpc_config.h" + +#include +#include + +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" + + + +void +xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP) { + + if (arrayP == NULL) + abort(); + else if (arrayP->_type != XMLRPC_TYPE_ARRAY) + abort(); + else { + unsigned int const arraySize = + XMLRPC_MEMBLOCK_SIZE(xmlrpc_value*, &arrayP->_block); + xmlrpc_value ** const contents = + XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block); + + if (contents == NULL) + abort(); + else { + unsigned int index; + + for (index = 0; index < arraySize; ++index) { + xmlrpc_value * const itemP = contents[index]; + if (itemP == NULL) + abort(); + else if (itemP->_refcount < 1) + abort(); + } + } + } +} + + + +void +xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP) { +/*---------------------------------------------------------------------------- + Dispose of the contents of an array (but not the array value itself). + The value is not valid after this. +-----------------------------------------------------------------------------*/ + unsigned int const arraySize = + XMLRPC_MEMBLOCK_SIZE(xmlrpc_value*, &arrayP->_block); + xmlrpc_value ** const contents = + XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block); + + unsigned int index; + + XMLRPC_ASSERT_ARRAY_OK(arrayP); + + /* Release our reference to each item in the array */ + for (index = 0; index < arraySize; ++index) { + xmlrpc_value * const itemP = contents[index]; + xmlrpc_DECREF(itemP); + } + XMLRPC_MEMBLOCK_CLEAN(xmlrpc_value *, &arrayP->_block); +} + + + +int +xmlrpc_array_size(xmlrpc_env * const env, + const xmlrpc_value * const array) { + + int retval; + + /* Suppress a compiler warning about uninitialized variables. */ + retval = 0; + + XMLRPC_ASSERT_ENV_OK(env); + XMLRPC_ASSERT_VALUE_OK(array); + XMLRPC_TYPE_CHECK(env, array, XMLRPC_TYPE_ARRAY); + + retval = XMLRPC_TYPED_MEM_BLOCK_SIZE(xmlrpc_value*, &array->_block); + + cleanup: + if (env->fault_occurred) + return -1; + else + return retval; +} + + + +void +xmlrpc_array_append_item(xmlrpc_env * const envP, + xmlrpc_value * const arrayP, + xmlrpc_value * const valueP) { + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(arrayP); + + if (xmlrpc_value_type(arrayP) != XMLRPC_TYPE_ARRAY) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value is not an array"); + else { + size_t const size = + XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block); + + XMLRPC_MEMBLOCK_RESIZE(xmlrpc_value *, envP, &arrayP->_block, size+1); + + if (!envP->fault_occurred) { + xmlrpc_value ** const contents = + XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block); + xmlrpc_INCREF(valueP); + contents[size] = valueP; + } + } +} + + + +void +xmlrpc_array_read_item(xmlrpc_env * const envP, + const xmlrpc_value * const arrayP, + unsigned int const index, + xmlrpc_value ** const valuePP) { + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(arrayP); + XMLRPC_ASSERT_PTR_OK(valuePP); + + if (arrayP->_type != XMLRPC_TYPE_ARRAY) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Attempt to read array item from " + "a value that is not an array"); + else { + xmlrpc_value ** const contents = + XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value *, &arrayP->_block); + size_t const size = + XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block); + + if (index >= size) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, "Array index %u is beyond end " + "of %u-item array", index, (unsigned int)size); + else { + *valuePP = contents[index]; + xmlrpc_INCREF(*valuePP); + } + } +} + + + +xmlrpc_value * +xmlrpc_array_get_item(xmlrpc_env * const envP, + const xmlrpc_value * const arrayP, + int const index) { + + xmlrpc_value * valueP; + + if (index < 0) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, "Index %d is negative.", index); + else { + xmlrpc_array_read_item(envP, arrayP, index, &valueP); + + if (!envP->fault_occurred) + xmlrpc_DECREF(valueP); + } + if (envP->fault_occurred) + valueP = NULL; + + return valueP; +} + + + +xmlrpc_value * +xmlrpc_array_new(xmlrpc_env * const envP) { +/*---------------------------------------------------------------------------- + Create an empty array xmlrpc_value. +-----------------------------------------------------------------------------*/ + xmlrpc_value * arrayP; + + xmlrpc_createXmlrpcValue(envP, &arrayP); + if (!envP->fault_occurred) { + arrayP->_type = XMLRPC_TYPE_ARRAY; + XMLRPC_MEMBLOCK_INIT(xmlrpc_value*, envP, &arrayP->_block, 0); + if (envP->fault_occurred) + free(arrayP); + } + return arrayP; +} + + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** Copyright (C) 2001 by Eric Kidd. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_authcookie.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_authcookie.c new file mode 100644 index 0000000..ae6bb85 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_authcookie.c @@ -0,0 +1,85 @@ +/* Copyright (C) 2002 by jeff@ourexchange.net. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#include "xmlrpc_config.h" + +#include +#include +#include + +#include "mallocvar.h" +#include "xmlrpc-c/base.h" + +/***************************************************************************** + I don't see how these were expected to be used. And I probably + broke it somehow at some point by removing code from somewhere else. + But I doubt that, whatever it's supposed to do, environment + variables are the right tool. + + Note that on a platform that doesn't have SETENV, + xmlrpc_authcookie_set() is just a no-op. + + -Bryan 2005.06.10 +****************************************************************************/ + +void +xmlrpc_authcookie_set(xmlrpc_env * const envP, + const char * const username, + const char * const password) { + + char * unencoded; + xmlrpc_mem_block * token; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(username); + XMLRPC_ASSERT_PTR_OK(password); + + /* Create unencoded string/hash. */ + + MALLOCARRAY(unencoded,(strlen(username) + strlen(password) + 1 + 1)); + sprintf(unencoded, "%s:%s", username, password); + + /* Create encoded string. */ + token = xmlrpc_base64_encode_without_newlines( + envP, (unsigned char *)unencoded, strlen(unencoded)); + if (!envP->fault_occurred) { + /* Set HTTP_COOKIE_AUTH to the character representation of the + encoded string. + */ +#if HAVE_SETENV + setenv("HTTP_COOKIE_AUTH", + XMLRPC_MEMBLOCK_CONTENTS(char, token), + 1); +#endif + xmlrpc_mem_block_free(token); + } + free(unencoded); +} + + + +char *xmlrpc_authcookie ( void ) { + return getenv("HTTP_COOKIE_AUTH"); +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_base64.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_base64.c new file mode 100644 index 0000000..2f54377 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_base64.c @@ -0,0 +1,266 @@ +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** There is more copyright information in the bottom half of this file. +** Please see it for more details. */ + + +/*========================================================================= +** XML-RPC Base64 Utilities +**========================================================================= +** This code was swiped from Jack Jansen's code in Python 1.5.2 and +** modified to work with our data types. +*/ + +#include "xmlrpc_config.h" + +#include "xmlrpc-c/base.h" + +#define CRLF "\015\012" +#define CR '\015' +#define LF '\012' + + +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI or Corporation for National Research Initiatives or +CNRI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +While CWI is the initial source for this software, a modified version +is made available by the Corporation for National Research Initiatives +(CNRI) at the Internet address ftp://ftp.python.org. + +STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH +CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +static char table_a2b_base64[] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, /* Note PAD->0 */ + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; + +#define BASE64_PAD '=' +#define BASE64_MAXBIN 57 /* Max binary chunk size (76 char line) */ +#define BASE64_LINE_SZ 128 /* Buffer size for a single line. */ + +static unsigned char table_b2a_base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static xmlrpc_mem_block * +xmlrpc_base64_encode_internal (xmlrpc_env *env, + unsigned char *bin_data, + size_t bin_len, + int want_newlines) +{ + size_t chunk_start, chunk_left; + unsigned char *ascii_data; + int leftbits; + unsigned char this_ch; + unsigned int leftchar; + xmlrpc_mem_block *output; + unsigned char line_buffer[BASE64_LINE_SZ]; + + /* Create a block to hold our lines when we finish them. */ + output = xmlrpc_mem_block_new(env, 0); + XMLRPC_FAIL_IF_FAULT(env); + + /* Deal with empty data blocks gracefully. Yuck. */ + if (bin_len == 0) { + if (want_newlines) + XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, CRLF, 2); + goto cleanup; + } + + /* Process our binary data in line-sized chunks. */ + for (chunk_start=0; chunk_start < bin_len; chunk_start += BASE64_MAXBIN) { + + /* Set up our per-line state. */ + ascii_data = &line_buffer[0]; + chunk_left = bin_len - chunk_start; + if (chunk_left > BASE64_MAXBIN) + chunk_left = BASE64_MAXBIN; + leftbits = 0; + leftchar = 0; + + for(; chunk_left > 0; chunk_left--, bin_data++) { + /* Shift the data into our buffer */ + leftchar = (leftchar << 8) | *bin_data; + leftbits += 8; + + /* See if there are 6-bit groups ready */ + while (leftbits >= 6) { + this_ch = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + *ascii_data++ = table_b2a_base64[this_ch]; + } + } + if (leftbits == 2) { + *ascii_data++ = table_b2a_base64[(leftchar&3) << 4]; + *ascii_data++ = BASE64_PAD; + *ascii_data++ = BASE64_PAD; + } else if (leftbits == 4) { + *ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2]; + *ascii_data++ = BASE64_PAD; + } + + /* Append a courtesy CRLF. */ + if (want_newlines) { + *ascii_data++ = CR; + *ascii_data++ = LF; + } + + /* Save our line. */ + XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, line_buffer, + ascii_data - &line_buffer[0]); + XMLRPC_FAIL_IF_FAULT(env); + } + + cleanup: + if (env->fault_occurred) { + if (output) + xmlrpc_mem_block_free(output); + return NULL; + } + return output; +} + + +xmlrpc_mem_block * +xmlrpc_base64_encode (xmlrpc_env *env, unsigned char *bin_data, size_t bin_len) +{ + return xmlrpc_base64_encode_internal(env, bin_data, bin_len, 1); +} + + +xmlrpc_mem_block * +xmlrpc_base64_encode_without_newlines (xmlrpc_env *env, + unsigned char *bin_data, + size_t bin_len) +{ + return xmlrpc_base64_encode_internal(env, bin_data, bin_len, 0); +} + + +xmlrpc_mem_block * +xmlrpc_base64_decode (xmlrpc_env * const env, + const char * const ascii_data, + size_t const ascii_len) { + + unsigned char *bin_data; + int leftbits; + unsigned char this_ch; + unsigned int leftchar; + size_t npad; + size_t bin_len, buffer_size; + xmlrpc_mem_block *output; + const char * next_char; + size_t remaining_len; + + /* Create a block to hold our chunks when we finish them. + ** We overestimate the size now, and fix it later. */ + buffer_size = ((ascii_len+3)/4)*3; + output = xmlrpc_mem_block_new(env, buffer_size); + XMLRPC_FAIL_IF_FAULT(env); + + /* Set up our decoder state. */ + leftbits = 0; + leftchar = 0; + npad = 0; + bin_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(unsigned char, output); + bin_len = 0; + + for (remaining_len = ascii_len, next_char = ascii_data; + remaining_len > 0; + --remaining_len, ++next_char) { + + /* Skip some punctuation. */ + this_ch = (*next_char & 0x7f); + if ( this_ch == '\r' || this_ch == '\n' || this_ch == ' ' ) + continue; + if ( this_ch == BASE64_PAD ) + npad++; + this_ch = table_a2b_base64[(*next_char) & 0x7f]; + + /* XXX - We just throw away invalid characters. Is this right? */ + if ( this_ch == (unsigned char) -1 ) continue; + + /* Shift it in on the low end, and see if there's + ** a byte ready for output. */ + leftchar = (leftchar << 6) | (this_ch); + leftbits += 6; + if ( leftbits >= 8 ) { + leftbits -= 8; + XMLRPC_ASSERT(bin_len < buffer_size); + *bin_data++ = (leftchar >> leftbits) & 0xFF; + leftchar &= ((1 << leftbits) - 1); + bin_len++; + } + } + + /* Check that no bits are left. */ + if ( leftbits ) + XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR, "Incorrect Base64 padding"); + + /* Check to make sure we have a sane amount of padding. */ + if (npad > bin_len || npad > 2) + XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR, "Malformed Base64 data"); + + /* Remove any padding and set the correct size. */ + bin_len -= npad; + XMLRPC_TYPED_MEM_BLOCK_RESIZE(char, env, output, bin_len); + XMLRPC_ASSERT(!env->fault_occurred); + + cleanup: + if (env->fault_occurred) { + if (output) + xmlrpc_mem_block_free(output); + return NULL; + } + return output; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_build.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_build.c new file mode 100644 index 0000000..19e2a55 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_build.c @@ -0,0 +1,438 @@ +/* Copyright information is at end of file */ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include + +#include "bool.h" +#include "c_util.h" +#include "mallocvar.h" +#include "stdargx.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" + + +/*========================================================================= +** Creating XML-RPC values. +**========================================================================= +** Build new XML-RPC values from a format string. This code is heavily +** inspired by Py_BuildValue from Python 1.5.2. In particular, our +** particular abuse of the va_list data type is copied from the equivalent +** Python code in modsupport.c. Since Python is portable, our code should +** (in theory) also be portable. +*/ + + +static void +getString(xmlrpc_env * const envP, + const char ** const formatP, + va_listx * const argsP, + xmlrpc_value ** const valPP) { + + const char * str; + unsigned int len; + + str = (const char*) va_arg(argsP->v, char*); + if (**formatP == '#') { + (*formatP)++; + len = (size_t) va_arg(argsP->v, size_t); + } else + len = strlen(str); + + *valPP = xmlrpc_string_new_lp(envP, len, str); +} + + + +static void +getWideString(xmlrpc_env * const envP ATTR_UNUSED, + const char ** const formatP ATTR_UNUSED, + va_listx * const argsP ATTR_UNUSED, + xmlrpc_value ** const valPP ATTR_UNUSED) { + +#if HAVE_UNICODE_WCHAR + wchar_t *wcs; + size_t len; + + wcs = (wchar_t*) va_arg(argsP->v, wchar_t*); + if (**formatP == '#') { + (*formatP)++; + len = (size_t) va_arg(argsP->v, size_t); + } else + len = wcslen(wcs); + + *valPP = xmlrpc_string_w_new_lp(envP, len, wcs); + +#endif /* HAVE_UNICODE_WCHAR */ +} + + + +static void +getBase64(xmlrpc_env * const envP, + va_listx * const argsP, + xmlrpc_value ** const valPP) { + + unsigned char * value; + size_t length; + + value = (unsigned char*) va_arg(argsP->v, unsigned char*); + length = (size_t) va_arg(argsP->v, size_t); + + *valPP = xmlrpc_base64_new(envP, length, value); +} + + + +static void +getValue(xmlrpc_env * const envP, + const char** const format, + va_listx * const argsP, + xmlrpc_value ** const valPP); + + + +static void +getArray(xmlrpc_env * const envP, + const char ** const formatP, + char const delimiter, + va_listx * const argsP, + xmlrpc_value ** const arrayPP) { + + xmlrpc_value * arrayP; + + arrayP = xmlrpc_array_new(envP); + + /* Add items to the array until we hit our delimiter. */ + + while (**formatP != delimiter && !envP->fault_occurred) { + + xmlrpc_value * itemP; + + if (**formatP == '\0') + xmlrpc_env_set_fault( + envP, XMLRPC_INTERNAL_ERROR, + "format string ended before closing ')'."); + else { + getValue(envP, formatP, argsP, &itemP); + if (!envP->fault_occurred) { + xmlrpc_array_append_item(envP, arrayP, itemP); + xmlrpc_DECREF(itemP); + } + } + } + if (envP->fault_occurred) + xmlrpc_DECREF(arrayP); + + *arrayPP = arrayP; +} + + + +static void +getStructMember(xmlrpc_env * const envP, + const char ** const formatP, + va_listx * const argsP, + xmlrpc_value ** const keyPP, + xmlrpc_value ** const valuePP) { + + + /* Get the key */ + getValue(envP, formatP, argsP, keyPP); + if (!envP->fault_occurred) { + if (**formatP != ':') + xmlrpc_env_set_fault( + envP, XMLRPC_INTERNAL_ERROR, + "format string does not have ':' after a " + "structure member key."); + else { + /* Skip over colon that separates key from value */ + (*formatP)++; + + /* Get the value */ + getValue(envP, formatP, argsP, valuePP); + } + if (envP->fault_occurred) + xmlrpc_DECREF(*keyPP); + } +} + + + +static void +getStruct(xmlrpc_env * const envP, + const char ** const formatP, + char const delimiter, + va_listx * const argsP, + xmlrpc_value ** const structPP) { + + xmlrpc_value * structP; + + structP = xmlrpc_struct_new(envP); + if (!envP->fault_occurred) { + while (**formatP != delimiter && !envP->fault_occurred) { + xmlrpc_value * keyP; + xmlrpc_value * valueP; + + getStructMember(envP, formatP, argsP, &keyP, &valueP); + + if (!envP->fault_occurred) { + if (**formatP == ',') + (*formatP)++; /* Skip over the comma */ + else if (**formatP == delimiter) { + /* End of the line */ + } else + xmlrpc_env_set_fault( + envP, XMLRPC_INTERNAL_ERROR, + "format string does not have ',' or ')' after " + "a structure member"); + + if (!envP->fault_occurred) + /* Add the new member to the struct. */ + xmlrpc_struct_set_value_v(envP, structP, keyP, valueP); + + xmlrpc_DECREF(valueP); + xmlrpc_DECREF(keyP); + } + } + if (envP->fault_occurred) + xmlrpc_DECREF(structP); + } + *structPP = structP; +} + + + +static void +mkArrayFromVal(xmlrpc_env * const envP, + xmlrpc_value * const value, + xmlrpc_value ** const valPP) { + + if (xmlrpc_value_type(value) != XMLRPC_TYPE_ARRAY) + xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, + "Array format ('A'), non-array xmlrpc_value"); + else + xmlrpc_INCREF(value); + + *valPP = value; +} + + + +static void +mkStructFromVal(xmlrpc_env * const envP, + xmlrpc_value * const value, + xmlrpc_value ** const valPP) { + + if (xmlrpc_value_type(value) != XMLRPC_TYPE_STRUCT) + xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, + "Struct format ('S'), non-struct xmlrpc_value"); + else + xmlrpc_INCREF(value); + + *valPP = value; +} + + + +static void +getValue(xmlrpc_env * const envP, + const char** const formatP, + va_listx * const argsP, + xmlrpc_value ** const valPP) { +/*---------------------------------------------------------------------------- + Get the next value from the list. *formatP points to the specifier + for the next value in the format string (i.e. to the type code + character) and we move *formatP past the whole specifier for the + next value. We read the required arguments from 'argsP'. We return + the value as *valPP with a reference to it. + + For example, if *formatP points to the "i" in the string "sis", + we read one argument from 'argsP' and return as *valP an integer whose + value is the argument we read. We advance *formatP to point to the + last 's' and advance 'argsP' to point to the argument that belongs to + that 's'. +-----------------------------------------------------------------------------*/ + char const formatChar = *(*formatP)++; + + switch (formatChar) { + case 'i': + *valPP = + xmlrpc_int_new(envP, (xmlrpc_int32) va_arg(argsP->v, + xmlrpc_int32)); + break; + + case 'b': + *valPP = + xmlrpc_bool_new(envP, (xmlrpc_bool) va_arg(argsP->v, xmlrpc_bool)); + break; + + case 'd': + *valPP = + xmlrpc_double_new(envP, (double) va_arg(argsP->v, double)); + break; + + case 's': + getString(envP, formatP, argsP, valPP); + break; + + case 'w': + getWideString(envP, formatP, argsP, valPP); + break; + + case 't': + *valPP = xmlrpc_datetime_new_sec(envP, va_arg(argsP->v, time_t)); + break; + + case '8': + *valPP = xmlrpc_datetime_new_str(envP, va_arg(argsP->v, char*)); + break; + + case '6': + getBase64(envP, argsP, valPP); + break; + + case 'n': + *valPP = + xmlrpc_nil_new(envP); + break; + + case 'I': + *valPP = + xmlrpc_i8_new(envP, (xmlrpc_int64) va_arg(argsP->v, xmlrpc_int64)); + break; + + case 'p': + *valPP = + xmlrpc_cptr_new(envP, (void*) va_arg(argsP->v, void*)); + break; + + case 'A': + mkArrayFromVal(envP, (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*), + valPP); + break; + + case 'S': + mkStructFromVal(envP, (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*), + valPP); + break; + + case 'V': + *valPP = (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*); + xmlrpc_INCREF(*valPP); + break; + + case '(': + getArray(envP, formatP, ')', argsP, valPP); + if (!envP->fault_occurred) { + XMLRPC_ASSERT(**formatP == ')'); + (*formatP)++; /* Skip over closing parenthesis */ + } + break; + + case '{': + getStruct(envP, formatP, '}', argsP, valPP); + if (!envP->fault_occurred) { + XMLRPC_ASSERT(**formatP == '}'); + (*formatP)++; /* Skip over closing brace */ + } + break; + + default: { + const char * const badCharacter = xmlrpc_makePrintableChar(formatChar); + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INTERNAL_ERROR, + "Unexpected character '%s' in format string", badCharacter); + xmlrpc_strfree(badCharacter); + } + } +} + + + +void +xmlrpc_build_value_va(xmlrpc_env * const envP, + const char * const format, + va_list const args, + xmlrpc_value ** const valPP, + const char ** const tailP) { + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(format != NULL); + + if (strlen(format) == 0) + xmlrpc_faultf(envP, "Format string is empty."); + else { + va_listx currentArgs; + const char * formatCursor; + + init_va_listx(¤tArgs, args); + formatCursor = &format[0]; + getValue(envP, &formatCursor, ¤tArgs, valPP); + + if (!envP->fault_occurred) + XMLRPC_ASSERT_VALUE_OK(*valPP); + + *tailP = formatCursor; + } +} + + + +xmlrpc_value * +xmlrpc_build_value(xmlrpc_env * const envP, + const char * const format, + ...) { + + va_list args; + xmlrpc_value * retval; + const char * suffix; + + va_start(args, format); + xmlrpc_build_value_va(envP, format, args, &retval, &suffix); + va_end(args); + + if (!envP->fault_occurred) { + if (*suffix != '\0') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INTERNAL_ERROR, "Junk after the argument " + "specifier: '%s'. There must be exactly one arument.", + suffix); + + if (envP->fault_occurred) + xmlrpc_DECREF(retval); + } + return retval; +} + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** Copyright (C) 2001 by Eric Kidd. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_client.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_client.c new file mode 100644 index 0000000..88f3dcf --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_client.c @@ -0,0 +1,998 @@ +/* Copyright information is at end of file */ + +#include "xmlrpc_config.h" + +#undef PACKAGE +#undef VERSION + +#include +#include +#include +#include +#include +#include +#include + +#include "bool.h" +#include "mallocvar.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/client.h" +#include "xmlrpc-c/client_int.h" +/* transport_config.h defines XMLRPC_DEFAULT_TRANSPORT, + MUST_BUILD_WININET_CLIENT, MUST_BUILD_CURL_CLIENT, + MUST_BUILD_LIBWWW_CLIENT +*/ +#include "transport_config.h" +#include "version.h" + +struct xmlrpc_client { +/*---------------------------------------------------------------------------- + This represents a client object. +-----------------------------------------------------------------------------*/ + bool myTransport; + /* The transport described below was created by this object; + No one else knows it exists and this object is responsible + for destroying it. + */ + struct xmlrpc_client_transport * transportP; + struct xmlrpc_client_transport_ops transportOps; + xmlrpc_dialect dialect; +}; + + + +struct xmlrpc_call_info { + /* This is all the information needed to finish executing a started + RPC. + + You don't need this for an RPC the user executes synchronously, + because then you can just use the storage in which the user passed + his arguments. But for asynchronous, the user will take back his + storage, and we need to keep this info in our own. + */ + + struct { + /* This are arguments to pass to the completion function. It + doesn't make sense to use them for anything else. In fact, it + really doesn't make sense for them to be arguments to the + completion function, but they are historically. */ + const char * serverUrl; + const char * methodName; + xmlrpc_value * paramArrayP; + void * userData; + } completionArgs; + xmlrpc_response_handler completionFn; + + + /* The serialized XML data passed to this call. We keep this around + ** for use by our source_anchor field. */ + xmlrpc_mem_block *serialized_xml; +}; + + + +/*========================================================================= + Global Constant Setup/Teardown +=========================================================================*/ + +static void +callTransportSetup(xmlrpc_env * const envP, + xmlrpc_transport_setup setupFn) { + + if (setupFn) + setupFn(envP); +} + + + +static void +setupTransportGlobalConst(xmlrpc_env * const envP) { + +#if MUST_BUILD_WININET_CLIENT + if (!envP->fault_occurred) + callTransportSetup(envP, + xmlrpc_wininet_transport_ops.setup_global_const); +#endif +#if MUST_BUILD_CURL_CLIENT + if (!envP->fault_occurred) + callTransportSetup(envP, + xmlrpc_curl_transport_ops.setup_global_const); +#endif +#if MUST_BUILD_LIBWWW_CLIENT + if (!envP->fault_occurred) + callTransportSetup(envP, + xmlrpc_libwww_transport_ops.setup_global_const); +#endif +} + + + +static void +callTransportTeardown(xmlrpc_transport_teardown teardownFn) { + + if (teardownFn) + teardownFn(); +} + + + +static void +teardownTransportGlobalConst(void) { + +#if MUST_BUILD_WININET_CLIENT + callTransportTeardown( + xmlrpc_wininet_transport_ops.teardown_global_const); +#endif +#if MUST_BUILD_CURL_CLIENT + callTransportTeardown( + xmlrpc_curl_transport_ops.teardown_global_const); +#endif +#if MUST_BUILD_LIBWWW_CLIENT + callTransportTeardown( + xmlrpc_libwww_transport_ops.teardown_global_const); +#endif +} + + + +/*========================================================================= + Global stuff (except the global client) +=========================================================================*/ + +static unsigned int constSetupCount = 0; + + +void +xmlrpc_client_setup_global_const(xmlrpc_env * const envP) { +/*---------------------------------------------------------------------------- + Set up pseudo-constant global variables (they'd be constant, except that + the library loader doesn't set them. An explicit call from the loaded + program does). + + This function is not thread-safe. The user is supposed to call it + (perhaps cascaded down from a multitude of higher level libraries) + as part of early program setup, when the program is only one thread. +-----------------------------------------------------------------------------*/ + if (constSetupCount == 0) + setupTransportGlobalConst(envP); + + ++constSetupCount; +} + + + +void +xmlrpc_client_teardown_global_const(void) { +/*---------------------------------------------------------------------------- + Complement to xmlrpc_client_setup_global_const(). + + This function is not thread-safe. The user is supposed to call it + (perhaps cascaded down from a multitude of higher level libraries) + as part of final program cleanup, when the program is only one thread. +-----------------------------------------------------------------------------*/ + assert(constSetupCount > 0); + + --constSetupCount; + + if (constSetupCount == 0) + teardownTransportGlobalConst(); +} + + + +unsigned int const xmlrpc_client_version_major = XMLRPC_VERSION_MAJOR; +unsigned int const xmlrpc_client_version_minor = XMLRPC_VERSION_MINOR; +unsigned int const xmlrpc_client_version_point = XMLRPC_VERSION_POINT; + + +/*========================================================================= + Client Create/Destroy +=========================================================================*/ + +static void +getTransportOps( + xmlrpc_env * const envP, + const char * const transportName, + const struct xmlrpc_client_transport_ops ** const opsPP) { + + if (false) { + } +#if MUST_BUILD_WININET_CLIENT + else if (strcmp(transportName, "wininet") == 0) + *opsPP = &xmlrpc_wininet_transport_ops; +#endif +#if MUST_BUILD_CURL_CLIENT + else if (strcmp(transportName, "curl") == 0) + *opsPP = &xmlrpc_curl_transport_ops; +#endif +#if MUST_BUILD_LIBWWW_CLIENT + else if (strcmp(transportName, "libwww") == 0) + *opsPP = &xmlrpc_libwww_transport_ops; +#endif + else + xmlrpc_faultf(envP, "Unrecognized XML transport name '%s'", + transportName); +} + + + +struct xportParms { + const void * parmsP; + size_t size; +}; + + + +static void +getTransportParmsFromClientParms( + xmlrpc_env * const envP, + const struct xmlrpc_clientparms * const clientparmsP, + unsigned int const parmSize, + struct xportParms * const xportParmsP) { + + if (parmSize < XMLRPC_CPSIZE(transportparmsP) || + clientparmsP->transportparmsP == NULL) { + + xportParmsP->parmsP = NULL; + xportParmsP->size = 0; + } else { + xportParmsP->parmsP = clientparmsP->transportparmsP; + if (parmSize < XMLRPC_CPSIZE(transportparm_size)) + xmlrpc_faultf(envP, "Your 'clientparms' argument contains the " + "transportparmsP member, " + "but no transportparms_size member"); + else + xportParmsP->size = clientparmsP->transportparm_size; + } +} + + + +static void +getTransportInfo( + xmlrpc_env * const envP, + const struct xmlrpc_clientparms * const clientparmsP, + unsigned int const parmSize, + const char ** const transportNameP, + struct xportParms * const transportParmsP, + const struct xmlrpc_client_transport_ops ** const transportOpsPP, + xmlrpc_client_transport ** const transportPP) { + + const char * transportNameParm; + xmlrpc_client_transport * transportP; + const struct xmlrpc_client_transport_ops * transportOpsP; + + if (parmSize < XMLRPC_CPSIZE(transport)) + transportNameParm = NULL; + else + transportNameParm = clientparmsP->transport; + + if (parmSize < XMLRPC_CPSIZE(transportP)) + transportP = NULL; + else + transportP = clientparmsP->transportP; + + if (parmSize < XMLRPC_CPSIZE(transportOpsP)) + transportOpsP = NULL; + else + transportOpsP = clientparmsP->transportOpsP; + + if ((transportOpsP && !transportP) || (transportP && ! transportOpsP)) + xmlrpc_faultf(envP, "'transportOpsP' and 'transportP' go together. " + "You must specify both or neither"); + else if (transportNameParm && transportP) + xmlrpc_faultf(envP, "You cannot specify both 'transport' and " + "'transportP' transport parameters."); + else if (transportP) + *transportNameP = NULL; + else if (transportNameParm) + *transportNameP = transportNameParm; + else + *transportNameP = xmlrpc_client_get_default_transport(envP); + + *transportOpsPP = transportOpsP; + *transportPP = transportP; + + if (!envP->fault_occurred) { + getTransportParmsFromClientParms( + envP, clientparmsP, parmSize, transportParmsP); + + if (!envP->fault_occurred) { + if (transportParmsP->parmsP && !transportNameParm) + xmlrpc_faultf( + envP, + "You specified transport parameters, but did not " + "specify a transport type. Parameters are specific " + "to a particular type."); + } + } +} + + + +static void +getDialectFromClientParms( + const struct xmlrpc_clientparms * const clientparmsP, + unsigned int const parmSize, + xmlrpc_dialect * const dialectP) { + + if (parmSize < XMLRPC_CPSIZE(dialect)) + *dialectP = xmlrpc_dialect_i8; + else + *dialectP = clientparmsP->dialect; +} + + + +static void +clientCreate( + xmlrpc_env * const envP, + bool const myTransport, + const struct xmlrpc_client_transport_ops * const transportOpsP, + struct xmlrpc_client_transport * const transportP, + xmlrpc_dialect const dialect, + xmlrpc_client ** const clientPP) { + + XMLRPC_ASSERT_PTR_OK(transportOpsP); + XMLRPC_ASSERT_PTR_OK(transportP); + XMLRPC_ASSERT_PTR_OK(clientPP); + + if (constSetupCount == 0) { + xmlrpc_faultf(envP, + "You have not called " + "xmlrpc_client_setup_global_const()."); + /* Impl note: We can't just call it now because it isn't + thread-safe. + */ + } else { + xmlrpc_client * clientP; + + MALLOCVAR(clientP); + + if (clientP == NULL) + xmlrpc_faultf(envP, "Unable to allocate memory for " + "client descriptor."); + else { + clientP->myTransport = myTransport; + clientP->transportOps = *transportOpsP; + clientP->transportP = transportP; + clientP->dialect = dialect; + + *clientPP = clientP; + } + } +} + + + +static void +createTransportAndClient( + xmlrpc_env * const envP, + const char * const transportName, + const void * const transportparmsP, + size_t const transportparmSize, + int const flags, + const char * const appname, + const char * const appversion, + xmlrpc_dialect const dialect, + xmlrpc_client ** const clientPP) { + + const struct xmlrpc_client_transport_ops * transportOpsP; + + getTransportOps(envP, transportName, &transportOpsP); + if (!envP->fault_occurred) { + xmlrpc_client_transport * transportP; + + /* The following call is not thread-safe */ + transportOpsP->create( + envP, flags, appname, appversion, + transportparmsP, transportparmSize, + &transportP); + if (!envP->fault_occurred) { + bool const myTransportTrue = true; + + clientCreate(envP, myTransportTrue, transportOpsP, transportP, + dialect, clientPP); + + if (envP->fault_occurred) + transportOpsP->destroy(transportP); + } + } +} + + + +void +xmlrpc_client_create(xmlrpc_env * const envP, + int const flags, + const char * const appname, + const char * const appversion, + const struct xmlrpc_clientparms * const clientparmsP, + unsigned int const parmSize, + xmlrpc_client ** const clientPP) { + + XMLRPC_ASSERT_PTR_OK(clientPP); + + if (constSetupCount == 0) { + xmlrpc_faultf(envP, + "You have not called " + "xmlrpc_client_setup_global_const()."); + /* Impl note: We can't just call it now because it isn't + thread-safe. + */ + } else { + const char * transportName; + struct xportParms transportparms; + const struct xmlrpc_client_transport_ops * transportOpsP; + xmlrpc_client_transport * transportP; + xmlrpc_dialect dialect; + + getTransportInfo(envP, clientparmsP, parmSize, &transportName, + &transportparms, &transportOpsP, &transportP); + + getDialectFromClientParms(clientparmsP, parmSize, &dialect); + + if (!envP->fault_occurred) { + if (transportName) + createTransportAndClient(envP, transportName, + transportparms.parmsP, + transportparms.size, + flags, appname, appversion, dialect, + clientPP); + else { + bool myTransportFalse = false; + clientCreate(envP, myTransportFalse, + transportOpsP, transportP, dialect, clientPP); + } + } + } +} + + + +void +xmlrpc_client_destroy(xmlrpc_client * const clientP) { + + XMLRPC_ASSERT_PTR_OK(clientP); + + if (clientP->myTransport) + clientP->transportOps.destroy(clientP->transportP); + + free(clientP); +} + + + +/*========================================================================= + Call/Response Utilities +=========================================================================*/ + +static void +makeCallXml(xmlrpc_env * const envP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_dialect const dialect, + xmlrpc_mem_block ** const callXmlPP) { + + XMLRPC_ASSERT_VALUE_OK(paramArrayP); + XMLRPC_ASSERT_PTR_OK(callXmlPP); + + if (methodName == NULL) + xmlrpc_faultf(envP, "method name argument is NULL pointer"); + else { + xmlrpc_mem_block * callXmlP; + + callXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0); + if (!envP->fault_occurred) { + xmlrpc_serialize_call2(envP, callXmlP, methodName, paramArrayP, + dialect); + + *callXmlPP = callXmlP; + + if (envP->fault_occurred) + XMLRPC_MEMBLOCK_FREE(char, callXmlP); + } + } +} + + + +/*========================================================================= + Synchronous Call +=========================================================================*/ + +void +xmlrpc_client_transport_call2( + xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block ** const respXmlPP) { + + XMLRPC_ASSERT_PTR_OK(clientP); + XMLRPC_ASSERT_PTR_OK(serverP); + XMLRPC_ASSERT_PTR_OK(callXmlP); + XMLRPC_ASSERT_PTR_OK(respXmlPP); + + clientP->transportOps.call( + envP, clientP->transportP, serverP, callXmlP, + respXmlPP); +} + + + +static void +parseResponse(xmlrpc_env * const envP, + xmlrpc_mem_block * const respXmlP, + xmlrpc_value ** const resultPP, + int * const faultCodeP, + const char ** const faultStringP) { + + xmlrpc_env respEnv; + + xmlrpc_env_init(&respEnv); + + xmlrpc_parse_response2( + &respEnv, + XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP), + XMLRPC_MEMBLOCK_SIZE(char, respXmlP), + resultPP, faultCodeP, faultStringP); + + if (respEnv.fault_occurred) + xmlrpc_env_set_fault_formatted( + envP, respEnv.fault_code, + "Unable to make sense of XML-RPC response from server. " + "%s. Use XMLRPC_TRACE_XML to see for yourself", + respEnv.fault_string); + + xmlrpc_env_clean(&respEnv); +} + + + +void +xmlrpc_client_call2(xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_value ** const resultPP) { + + xmlrpc_mem_block * callXmlP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(clientP); + XMLRPC_ASSERT_PTR_OK(serverInfoP); + XMLRPC_ASSERT_PTR_OK(paramArrayP); + + makeCallXml(envP, methodName, paramArrayP, clientP->dialect, &callXmlP); + + if (!envP->fault_occurred) { + xmlrpc_mem_block * respXmlP; + + xmlrpc_traceXml("XML-RPC CALL", + XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP), + XMLRPC_MEMBLOCK_SIZE(char, callXmlP)); + + clientP->transportOps.call( + envP, clientP->transportP, serverInfoP, callXmlP, &respXmlP); + if (!envP->fault_occurred) { + int faultCode; + const char * faultString; + + xmlrpc_traceXml("XML-RPC RESPONSE", + XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP), + XMLRPC_MEMBLOCK_SIZE(char, respXmlP)); + + parseResponse(envP, respXmlP, resultPP, &faultCode, &faultString); + + if (!envP->fault_occurred) { + if (faultString) { + xmlrpc_env_set_fault_formatted( + envP, faultCode, + "RPC failed at server. %s", faultString); + xmlrpc_strfree(faultString); + } else + XMLRPC_ASSERT_VALUE_OK(*resultPP); + } + XMLRPC_MEMBLOCK_FREE(char, respXmlP); + } + XMLRPC_MEMBLOCK_FREE(char, callXmlP); + } +} + + + +static void +clientCall2f_va(xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const char * const serverUrl, + const char * const methodName, + const char * const format, + xmlrpc_value ** const resultPP, + va_list args) { + + xmlrpc_value * argP; + xmlrpc_env argenv; + const char * suffix; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(serverUrl); + XMLRPC_ASSERT_PTR_OK(methodName); + XMLRPC_ASSERT_PTR_OK(format); + XMLRPC_ASSERT_PTR_OK(resultPP); + + /* Build our argument value. */ + xmlrpc_env_init(&argenv); + xmlrpc_build_value_va(&argenv, format, args, &argP, &suffix); + if (argenv.fault_occurred) + xmlrpc_env_set_fault_formatted( + envP, argenv.fault_code, "Invalid RPC arguments. " + "The format argument must indicate a single array, and the " + "following arguments must correspond to that format argument. " + "The failure is: %s", + argenv.fault_string); + else { + XMLRPC_ASSERT_VALUE_OK(argP); + + if (*suffix != '\0') + xmlrpc_faultf(envP, "Junk after the argument specifier: '%s'. " + "There must be exactly one argument.", + suffix); + else { + xmlrpc_server_info * serverInfoP; + + serverInfoP = xmlrpc_server_info_new(envP, serverUrl); + + if (!envP->fault_occurred) { + /* Perform the actual XML-RPC call. */ + xmlrpc_client_call2(envP, clientP, + serverInfoP, methodName, argP, resultPP); + if (!envP->fault_occurred) + XMLRPC_ASSERT_VALUE_OK(*resultPP); + xmlrpc_server_info_free(serverInfoP); + } + } + xmlrpc_DECREF(argP); + } + xmlrpc_env_clean(&argenv); +} + + + +void +xmlrpc_client_call2f(xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const char * const serverUrl, + const char * const methodName, + xmlrpc_value ** const resultPP, + const char * const format, + ...) { + + va_list args; + + va_start(args, format); + clientCall2f_va(envP, clientP, serverUrl, + methodName, format, resultPP, args); + va_end(args); +} + + + +/*========================================================================= + Asynchronous Call +=========================================================================*/ + +static void +callInfoSetCompletion(xmlrpc_env * const envP, + struct xmlrpc_call_info * const callInfoP, + const char * const serverUrl, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_response_handler completionFn, + void * const userData) { + + callInfoP->completionFn = completionFn; + callInfoP->completionArgs.userData = userData; + callInfoP->completionArgs.serverUrl = strdup(serverUrl); + if (callInfoP->completionArgs.serverUrl == NULL) + xmlrpc_faultf(envP, "Couldn't get memory to store server URL"); + else { + callInfoP->completionArgs.methodName = strdup(methodName); + if (callInfoP->completionArgs.methodName == NULL) + xmlrpc_faultf(envP, "Couldn't get memory to store method name"); + else { + callInfoP->completionArgs.paramArrayP = paramArrayP; + xmlrpc_INCREF(paramArrayP); + } + if (envP->fault_occurred) + xmlrpc_strfree(callInfoP->completionArgs.serverUrl); + } +} + + + +static void +callInfoCreate(xmlrpc_env * const envP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_dialect const dialect, + const char * const serverUrl, + xmlrpc_response_handler completionFn, + void * const userData, + struct xmlrpc_call_info ** const callInfoPP) { +/*---------------------------------------------------------------------------- + Create a call_info object. A call_info object represents an XML-RPC + call. +-----------------------------------------------------------------------------*/ + struct xmlrpc_call_info * callInfoP; + + XMLRPC_ASSERT_PTR_OK(serverUrl); + XMLRPC_ASSERT_PTR_OK(methodName); + XMLRPC_ASSERT_VALUE_OK(paramArrayP); + XMLRPC_ASSERT_PTR_OK(callInfoPP); + + MALLOCVAR(callInfoP); + if (callInfoP == NULL) + xmlrpc_faultf(envP, "Couldn't allocate memory for xmlrpc_call_info"); + else { + xmlrpc_mem_block * callXmlP; + + makeCallXml(envP, methodName, paramArrayP, dialect, &callXmlP); + + if (!envP->fault_occurred) { + xmlrpc_traceXml("XML-RPC CALL", + XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP), + XMLRPC_MEMBLOCK_SIZE(char, callXmlP)); + + callInfoP->serialized_xml = callXmlP; + + *callInfoPP = callInfoP; + + callInfoSetCompletion(envP, callInfoP, serverUrl, methodName, + paramArrayP, completionFn, userData); + + if (envP->fault_occurred) + free(callInfoP); + } + } +} + + + +static void +callInfoDestroy(struct xmlrpc_call_info * const callInfoP) { + + XMLRPC_ASSERT_PTR_OK(callInfoP); + + if (callInfoP->completionFn) { + xmlrpc_DECREF(callInfoP->completionArgs.paramArrayP); + xmlrpc_strfree(callInfoP->completionArgs.methodName); + xmlrpc_strfree(callInfoP->completionArgs.serverUrl); + } + if (callInfoP->serialized_xml) + xmlrpc_mem_block_free(callInfoP->serialized_xml); + + free(callInfoP); +} + + + +void +xmlrpc_client_event_loop_finish(xmlrpc_client * const clientP) { + + XMLRPC_ASSERT_PTR_OK(clientP); + + clientP->transportOps.finish_asynch( + clientP->transportP, timeout_no, 0); +} + + + +void +xmlrpc_client_event_loop_finish_timeout(xmlrpc_client * const clientP, + xmlrpc_timeout const timeout) { + + XMLRPC_ASSERT_PTR_OK(clientP); + + clientP->transportOps.finish_asynch( + clientP->transportP, timeout_yes, timeout); +} + + + +static void +asynchComplete(struct xmlrpc_call_info * const callInfoP, + xmlrpc_mem_block * const responseXmlP, + xmlrpc_env const transportEnv) { +/*---------------------------------------------------------------------------- + Complete an asynchronous XML-RPC call request. + + This includes calling the user's RPC completion routine. + + 'transportEnv' describes an error that the transport + encountered in processing the call. If the transport successfully + sent the call to the server and processed the response but the + server failed the call, 'transportEnv' indicates no error, and the + response in *responseXmlP might very well indicate that the server + failed the request. +-----------------------------------------------------------------------------*/ + xmlrpc_env env; + xmlrpc_value * resultP; + + xmlrpc_env_init(&env); + + resultP = NULL; /* Just to quiet compiler warning */ + + if (transportEnv.fault_occurred) + xmlrpc_env_set_fault_formatted( + &env, transportEnv.fault_code, + "Client transport failed to execute the RPC. %s", + transportEnv.fault_string); + + if (!env.fault_occurred) { + int faultCode; + const char * faultString; + + xmlrpc_parse_response2(&env, + XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlP), + XMLRPC_MEMBLOCK_SIZE(char, responseXmlP), + &resultP, &faultCode, &faultString); + + if (!env.fault_occurred) { + if (faultString) { + xmlrpc_env_set_fault_formatted( + &env, faultCode, + "RPC failed at server. %s", faultString); + xmlrpc_strfree(faultString); + } + } + } + /* Call the user's completion function with the RPC result */ + (*callInfoP->completionFn)(callInfoP->completionArgs.serverUrl, + callInfoP->completionArgs.methodName, + callInfoP->completionArgs.paramArrayP, + callInfoP->completionArgs.userData, + &env, resultP); + + if (!env.fault_occurred) + xmlrpc_DECREF(resultP); + + callInfoDestroy(callInfoP); + + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_client_start_rpc(xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_value * const argP, + xmlrpc_response_handler completionFn, + void * const userData) { + + struct xmlrpc_call_info * callInfoP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(clientP); + XMLRPC_ASSERT_PTR_OK(serverInfoP); + XMLRPC_ASSERT_PTR_OK(methodName); + XMLRPC_ASSERT_VALUE_OK(argP); + + callInfoCreate(envP, methodName, argP, clientP->dialect, + serverInfoP->serverUrl, completionFn, userData, + &callInfoP); + + if (!envP->fault_occurred) + clientP->transportOps.send_request( + envP, clientP->transportP, serverInfoP, + callInfoP->serialized_xml, + &asynchComplete, callInfoP); + + if (envP->fault_occurred) + callInfoDestroy(callInfoP); + else { + /* asynchComplete() will destroy *callInfoP */ + } +} + + + +void +xmlrpc_client_start_rpcf(xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const char * const serverUrl, + const char * const methodName, + xmlrpc_response_handler responseHandler, + void * const userData, + const char * const format, + ...) { + + va_list args; + xmlrpc_value * paramArrayP; + const char * suffix; + + XMLRPC_ASSERT_PTR_OK(serverUrl); + XMLRPC_ASSERT_PTR_OK(format); + + /* Build our argument array. */ + va_start(args, format); + xmlrpc_build_value_va(envP, format, args, ¶mArrayP, &suffix); + va_end(args); + if (!envP->fault_occurred) { + if (*suffix != '\0') + xmlrpc_faultf(envP, "Junk after the argument " + "specifier: '%s'. " + "There must be exactly one arument.", + suffix); + else { + xmlrpc_server_info * serverInfoP; + + serverInfoP = xmlrpc_server_info_new(envP, serverUrl); + if (!envP->fault_occurred) { + xmlrpc_client_start_rpc( + envP, clientP, + serverInfoP, methodName, paramArrayP, + responseHandler, userData); + } + xmlrpc_server_info_free(serverInfoP); + } + xmlrpc_DECREF(paramArrayP); + } +} + + + +/*========================================================================= + Miscellaneous +=========================================================================*/ + +const char * +xmlrpc_client_get_default_transport(xmlrpc_env * const envP ATTR_UNUSED) { + + return XMLRPC_DEFAULT_TRANSPORT; +} + + + +void +xmlrpc_client_set_interrupt(xmlrpc_client * const clientP, + int * const interruptP) { + + if (clientP->transportOps.set_interrupt) + clientP->transportOps.set_interrupt(clientP->transportP, interruptP); +} + + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +*/ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_client_global.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_client_global.c new file mode 100644 index 0000000..7beba14 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_client_global.c @@ -0,0 +1,414 @@ +#include + +#include "xmlrpc_config.h" + +#include "bool.h" + +#include +#include +#include +#include + +/*========================================================================= + Global Client +=========================================================================*/ + +static struct xmlrpc_client * globalClientP; +static bool globalClientExists = false; + + +void +xmlrpc_client_init2(xmlrpc_env * const envP, + int const flags, + const char * const appname, + const char * const appversion, + const struct xmlrpc_clientparms * const clientparmsP, + unsigned int const parmSize) { +/*---------------------------------------------------------------------------- + This function is not thread-safe. +-----------------------------------------------------------------------------*/ + if (globalClientExists) + xmlrpc_faultf( + envP, + "Xmlrpc-c global client instance has already been created " + "(need to call xmlrpc_client_cleanup() before you can " + "reinitialize)."); + else { + /* The following call is not thread-safe */ + xmlrpc_client_setup_global_const(envP); + if (!envP->fault_occurred) { + xmlrpc_client_create(envP, flags, appname, appversion, + clientparmsP, parmSize, &globalClientP); + if (!envP->fault_occurred) + globalClientExists = true; + + if (envP->fault_occurred) + xmlrpc_client_teardown_global_const(); + } + } +} + + + +void +xmlrpc_client_init(int const flags, + const char * const appname, + const char * const appversion) { +/*---------------------------------------------------------------------------- + This function is not thread-safe. +-----------------------------------------------------------------------------*/ + struct xmlrpc_clientparms clientparms; + + /* As our interface does not allow for failure, we just fail silently ! */ + + xmlrpc_env env; + xmlrpc_env_init(&env); + + clientparms.transport = NULL; + + /* The following call is not thread-safe */ + xmlrpc_client_init2(&env, flags, + appname, appversion, + &clientparms, XMLRPC_CPSIZE(transport)); + + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_client_cleanup() { +/*---------------------------------------------------------------------------- + This function is not thread-safe +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT(globalClientExists); + + xmlrpc_client_destroy(globalClientP); + + globalClientExists = false; + + /* The following call is not thread-safe */ + xmlrpc_client_teardown_global_const(); +} + + + +static void +validateGlobalClientExists(xmlrpc_env * const envP) { + + if (!globalClientExists) + xmlrpc_faultf(envP, + "Xmlrpc-c global client instance " + "has not been created " + "(need to call xmlrpc_client_init2())."); +} + + + +void +xmlrpc_client_transport_call( + xmlrpc_env * const envP, + void * const reserved ATTR_UNUSED, + /* for client handle */ + const xmlrpc_server_info * const serverP, + xmlrpc_mem_block * const callXmlP, + xmlrpc_mem_block ** const respXmlPP) { + + validateGlobalClientExists(envP); + if (!envP->fault_occurred) + xmlrpc_client_transport_call2(envP, globalClientP, serverP, + callXmlP, respXmlPP); +} + + + +static void +clientCall_va(xmlrpc_env * const envP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + const char * const format, + va_list args, + xmlrpc_value ** const resultPP) { + + validateGlobalClientExists(envP); + if (!envP->fault_occurred) { + xmlrpc_value * paramArrayP; + const char * suffix; + + xmlrpc_build_value_va(envP, format, args, ¶mArrayP, &suffix); + + if (!envP->fault_occurred) { + if (*suffix != '\0') + xmlrpc_faultf(envP, "Junk after the argument " + "specifier: '%s'. " + "There must be exactly one arument.", + suffix); + else + xmlrpc_client_call2(envP, globalClientP, serverInfoP, + methodName, paramArrayP, resultPP); + + xmlrpc_DECREF(paramArrayP); + } + } +} + + + +xmlrpc_value * +xmlrpc_client_call(xmlrpc_env * const envP, + const char * const serverUrl, + const char * const methodName, + const char * const format, + ...) { + + xmlrpc_value * resultP; + + xmlrpc_server_info * serverInfoP; + + serverInfoP = xmlrpc_server_info_new(envP, serverUrl); + + if (!envP->fault_occurred) { + va_list args; + va_start(args, format); + + clientCall_va(envP, serverInfoP, methodName, format, args, &resultP); + + va_end(args); + xmlrpc_server_info_free(serverInfoP); + } + + return resultP; +} + + + +xmlrpc_value * +xmlrpc_client_call_server(xmlrpc_env * const envP, + const xmlrpc_server_info * const serverP, + const char * const methodName, + const char * const format, + ...) { + + va_list args; + xmlrpc_value * resultP; + + va_start(args, format); + clientCall_va(envP, serverP, methodName, format, args, &resultP); + va_end(args); + + return resultP; +} + + + +xmlrpc_value * +xmlrpc_client_call_server_params( + xmlrpc_env * const envP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_value * const paramArrayP) { + + xmlrpc_value * resultP; + + validateGlobalClientExists(envP); + + if (!envP->fault_occurred) + xmlrpc_client_call2(envP, globalClientP, + serverInfoP, methodName, paramArrayP, + &resultP); + + return resultP; +} + + + +xmlrpc_value * +xmlrpc_client_call_params(xmlrpc_env * const envP, + const char * const serverUrl, + const char * const methodName, + xmlrpc_value * const paramArrayP) { + + xmlrpc_value * resultP; + + validateGlobalClientExists(envP); + + if (!envP->fault_occurred) { + xmlrpc_server_info * serverInfoP; + + serverInfoP = xmlrpc_server_info_new(envP, serverUrl); + + if (!envP->fault_occurred) { + xmlrpc_client_call2(envP, globalClientP, + serverInfoP, methodName, paramArrayP, + &resultP); + + xmlrpc_server_info_free(serverInfoP); + } + } + return resultP; +} + + + +void +xmlrpc_client_call_server_asynch_params( + xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_response_handler responseHandler, + void * const userData, + xmlrpc_value * const paramArrayP) { + + xmlrpc_env env; + + xmlrpc_env_init(&env); + + validateGlobalClientExists(&env); + + if (!env.fault_occurred) + xmlrpc_client_start_rpc(&env, globalClientP, + serverInfoP, methodName, paramArrayP, + responseHandler, userData); + + if (env.fault_occurred) { + /* Unfortunately, we have no way to return an error and the + regular callback for a failed RPC is designed to have the + parameter array passed to it. This was probably an oversight + of the original asynch design, but now we have to be as + backward compatible as possible, so we do this: + */ + (*responseHandler)(serverInfoP->serverUrl, + methodName, paramArrayP, userData, + &env, NULL); + } + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_client_call_asynch(const char * const serverUrl, + const char * const methodName, + xmlrpc_response_handler responseHandler, + void * const userData, + const char * const format, + ...) { + + xmlrpc_env env; + + xmlrpc_env_init(&env); + + validateGlobalClientExists(&env); + + if (!env.fault_occurred) { + xmlrpc_value * paramArrayP; + const char * suffix; + va_list args; + + va_start(args, format); + xmlrpc_build_value_va(&env, format, args, ¶mArrayP, &suffix); + va_end(args); + + if (!env.fault_occurred) { + if (*suffix != '\0') + xmlrpc_faultf(&env, "Junk after the argument " + "specifier: '%s'. " + "There must be exactly one arument.", + suffix); + else + xmlrpc_client_call_asynch_params( + serverUrl, methodName, responseHandler, userData, + paramArrayP); + } + } + if (env.fault_occurred) + (*responseHandler)(serverUrl, methodName, NULL, userData, &env, NULL); + + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_client_call_asynch_params(const char * const serverUrl, + const char * const methodName, + xmlrpc_response_handler responseHandler, + void * const userData, + xmlrpc_value * const paramArrayP) { + xmlrpc_env env; + xmlrpc_server_info * serverInfoP; + + xmlrpc_env_init(&env); + + serverInfoP = xmlrpc_server_info_new(&env, serverUrl); + + if (!env.fault_occurred) { + xmlrpc_client_call_server_asynch_params( + serverInfoP, methodName, responseHandler, userData, paramArrayP); + + xmlrpc_server_info_free(serverInfoP); + } + if (env.fault_occurred) + (*responseHandler)(serverUrl, methodName, paramArrayP, userData, + &env, NULL); + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_response_handler responseHandler, + void * const userData, + const char * const format, + ...) { + + xmlrpc_env env; + xmlrpc_value * paramArrayP; + const char * suffix; + va_list args; + + xmlrpc_env_init(&env); + + va_start(args, format); + xmlrpc_build_value_va(&env, format, args, ¶mArrayP, &suffix); + va_end(args); + + if (!env.fault_occurred) { + if (*suffix != '\0') + xmlrpc_faultf(&env, "Junk after the argument " + "specifier: '%s'. " + "There must be exactly one arument.", + suffix); + else + xmlrpc_client_call_server_asynch_params( + serverInfoP, methodName, responseHandler, userData, + paramArrayP); + + xmlrpc_DECREF(paramArrayP); + } + if (env.fault_occurred) + (*responseHandler)(serverInfoP->serverUrl, methodName, NULL, + userData, &env, NULL); + + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_client_event_loop_finish_asynch(void) { + + XMLRPC_ASSERT(globalClientExists); + xmlrpc_client_event_loop_finish(globalClientP); +} + + + +void +xmlrpc_client_event_loop_finish_asynch_timeout( + unsigned long const milliseconds) { + + XMLRPC_ASSERT(globalClientExists); + xmlrpc_client_event_loop_finish_timeout(globalClientP, milliseconds); +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_data.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_data.c new file mode 100644 index 0000000..28827fe --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_data.c @@ -0,0 +1,484 @@ +/* Copyright information is at end of file */ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include + +#include "bool.h" +#include "mallocvar.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" + + +static void +destroyValue(xmlrpc_value * const valueP) { + + /* First, we need to destroy this value's contents, if any. */ + switch (valueP->_type) { + case XMLRPC_TYPE_INT: + break; + + case XMLRPC_TYPE_BOOL: + break; + + case XMLRPC_TYPE_DOUBLE: + break; + + case XMLRPC_TYPE_DATETIME: + xmlrpc_mem_block_clean(&valueP->_block); + break; + + case XMLRPC_TYPE_STRING: + xmlrpc_destroyString(valueP); + break; + + case XMLRPC_TYPE_BASE64: + xmlrpc_mem_block_clean(&valueP->_block); + break; + + case XMLRPC_TYPE_ARRAY: + xmlrpc_destroyArrayContents(valueP); + break; + + case XMLRPC_TYPE_STRUCT: + xmlrpc_destroyStruct(valueP); + break; + + case XMLRPC_TYPE_C_PTR: + break; + + case XMLRPC_TYPE_NIL: + break; + + case XMLRPC_TYPE_I8: + break; + + case XMLRPC_TYPE_DEAD: + XMLRPC_ASSERT(false); /* Can't happen, per entry conditions */ + + default: + XMLRPC_ASSERT(false); /* There are no other possible values */ + } + + /* Next, we mark this value as invalid, to help catch refcount + ** errors. */ + valueP->_type = XMLRPC_TYPE_DEAD; + + /* Finally, we destroy the value itself. */ + free(valueP); +} + + + +/*========================================================================= +** Reference Counting +**========================================================================= +** Some simple reference-counting code. The xmlrpc_DECREF routine is in +** charge of destroying values when their reference count equals zero. +*/ + +void +xmlrpc_INCREF (xmlrpc_value * const valueP) { + + XMLRPC_ASSERT_VALUE_OK(valueP); + XMLRPC_ASSERT(valueP->_refcount > 0); + + ++valueP->_refcount; +} + + + +void +xmlrpc_DECREF (xmlrpc_value * const valueP) { + + XMLRPC_ASSERT_VALUE_OK(valueP); + XMLRPC_ASSERT(valueP->_refcount > 0); + XMLRPC_ASSERT(valueP->_type != XMLRPC_TYPE_DEAD); + + valueP->_refcount--; + + /* If we have no more refs, we need to deallocate this value. */ + if (valueP->_refcount == 0) + destroyValue(valueP); +} + + + +/*========================================================================= + Utiltiies +=========================================================================*/ + +const char * +xmlrpc_type_name(xmlrpc_type const type) { + + switch (type) { + + case XMLRPC_TYPE_INT: return "INT"; + case XMLRPC_TYPE_BOOL: return "BOOL"; + case XMLRPC_TYPE_DOUBLE: return "DOUBLE"; + case XMLRPC_TYPE_DATETIME: return "DATETIME"; + case XMLRPC_TYPE_STRING: return "STRING"; + case XMLRPC_TYPE_BASE64: return "BASE64"; + case XMLRPC_TYPE_ARRAY: return "ARRAY"; + case XMLRPC_TYPE_STRUCT: return "STRUCT"; + case XMLRPC_TYPE_C_PTR: return "C_PTR"; + case XMLRPC_TYPE_NIL: return "NIL"; + case XMLRPC_TYPE_I8: return "I8"; + case XMLRPC_TYPE_DEAD: return "DEAD"; + default: return "???"; + + } +} + + + +static void +validateType(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_type const expectedType) { + + if (valueP->_type != expectedType) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where " + "type %s was expected.", + xmlrpc_type_name(valueP->_type), xmlrpc_type_name(expectedType)); + } +} + + + +/*========================================================================= + Extracting XML-RPC value +=========================================================================== + These routines extract XML-RPC values into ordinary C data types. + + For array and struct values, see the separates files xmlrpc_array.c + and xmlrpc_struct.c. +=========================================================================*/ + +void +xmlrpc_read_int(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_int32 * const intValueP) { + + validateType(envP, valueP, XMLRPC_TYPE_INT); + if (!envP->fault_occurred) + *intValueP = valueP->_value.i; +} + + + +void +xmlrpc_read_bool(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_bool * const boolValueP) { + + validateType(envP, valueP, XMLRPC_TYPE_BOOL); + if (!envP->fault_occurred) + *boolValueP = valueP->_value.b; +} + + + +void +xmlrpc_read_double(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_double * const doubleValueP) { + + validateType(envP, valueP, XMLRPC_TYPE_DOUBLE); + if (!envP->fault_occurred) + *doubleValueP = valueP->_value.d; + +} + + + +/* datetime stuff is in xmlrpc_datetime.c */ + +/* string stuff is in xmlrpc_string.c */ + + + +void +xmlrpc_read_base64(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const unsigned char ** const byteStringValueP) { + + validateType(envP, valueP, XMLRPC_TYPE_BASE64); + if (!envP->fault_occurred) { + size_t const size = + XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); + const char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + + char * byteStringValue; + + byteStringValue = malloc(size); + if (byteStringValue == NULL) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes " + "for byte string.", size); + else { + memcpy(byteStringValue, contents, size); + *byteStringValueP = (const unsigned char *)byteStringValue; + *lengthP = size; + } + } +} + + + +void +xmlrpc_read_base64_old(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const unsigned char ** const byteStringValueP) { + + validateType(envP, valueP, XMLRPC_TYPE_BASE64); + if (!envP->fault_occurred) { + *lengthP = + XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); + *byteStringValueP = (const unsigned char *) + XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + } +} + + + +void +xmlrpc_read_base64_size(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP) { + + validateType(envP, valueP, XMLRPC_TYPE_BASE64); + if (!envP->fault_occurred) + *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); +} + + + +void +xmlrpc_read_cptr(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + void ** const ptrValueP) { + + validateType(envP, valueP, XMLRPC_TYPE_C_PTR); + if (!envP->fault_occurred) + *ptrValueP = valueP->_value.c_ptr; +} + + + +void +xmlrpc_read_nil(xmlrpc_env * const envP, + xmlrpc_value * const valueP) { +/*---------------------------------------------------------------------------- + Read out the value of a nil value. It doesn't have one, of course, so + this is essentially a no-op. But it does validate the type and is + necessary to match all the other types. +-----------------------------------------------------------------------------*/ + validateType(envP, valueP, XMLRPC_TYPE_NIL); +} + + + +void +xmlrpc_read_i8(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_int64 * const intValueP) { + + validateType(envP, valueP, XMLRPC_TYPE_I8); + if (!envP->fault_occurred) + *intValueP = valueP->_value.i8; +} + + + +xmlrpc_type xmlrpc_value_type (xmlrpc_value* const value) +{ + XMLRPC_ASSERT_VALUE_OK(value); + return value->_type; +} + + + +void +xmlrpc_createXmlrpcValue(xmlrpc_env * const envP, + xmlrpc_value ** const valPP) { +/*---------------------------------------------------------------------------- + Create a blank xmlrpc_value to be filled in. + + Set the reference count to 1. +-----------------------------------------------------------------------------*/ + xmlrpc_value * valP; + + MALLOCVAR(valP); + if (!valP) + xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, + "Could not allocate memory for xmlrpc_value"); + else + valP->_refcount = 1; + + *valPP = valP; +} + + + +xmlrpc_value * +xmlrpc_int_new(xmlrpc_env * const envP, + xmlrpc_int32 const value) { + + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_INT; + valP->_value.i = value; + } + return valP; +} + + + +xmlrpc_value * +xmlrpc_i8_new(xmlrpc_env * const envP, + xmlrpc_int64 const value) { + + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_I8; + valP->_value.i8 = value; + } + return valP; +} + + + +xmlrpc_value * +xmlrpc_bool_new(xmlrpc_env * const envP, + xmlrpc_bool const value) { + + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_BOOL; + valP->_value.b = value; + } + return valP; +} + + + +xmlrpc_value * +xmlrpc_double_new(xmlrpc_env * const envP, + double const value) { + + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_DOUBLE; + valP->_value.d = value; + } + return valP; +} + + + +xmlrpc_value * +xmlrpc_base64_new(xmlrpc_env * const envP, + size_t const length, + const unsigned char * const value) { + + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_BASE64; + + xmlrpc_mem_block_init(envP, &valP->_block, length); + if (!envP->fault_occurred) { + char * const contents = + xmlrpc_mem_block_contents(&valP->_block); + memcpy(contents, value, length); + } + if (envP->fault_occurred) + free(valP); + } + return valP; +} + + + +/* array stuff is in xmlrpc_array.c */ + + + +xmlrpc_value * +xmlrpc_cptr_new(xmlrpc_env * const envP, + void * const value) { + + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_C_PTR; + valP->_value.c_ptr = value; + } + return valP; +} + + + +xmlrpc_value * +xmlrpc_nil_new(xmlrpc_env * const envP) { + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + if (!envP->fault_occurred) + valP->_type = XMLRPC_TYPE_NIL; + + return valP; +} + + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** Copyright (C) 2001 by Eric Kidd. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_datetime.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_datetime.c new file mode 100644 index 0000000..a4b6454 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_datetime.c @@ -0,0 +1,699 @@ +#include "xmlrpc_config.h" + +#include +#include +#include +#include +#include +#include +#if MSVCRT +#include +#endif + +#include "bool.h" + +#include "xmlrpc-c/c_util.h" +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/time_int.h" + + +/* Future work: the XMLRPC_TYPE_DATETIME xmlrpc_value should store the + datetime as something computation-friendly, not as a string. The + XML-RPC XML parser should parse the string value and reject the XML if + it isn't valid. + + But this file should remain the authority on datetimes, so the XML + parser and builder should call on routines in here to do that. + + time_t won't work because it can't represent times before 1970 or + after 2038. We need to figure out something better. +*/ + +#if HAVE_REGEX +#include "regex.h" +#endif + +#if MSVCRT + +static const __int64 SECS_BETWEEN_EPOCHS = 11644473600; +static const __int64 SECS_TO_100NS = 10000000; /* 10^7 */ + + +void +UnixTimeToFileTime(time_t const t, + LPFILETIME const pft) { + + int64_t const ll = + Int32x32To64(t, SECS_TO_100NS) + SECS_BETWEEN_EPOCHS * SECS_TO_100NS; + + pft->dwLowDateTime = (DWORD)ll; + pft->dwHighDateTime = (DWORD)(ll >> 32); +} + + + +void +UnixTimeToSystemTime(time_t const t, + LPSYSTEMTIME const pst) { + FILETIME ft; + + UnixTimeToFileTime(t, &ft); + FileTimeToSystemTime(&ft, pst); +} + + + +static void +UnixTimeFromFileTime(xmlrpc_env * const envP, + LPFILETIME const pft, + time_t * const timeValueP) { + + int64_t const WinEpoch100Ns = + ((int64_t)pft->dwHighDateTime << 32) + pft->dwLowDateTime; + int64_t const unixEpoch100Ns = + WinEpoch100Ns - (SECS_BETWEEN_EPOCHS * SECS_TO_100NS); + int64_t const unixEpochSeconds = + unixEpoch100Ns / SECS_TO_100NS; + + if ((time_t)unixEpochSeconds != unixEpochSeconds) { + /* Value is too big for a time_t; fail. */ + xmlrpc_faultf(envP, "Does not indicate a valid date"); + *timeValueP = (time_t)(-1); + } else + *timeValueP = (time_t)unixEpochSeconds; +} + + + +static void +UnixTimeFromSystemTime(xmlrpc_env * const envP, + LPSYSTEMTIME const pst, + time_t * const timeValueP) { + FILETIME filetime; + + SystemTimeToFileTime(pst, &filetime); + UnixTimeFromFileTime(envP, &filetime, timeValueP); +} + +#endif /* MSVCRT */ + + + +static const char * const iso8601Regex = + "^([0-9]{4})([0-9]{2})([0-9]{2})T" + "([0-9]{2}):?([0-9]{2}):?([0-9]{2})\\.?([0-9]+)?$"; + + + +static void +validateDatetimeType(xmlrpc_env * const envP, + const xmlrpc_value * const valueP) { + + if (valueP->_type != XMLRPC_TYPE_DATETIME) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where " + "type %s was expected.", + xmlrpc_type_name(valueP->_type), + xmlrpc_type_name(XMLRPC_TYPE_DATETIME)); + } +} + + + +void +xmlrpc_read_datetime_str(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP) { + + validateDatetimeType(envP, valueP); + if (!envP->fault_occurred) { + const char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + *stringValueP = strdup(contents); + if (*stringValueP == NULL) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate space " + "for datetime string"); + } +} + + + +void +xmlrpc_read_datetime_str_old(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP) { + + validateDatetimeType(envP, valueP); + if (!envP->fault_occurred) { + *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + } +} + + + +#if HAVE_REGEX + +static unsigned int +digitStringValue(const char * const string, + regmatch_t const match) { +/*---------------------------------------------------------------------------- + Return the numerical value of the decimal whole number substring of + 'string' identified by 'match'. E.g. if 'string' is 'abc34d' and + 'match' says start at 3 and end at 5, we return 34. +-----------------------------------------------------------------------------*/ + unsigned int i; + unsigned int accum; + + assert(match.rm_so >= 0); + assert(match.rm_eo >= 0); + + for (i = match.rm_so, accum = 0; i < (unsigned)match.rm_eo; ++i) { + accum *= 10; + assert(isdigit(string[i])); + accum += string[i] - '0'; + } + return accum; +} +#endif /* HAVE_REGEX */ + + + +#if HAVE_REGEX + +static unsigned int +digitStringMillionths(const char * const string, + regmatch_t const match) { +/*---------------------------------------------------------------------------- + Return the number of millionths represented by the digits after the + decimal point in a decimal string, where thse digits are the substring + of 'string' identified by 'match'. E.g. if the substring is + 34, we return 340,000. +-----------------------------------------------------------------------------*/ + unsigned int i; + unsigned int accum; + + assert(match.rm_so >= 0); + assert(match.rm_eo >= 0); + + for (i = match.rm_so, accum = 0; i < (unsigned)match.rm_so+6; ++i) { + accum *= 10; + if (i < (unsigned)match.rm_eo) { + assert(isdigit(string[i])); + accum += string[i] - '0'; + } + } + return accum; +} +#endif /* HAVE_REGEX */ + + + +#if HAVE_REGEX +static void +parseDateNumbersRegex(xmlrpc_env * const envP, + const char * const datetimeString, + unsigned int * const YP, + unsigned int * const MP, + unsigned int * const DP, + unsigned int * const hP, + unsigned int * const mP, + unsigned int * const sP, + unsigned int * const uP) { + + + int status; + char errBuf[1024]; + regex_t re; + + status = regcomp(&re, iso8601Regex, REG_ICASE | REG_EXTENDED); + if (status == 0) { + regmatch_t matches[1024]; + int status; + + status = regexec(&re, datetimeString, ARRAY_SIZE(matches), matches, 0); + + if (status == 0) { + assert(matches[0].rm_so != -1); /* Match of whole regex */ + + *YP = digitStringValue(datetimeString, matches[1]); + *MP = digitStringValue(datetimeString, matches[2]); + *DP = digitStringValue(datetimeString, matches[3]); + *hP = digitStringValue(datetimeString, matches[4]); + *mP = digitStringValue(datetimeString, matches[5]); + *sP = digitStringValue(datetimeString, matches[6]); + + if (matches[7].rm_so == -1) + *uP = 0; + else + *uP = digitStringMillionths(datetimeString, matches[7]); + } else { + regerror(status, &re, errBuf, sizeof(errBuf)); + xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR, errBuf); + } + + } else { + regerror(status, &re, errBuf, sizeof(errBuf)); + xmlrpc_faultf(envP, "internal regex error at %s:%d: '%s'", + __FILE__, __LINE__, errBuf); + } + regfree(&re); +} +#endif /* HAVE_REGEX */ + + + +static __inline__ void +parseDateNumbersNoRegex(xmlrpc_env * const envP, + const char * const datetimeString, + unsigned int * const YP, + unsigned int * const MP, + unsigned int * const DP, + unsigned int * const hP, + unsigned int * const mP, + unsigned int * const sP, + unsigned int * const uP) { + + unsigned int const dtStrlen = strlen(datetimeString); + + char year[4+1]; + char month[2+1]; + char day[2+1]; + char hour[2+1]; + char minute[2+1]; + char second[2+1]; + + if (dtStrlen < 17 || dtStrlen == 18 || dtStrlen > 24) + xmlrpc_faultf(envP, "could not parse date, size incompatible: '%d'", + dtStrlen); + else { + year[0] = datetimeString[ 0]; + year[1] = datetimeString[ 1]; + year[2] = datetimeString[ 2]; + year[3] = datetimeString[ 3]; + year[4] = '\0'; + + month[0] = datetimeString[ 4]; + month[1] = datetimeString[ 5]; + month[2] = '\0'; + + day[0] = datetimeString[ 6]; + day[1] = datetimeString[ 7]; + day[2] = '\0'; + + assert(datetimeString[ 8] == 'T'); + + hour[0] = datetimeString[ 9]; + hour[1] = datetimeString[10]; + hour[2] = '\0'; + + assert(datetimeString[11] == ':'); + + minute[0] = datetimeString[12]; + minute[1] = datetimeString[13]; + minute[2] = '\0'; + + assert(datetimeString[14] == ':'); + + second[0] = datetimeString[15]; + second[1] = datetimeString[16]; + second[2] = '\0'; + + if (dtStrlen > 17) { + unsigned int const pad = 24 - dtStrlen; + unsigned int i; + + *uP = atoi(&datetimeString[18]); + for (i = 0; i < pad; ++i) + *uP *= 10; + } else + *uP = 0; + + *YP = atoi(year); + *MP = atoi(month); + *DP = atoi(day); + *hP = atoi(hour); + *mP = atoi(minute); + *sP = atoi(second); + } +} + + + +static void +validateFirst17(xmlrpc_env * const envP, + const char * const dt) { +/*---------------------------------------------------------------------------- + Assuming 'dt' is at least 17 characters long, validate that the first + 17 characters are a valid XML-RPC datetime, e.g. + "20080628T16:35:02" +-----------------------------------------------------------------------------*/ + unsigned int i; + + for (i = 0; i < 8 && !envP->fault_occurred; ++i) + if (!isdigit(dt[i])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[i]); + + if (dt[8] != 'T') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "9th character is '%c', not 'T'", + dt[8]); + if (!isdigit(dt[9])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[9]); + if (!isdigit(dt[10])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[10]); + if (dt[11] != ':') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a colon: '%c'", dt[11]); + if (!isdigit(dt[12])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[12]); + if (!isdigit(dt[13])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[13]); + if (dt[14] != ':') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a colon: '%c'", dt[14]); + if (!isdigit(dt[15])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[15]); + if (!isdigit(dt[16])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[16]); +} + + + +static void +validateFractionalSeconds(xmlrpc_env * const envP, + const char * const dt) { +/*---------------------------------------------------------------------------- + Validate the fractional seconds part of the XML-RPC datetime string + 'dt', if any. That's the decimal point and everything following + it. +-----------------------------------------------------------------------------*/ + if (strlen(dt) > 17) { + if (dt[17] != '.') { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "'%c' where only a period is valid", dt[17]); + } else { + if (dt[18] == '\0') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Nothing after decimal point"); + else { + unsigned int i; + for (i = 18; dt[i] != '\0' && !envP->fault_occurred; ++i) { + if (!isdigit(dt[i])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Non-digit in fractional seconds: '%c'", dt[i]); + } + } + } + } +} + + + +static __inline__ void +validateFormat(xmlrpc_env * const envP, + const char * const dt) { + + if (strlen(dt) < 17) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Invalid length of %u of datetime. " + "Must be at least 17 characters", + strlen(dt)); + else { + validateFirst17(envP, dt); + + validateFractionalSeconds(envP, dt); + } +} + + + +static void +parseDateNumbers(xmlrpc_env * const envP, + const char * const datetimeString, + unsigned int * const YP, + unsigned int * const MP, + unsigned int * const DP, + unsigned int * const hP, + unsigned int * const mP, + unsigned int * const sP, + unsigned int * const uP) { + +#if HAVE_REGEX + parseDateNumbersRegex(envP, datetimeString, YP, MP, DP, hP, mP, sP, uP); +#else + /* Note: validation is not as strong without regex */ + validateFormat(envP, datetimeString); + if (!envP->fault_occurred) + parseDateNumbersNoRegex(envP, datetimeString, + YP, MP, DP, hP, mP, sP, uP); +#endif +} + + + +static void +parseDatetime(xmlrpc_env * const envP, + const char * const datetimeString, + time_t * const timeValueP, + unsigned int * const usecsP) { +/*---------------------------------------------------------------------------- + Parse a time in the format stored in an xmlrpc_value and return the + time that it represents. + + datetimeString[] is the input time string. We return the result as + *timeValueP. + + Example of the format we parse: "19980717T14:08:55" + Note that this is not quite ISO 8601. It's a bizarre combination of + two ISO 8601 formats. + + The input is capable of representing datetimes that cannot be expressed + as a time_t. In that case, we fail, with fault code + XMLRPC_INTERNAL_ERROR. + + And of course the input may not validly represent a datetime at all. + In that case too, we fail with fault code XMLRPC_PARSE_ERROR. +-----------------------------------------------------------------------------*/ + validateFormat(envP, datetimeString); + + if (!envP->fault_occurred) { + unsigned int Y, M, D, h, m, s, u; + + parseDateNumbers(envP, datetimeString, &Y, &M, &D, &h, &m, &s, &u); + + if (!envP->fault_occurred) { + if (Y < 1970) + xmlrpc_env_set_fault_formatted(envP, XMLRPC_INTERNAL_ERROR, + "Year is too early to represent as " + "a standard Unix time"); + else { + struct tm brokenTime; + const char * error; + + brokenTime.tm_sec = s; + brokenTime.tm_min = m; + brokenTime.tm_hour = h; + brokenTime.tm_mday = D; + brokenTime.tm_mon = M - 1; + brokenTime.tm_year = Y - 1900; + + xmlrpc_timegm(&brokenTime, timeValueP, &error); + + if (error) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, error); + xmlrpc_strfree(error); + } else + *usecsP = u; + } + } + } +} + + + +void +xmlrpc_read_datetime_usec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + time_t * const secsP, + unsigned int * const usecsP) { + + validateDatetimeType(envP, valueP); + + if (!envP->fault_occurred) + parseDatetime(envP, + XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block), + secsP, + usecsP); +} + + + +void +xmlrpc_read_datetime_sec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + time_t * const timeValueP) { + + unsigned int usecs; + + xmlrpc_read_datetime_usec(envP, valueP, timeValueP, &usecs); +} + + + +#if XMLRPC_HAVE_TIMEVAL + +void +xmlrpc_read_datetime_timeval(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + struct timeval * const timeValueP) { + + time_t secs; + unsigned int usecs; + + xmlrpc_read_datetime_usec(envP, valueP, &secs, &usecs); + + timeValueP->tv_sec = secs; + timeValueP->tv_usec = usecs; +} +#endif + + + +#if XMLRPC_HAVE_TIMESPEC + +void +xmlrpc_read_datetime_timespec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + struct timespec * const timeValueP) { + + time_t secs; + unsigned int usecs; + + xmlrpc_read_datetime_usec(envP, valueP, &secs, &usecs); + + timeValueP->tv_sec = secs; + timeValueP->tv_nsec = usecs * 1000; +} +#endif + + + +xmlrpc_value * +xmlrpc_datetime_new_str(xmlrpc_env * const envP, + const char * const value) { + + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_DATETIME; + + XMLRPC_TYPED_MEM_BLOCK_INIT( + char, envP, &valP->_block, strlen(value) + 1); + if (!envP->fault_occurred) { + char * const contents = + XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block); + strcpy(contents, value); + } + if (envP->fault_occurred) + free(valP); + } + return valP; +} + + + +xmlrpc_value* +xmlrpc_datetime_new_usec(xmlrpc_env * const envP, + time_t const secs, + unsigned int const usecs) { + + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + struct tm brokenTime; + char timeString[64]; + + xmlrpc_gmtime(secs, &brokenTime); + + /* Note that this format is NOT ISO 8601 -- it's a bizarre + hybrid of two ISO 8601 formats. + */ + strftime(timeString, sizeof(timeString), "%Y%m%dT%H:%M:%S", + &brokenTime); + + if (usecs != 0) { + char usecString[64]; + assert(usecs < 1000000); + snprintf(usecString, sizeof(usecString), ".%06u", usecs); + STRSCAT(timeString, usecString); + } + + valP->_type = XMLRPC_TYPE_DATETIME; + + XMLRPC_TYPED_MEM_BLOCK_INIT( + char, envP, &valP->_block, strlen(timeString) + 1); + + if (!envP->fault_occurred) { + char * const contents = + XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block); + + strcpy(contents, timeString); + } + if (envP->fault_occurred) { + free(valP); + valP = NULL; + } + } + return valP; +} + + + +xmlrpc_value * +xmlrpc_datetime_new_sec(xmlrpc_env * const envP, + time_t const value) { + + return xmlrpc_datetime_new_usec(envP, value, 0); +} + + + +#if XMLRPC_HAVE_TIMEVAL + +xmlrpc_value * +xmlrpc_datetime_new_timeval(xmlrpc_env * const envP, + struct timeval const value) { + + return xmlrpc_datetime_new_usec(envP, value.tv_sec, value.tv_usec); +} +#endif + + + +#if XMLRPC_HAVE_TIMESPEC + +xmlrpc_value * +xmlrpc_datetime_new_timespec(xmlrpc_env * const envP, + struct timespec const value) { + + return xmlrpc_datetime_new_usec(envP, value.tv_sec, value.tv_nsec/1000); +} +#endif diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_decompose.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_decompose.c new file mode 100644 index 0000000..eeb3414 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_decompose.c @@ -0,0 +1,1151 @@ +/* By Bryan Henderson July 2006. + + Contributed to the public domain. +*/ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include + +#include "bool.h" +#include "c_util.h" +#include "mallocvar.h" +#include "stdargx.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" + + +/* THE DECOMPOSITION TREE + + We execute xmlrpc_decompose_value() in two steps: + + 1) Create a "decomposition tree" that tells how Caller wants the XML-RPC + value decomposed. + + 2) Using that tree, decompose the value. I.e. store stuff in the variables + in which Caller wants it stored. + + The decomposition tree is composed of information from the format + string and the variable arguments that the format string describes. + Nothing in the tree is derived from the actual XML-RPC value being + decomposed, and the tree may in fact be invalid for the particular + XML-RPC value it's meant for. + + If the XML-RPC value is a simple value such as an integer, the + decomposition tree is trivial -- it's a single node that says + "store the value of an integer via pointer P". + + Where it gets interesting is where the XML-RPC value to be decomposed + is a complex value (array or struct). Then, the root node of the tree + says, e.g., "decompose a 5-item array according to the following + 5 decomposition trees" and it points to 5 additional nodes. Each of + those nodes is the root of another decomposition tree (which can also + be called a branch in this context). Each of those branches tells + how to decompose one of the items of the array. + + Roots, interior nodes, and leaves are all essentially the same data + type. +*/ + +struct integerDecomp { + xmlrpc_int32 * valueP; +}; + +struct boolDecomp { + xmlrpc_bool * valueP; +}; + +struct doubleDecomp { + double * valueP; +}; + +struct datetimeTDecomp { + time_t * valueP; +}; + +struct datetime8Decomp { + const char ** valueP; +}; + +struct stringDecomp { + const char ** valueP; + size_t * sizeP; + /* NULL means don't store a size */ +}; + +struct wideStringDecomp { +#if HAVE_UNICODE_WCHAR + const wchar_t ** valueP; +#endif + size_t * sizeP; + /* NULL means don't store a size */ +}; + +struct bitStringDecomp { + const unsigned char ** valueP; + size_t * sizeP; +}; + +struct cptrDecomp { + void ** valueP; +}; + +struct i8Decomp { + xmlrpc_int64 * valueP; +}; + +struct valueDecomp { + xmlrpc_value ** valueP; +}; + +struct arrayValDecomp { + xmlrpc_value ** valueP; +}; + +struct structValDecomp { + xmlrpc_value ** valueP; +}; + +struct arrayDecomp { + unsigned int itemCnt; + bool ignoreExcess; + /* If there are more that 'itemCnt' items in the array, just + extract the first 'itemCnt' and ignore the rest, rather than + fail the decomposition. + */ + struct decompTreeNode * itemArray[16]; + /* Only first 'itemCnt' elements of this array are defined */ +}; + +struct mbrDecomp { + const char * key; + /* The key for the member whose value client wants to extract */ + struct decompTreeNode * decompTreeP; + /* Instructions on how to decompose (extract) member's value */ +}; + +struct structDecomp { + unsigned int mbrCnt; + struct mbrDecomp mbrArray[16]; +}; + + +struct decompTreeNode { + char formatSpecChar; + /* e.g. 'i', 'b', '8', 'A'. '(' means array; '{' means struct */ + union { + /*------------------------------------------------------------------------ + 'formatSpecChar' selects among these members. + -------------------------------------------------------------------------*/ + struct integerDecomp Tinteger; + struct boolDecomp Tbool; + struct doubleDecomp Tdouble; + struct datetimeTDecomp TdatetimeT; + struct datetime8Decomp Tdatetime8; + struct stringDecomp Tstring; + struct wideStringDecomp TwideString; + struct bitStringDecomp TbitString; + struct cptrDecomp Tcptr; + struct i8Decomp Ti8; + struct valueDecomp Tvalue; + struct arrayValDecomp TarrayVal; + struct structValDecomp TstructVal; + struct arrayDecomp Tarray; + struct structDecomp Tstruct; + } store; + +}; + + + +/* prototype for recursive calls */ +static void +releaseDecomposition(const struct decompTreeNode * const decompRootP, + bool const oldstyleMemMgmt); + + +static void +releaseDecompArray(struct arrayDecomp const arrayDecomp, + bool const oldstyleMemMgmt) { + + unsigned int i; + for (i = 0; i < arrayDecomp.itemCnt; ++i) { + releaseDecomposition(arrayDecomp.itemArray[i], oldstyleMemMgmt); + } +} + + +static void +releaseDecompStruct(struct structDecomp const structDecomp, + bool const oldstyleMemMgmt) { + + unsigned int i; + for (i = 0; i < structDecomp.mbrCnt; ++i) { + releaseDecomposition(structDecomp.mbrArray[i].decompTreeP, + oldstyleMemMgmt); + } +} + + + +static void +releaseDecomposition(const struct decompTreeNode * const decompRootP, + bool const oldstyleMemMgmt) { +/*---------------------------------------------------------------------------- + Assuming that Caller has decomposed something according to 'decompRootP', + release whatever resources the decomposed information occupies. + + E.g. if it's an XML-RPC string, Caller would have allocated memory + for the C string that represents the decomposed value of XML-RPC string, + and we release that memory. +-----------------------------------------------------------------------------*/ + switch (decompRootP->formatSpecChar) { + case 'i': + case 'b': + case 'd': + case 'n': + case 'I': + case 't': + case 'p': + /* Nothing was allocated; nothing to release */ + break; + case '8': + xmlrpc_strfree(*decompRootP->store.Tdatetime8.valueP); + break; + case 's': + xmlrpc_strfree(*decompRootP->store.Tstring.valueP); + break; + case 'w': + free((void*)*decompRootP->store.TwideString.valueP); + break; + case '6': + free((void*)*decompRootP->store.TbitString.valueP); + break; + case 'V': + xmlrpc_DECREF(*decompRootP->store.Tvalue.valueP); + break; + case 'A': + xmlrpc_DECREF(*decompRootP->store.TarrayVal.valueP); + break; + case 'S': + xmlrpc_DECREF(*decompRootP->store.TstructVal.valueP); + break; + case '(': + releaseDecompArray(decompRootP->store.Tarray, oldstyleMemMgmt); + break; + case '{': + releaseDecompStruct(decompRootP->store.Tstruct, oldstyleMemMgmt); + break; + } +} + + + +/* Prototype for recursive invocation: */ + +static void +decomposeValueWithTree(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + bool const oldstyleMemMgmt, + const struct decompTreeNode * const decompRootP); + + + +static void +validateArraySize(xmlrpc_env * const envP, + const xmlrpc_value * const arrayP, + struct arrayDecomp const arrayDecomp) { + + unsigned int size; + + size = xmlrpc_array_size(envP, arrayP); + if (!envP->fault_occurred) { + if (arrayDecomp.itemCnt > size) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, + "Format string requests %u items from array, but array " + "has only %u items.", arrayDecomp.itemCnt, size); + else if (arrayDecomp.itemCnt < size && !arrayDecomp.ignoreExcess) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, + "Format string requests exactly %u items from array, " + "but array has %u items. (A '*' at the end would avoid " + "this failure)", arrayDecomp.itemCnt, size); + } +} + + + +static void +parsearray(xmlrpc_env * const envP, + const xmlrpc_value * const arrayP, + struct arrayDecomp const arrayDecomp, + bool const oldstyleMemMgmt) { + + validateArraySize(envP, arrayP, arrayDecomp); + + if (!envP->fault_occurred) { + unsigned int doneCnt; + + doneCnt = 0; + while(doneCnt < arrayDecomp.itemCnt && !envP->fault_occurred) { + xmlrpc_value * itemP; + + xmlrpc_array_read_item(envP, arrayP, doneCnt, &itemP); + + if (!envP->fault_occurred) { + XMLRPC_ASSERT(doneCnt < ARRAY_SIZE(arrayDecomp.itemArray)); + decomposeValueWithTree(envP, itemP, oldstyleMemMgmt, + arrayDecomp.itemArray[doneCnt]); + + if (!envP->fault_occurred) + ++doneCnt; + + xmlrpc_DECREF(itemP); + } + } + if (envP->fault_occurred) { + /* Release the items we completed before we failed. */ + unsigned int i; + for (i = 0; i < doneCnt; ++i) + releaseDecomposition(arrayDecomp.itemArray[i], + oldstyleMemMgmt); + } + } +} + + + +static void +parsestruct(xmlrpc_env * const envP, + xmlrpc_value * const structP, + struct structDecomp const structDecomp, + bool const oldstyleMemMgmt) { + + unsigned int doneCount; + + doneCount = 0; /* No members done yet */ + + while (doneCount < structDecomp.mbrCnt && !envP->fault_occurred) { + const char * const key = structDecomp.mbrArray[doneCount].key; + + xmlrpc_value * valueP; + + xmlrpc_struct_read_value(envP, structP, key, &valueP); + + if (!envP->fault_occurred) { + decomposeValueWithTree( + envP, valueP, oldstyleMemMgmt, + structDecomp.mbrArray[doneCount].decompTreeP); + + if (!envP->fault_occurred) + ++doneCount; + + xmlrpc_DECREF(valueP); + } + } + + if (envP->fault_occurred) { + unsigned int i; + for (i = 0; i < doneCount; ++i) + releaseDecomposition(structDecomp.mbrArray[i].decompTreeP, + oldstyleMemMgmt); + } +} + + + +static void +readString(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP, + bool const oldstyleMemMgmt) { + + if (oldstyleMemMgmt) { + xmlrpc_read_string_old(envP, valueP, stringValueP); + } else + xmlrpc_read_string(envP, valueP, stringValueP); +} + + + +static void +readStringLp(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const char ** const stringValueP, + bool const oldstyleMemMgmt) { + + if (oldstyleMemMgmt) { + xmlrpc_read_string_lp_old(envP, valueP, lengthP, stringValueP); + } else + xmlrpc_read_string_lp(envP, valueP, lengthP, stringValueP); +} + + + +#if HAVE_UNICODE_WCHAR +static void +readStringW(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const wchar_t ** const stringValueP, + bool const oldstyleMemMgmt) { + + if (oldstyleMemMgmt) { + xmlrpc_read_string_w_old(envP, valueP, stringValueP); + } else + xmlrpc_read_string_w(envP, valueP, stringValueP); +} + + + +static void +readStringWLp(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + size_t * const lengthP, + const wchar_t ** const stringValueP, + bool const oldstyleMemMgmt) { + + if (oldstyleMemMgmt) { + xmlrpc_read_string_w_lp_old(envP, valueP, lengthP, stringValueP); + } else + xmlrpc_read_string_w_lp(envP, valueP, lengthP, stringValueP); +} +#endif + + +static void +readDatetime8Str(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP, + bool const oldstyleMemMgmt) { + + if (oldstyleMemMgmt) + xmlrpc_read_datetime_str_old(envP, valueP, stringValueP); + else + xmlrpc_read_datetime_str(envP, valueP, stringValueP); +} + + + +static void +readBase64(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const unsigned char ** const byteStringValueP, + bool const oldstyleMemMgmt) { + + if (oldstyleMemMgmt) + xmlrpc_read_base64_old(envP, valueP, lengthP, byteStringValueP); + else + xmlrpc_read_base64(envP, valueP, lengthP, byteStringValueP); +} + + +static void +decomposeValueWithTree(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + bool const oldstyleMemMgmt, + const struct decompTreeNode * const decompRootP) { +/*---------------------------------------------------------------------------- + Decompose XML-RPC value *valueP, given the decomposition tree + *decompRootP. The decomposition tree tells what structure *valueP + is expected to have and where to put the various components of it + (e.g. it says "it's an array of 3 integers. Put their values at + locations x, y, and z") +-----------------------------------------------------------------------------*/ + switch (decompRootP->formatSpecChar) { + case '-': + /* There's nothing to validate or return */ + break; + case 'i': + xmlrpc_read_int(envP, valueP, decompRootP->store.Tinteger.valueP); + break; + + case 'b': + xmlrpc_read_bool(envP, valueP, decompRootP->store.Tbool.valueP); + break; + + case 'd': + xmlrpc_read_double(envP, valueP, decompRootP->store.Tdouble.valueP); + break; + + case 't': + xmlrpc_read_datetime_sec(envP, valueP, + decompRootP->store.TdatetimeT.valueP); + break; + + case '8': + readDatetime8Str(envP, valueP, decompRootP->store.Tdatetime8.valueP, + oldstyleMemMgmt); + break; + + case 's': + if (decompRootP->store.Tstring.sizeP) + readStringLp(envP, valueP, + decompRootP->store.Tstring.sizeP, + decompRootP->store.Tstring.valueP, + oldstyleMemMgmt); + else + readString(envP, valueP, decompRootP->store.Tstring.valueP, + oldstyleMemMgmt); + break; + + case 'w': +#if HAVE_UNICODE_WCHAR + if (decompRootP->store.Tstring.sizeP) + readStringWLp(envP, valueP, + decompRootP->store.TwideString.sizeP, + decompRootP->store.TwideString.valueP, + oldstyleMemMgmt); + else + readStringW(envP, valueP, decompRootP->store.TwideString.valueP, + oldstyleMemMgmt); +#else + XMLRPC_ASSERT(false); +#endif /* HAVE_UNICODE_WCHAR */ + break; + + case '6': + readBase64(envP, valueP, + decompRootP->store.TbitString.sizeP, + decompRootP->store.TbitString.valueP, + oldstyleMemMgmt); + break; + + case 'n': + xmlrpc_read_nil(envP, valueP); + break; + + case 'I': + xmlrpc_read_i8(envP, valueP, decompRootP->store.Ti8.valueP); + break; + + case 'p': + xmlrpc_read_cptr(envP, valueP, decompRootP->store.Tcptr.valueP); + break; + + case 'V': + *decompRootP->store.Tvalue.valueP = valueP; + if (!oldstyleMemMgmt) + xmlrpc_INCREF(valueP); + break; + + case 'A': + if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_ARRAY) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value to be decomposed is of type " + "%s, but the 'A' specifier requires type ARRAY", + xmlrpc_type_name(xmlrpc_value_type(valueP))); + else { + *decompRootP->store.TarrayVal.valueP = valueP; + if (!oldstyleMemMgmt) + xmlrpc_INCREF(valueP); + } + break; + + case 'S': + if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_STRUCT) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value to be decomposed is of type " + "%s, but the 'S' specifier requires type STRUCT.", + xmlrpc_type_name(xmlrpc_value_type(valueP))); + else { + *decompRootP->store.TstructVal.valueP = valueP; + if (!oldstyleMemMgmt) + xmlrpc_INCREF(valueP); + } + break; + + case '(': + if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_ARRAY) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value to be decomposed is of type " + "%s, but the '(...)' specifier requires type ARRAY", + xmlrpc_type_name(xmlrpc_value_type(valueP))); + else + parsearray(envP, valueP, decompRootP->store.Tarray, + oldstyleMemMgmt); + break; + + case '{': + if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_STRUCT) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value to be decomposed is of type " + "%s, but the '{...}' specifier requires type STRUCT", + xmlrpc_type_name(xmlrpc_value_type(valueP))); + else + parsestruct(envP, valueP, decompRootP->store.Tstruct, + oldstyleMemMgmt); + break; + + default: + /* Every format character that is allowed in a decomposition tree + node is handled above. + */ + XMLRPC_ASSERT(false); + } +} + + +/* Forward declaration for recursive calls */ + +static void +createDecompTreeNext(xmlrpc_env * const envP, + const char ** const formatP, + va_listx * const argsP, + struct decompTreeNode ** const decompNodePP); + + + +static void +buildWideStringNode(xmlrpc_env * const envP ATTR_UNUSED, + const char ** const formatP, + va_listx * const argsP, + struct decompTreeNode * const decompNodeP) { + +#if HAVE_UNICODE_WCHAR + decompNodeP->store.TwideString.valueP = + (const wchar_t**) va_arg(argsP->v, wchar_t**); + if (**formatP == '#') { + decompNodeP->store.TwideString.sizeP = + (size_t*) va_arg(argsP->v, size_t**); + (*formatP)++; + } else + decompNodeP->store.TwideString.sizeP = NULL; +#else + xmlrpc_faultf(envP, + "This XML-RPC For C/C++ library was built without Unicode " + "wide character capability. 'w' isn't available."); +#endif /* HAVE_UNICODE_WCHAR */ +} + + + +static void +destroyDecompTree(struct decompTreeNode * const decompRootP) { + + switch (decompRootP->formatSpecChar) { + case '(': { + unsigned int i; + for (i = 0; i < decompRootP->store.Tarray.itemCnt; ++i) + destroyDecompTree(decompRootP->store.Tarray.itemArray[i]); + } break; + case '{': { + unsigned int i; + for (i = 0; i < decompRootP->store.Tstruct.mbrCnt; ++i) + destroyDecompTree( + decompRootP->store.Tstruct.mbrArray[i].decompTreeP); + } break; + } + + free(decompRootP); +} + + + +static void +processArraySpecTail(xmlrpc_env * const envP, + const char ** const formatP, + bool * const hasTrailingAsteriskP, + char const delim) { + + if (**formatP == '*') { + *hasTrailingAsteriskP = true; + + ++*formatP; + + if (!**formatP) + xmlrpc_faultf(envP, "missing closing delimiter ('%c')", delim); + else if (**formatP != delim) + xmlrpc_faultf(envP, "character following '*' in array " + "specification should be the closing delimiter " + "'%c', but is '%c'", delim, **formatP); + } else { + *hasTrailingAsteriskP = false; + + if (!**formatP) + xmlrpc_faultf(envP, "missing closing delimiter ('%c')", delim); + } + if (!envP->fault_occurred) + XMLRPC_ASSERT(**formatP == delim); +} + + + +static void +buildArrayDecompBranch(xmlrpc_env * const envP, + const char ** const formatP, + char const delim, + va_listx * const argsP, + struct decompTreeNode * const decompNodeP) { +/*---------------------------------------------------------------------------- + Fill in the decomposition tree node *decompNodeP to cover an array + whose items are described by *formatP. To wit, they are the values + described by successive format specifiers in *formatP up to but not + including the next 'delim' character. + + Plus, the last character before the delimiter might be a '*', which + means "ignore any additional items in the array." + + We create a node (and whole branch if required) to describe each array + item. + + The pointers to where those items are to be stored are given by + 'argsP'. + + We advance *formatP to the delimiter character, and advance 'argsP' + past whatever arguments we use. +-----------------------------------------------------------------------------*/ + unsigned int itemCnt; + /* Number of array items in the branch so far */ + + itemCnt = 0; /* Branch is empty so far */ + + while (**formatP && **formatP != delim && **formatP != '*' && + !envP->fault_occurred) { + if (itemCnt >= ARRAY_SIZE(decompNodeP->store.Tarray.itemArray)) + xmlrpc_faultf(envP, "Too many array items in format string. " + "The most items you can have for an array in " + "a format string is %u.", + ARRAY_SIZE(decompNodeP->store.Tarray.itemArray)); + else { + struct decompTreeNode * itemNodeP; + + createDecompTreeNext(envP, formatP, argsP, &itemNodeP); + + if (!envP->fault_occurred) + decompNodeP->store.Tarray.itemArray[itemCnt++] = itemNodeP; + } + } + if (!envP->fault_occurred) { + decompNodeP->store.Tarray.itemCnt = itemCnt; + processArraySpecTail(envP, formatP, + &decompNodeP->store.Tarray.ignoreExcess, + delim); + } + if (envP->fault_occurred) { + unsigned int i; + for (i = 0; i < itemCnt; ++i) + destroyDecompTree(decompNodeP->store.Tarray.itemArray[i]); + } +} + + + +static void +doStructValue(xmlrpc_env * const envP, + const char ** const formatP, + va_listx * const argsP, + struct mbrDecomp * const mbrP) { + + struct decompTreeNode * valueNodeP; + + mbrP->key = (const char*) va_arg(argsP->v, char*); + + createDecompTreeNext(envP, formatP, argsP, &valueNodeP); + + if (!envP->fault_occurred) + mbrP->decompTreeP = valueNodeP; +} + + + +static void +skipAsterisk(xmlrpc_env * const envP, + const char ** const formatP, + char const delim) { + + if (**formatP == '*') { + ++*formatP; + + if (!**formatP) + xmlrpc_faultf(envP, "missing closing delimiter ('%c')", delim); + else if (**formatP != delim) + xmlrpc_faultf(envP, "junk after '*' in the specifier of an " + "array. First character='%c'", **formatP); + } else + /* Conceptually, one can make it an error to leave some struct + members behind, but we have never had code that knows how to + recognize that case. + */ + xmlrpc_faultf(envP, + "You must put a trailing '*' in the specifiers for " + "struct members to signify it's OK if there are " + "additional members you didn't get."); +} + + + +static void +skipColon(xmlrpc_env * const envP, + const char ** const formatP, + char const delim) { + + if (**formatP == '\0') + xmlrpc_faultf(envP, "format string ends in the middle of a struct " + "member specifier"); + else if (**formatP == delim) + xmlrpc_faultf(envP, "member list ends in the middle of a member"); + else if (**formatP != ':') + xmlrpc_faultf(envP, "In a struct specifier, '%c' found " + "where a colon (':') separating key and " + "value was expected.", **formatP); +} + + + +static void +skipComma(xmlrpc_env * const envP, + const char ** const formatP, + char const delim) { + + if (**formatP && **formatP != delim) { + if (**formatP == ',') + ++*formatP; /* skip over comma */ + else + xmlrpc_faultf(envP, "'%c' where we expected a ',' " + "to separate struct members", **formatP); + } +} + + + +static void +buildStructDecompBranch(xmlrpc_env * const envP, + const char ** const formatP, + char const delim, + va_listx * const argsP, + struct decompTreeNode * const decompNodeP) { +/*---------------------------------------------------------------------------- + Fill in the decomposition tree node *decompNodeP to cover a struct + whose members are described by *formatP. To wit, they are the values + described by successive format specifiers in *formatP up to but not + including the next 'delim' character. + + We create a node (and whole branch if required) to describe each + struct member value. + + The pointers to where those values are to be stored are given by + 'argsP'. + + The names of the members to be extracted are also given by 'argsP'. + + We advance *formatP to the delimiter character, and advance 'argsP' + past whatever arguments we use. +-----------------------------------------------------------------------------*/ + unsigned int memberCnt; + /* Number of struct members in the branch so far */ + + memberCnt = 0; /* Branch is empty so far */ + + while (**formatP && **formatP != delim && **formatP != '*' && + !envP->fault_occurred) { + if (memberCnt >= ARRAY_SIZE(decompNodeP->store.Tstruct.mbrArray)) + xmlrpc_faultf(envP, + "Too many structure members in format string. " + "The most members you can specify in " + "a format string is %u.", + ARRAY_SIZE(decompNodeP->store.Tstruct.mbrArray)); + else { + struct mbrDecomp * const mbrP = + &decompNodeP->store.Tstruct.mbrArray[memberCnt]; + + if (**formatP != 's') + xmlrpc_faultf(envP, "In a struct specifier, the specifier " + "for the key is '%c', but it must be 's'.", + **formatP); + else { + ++*formatP; + + skipColon(envP, formatP, delim); + + if (!envP->fault_occurred) { + ++*formatP; + + doStructValue(envP, formatP, argsP, mbrP); + + if (!envP->fault_occurred) + ++memberCnt; + + skipComma(envP, formatP, delim); + } + } + } + } + decompNodeP->store.Tstruct.mbrCnt = memberCnt; + + if (!envP->fault_occurred) { + skipAsterisk(envP, formatP, delim); + if (!envP->fault_occurred) + XMLRPC_ASSERT(**formatP == delim); + } + + if (envP->fault_occurred) { + unsigned int i; + for (i = 0; i < memberCnt; ++i) + destroyDecompTree( + decompNodeP->store.Tstruct.mbrArray[i].decompTreeP); + } +} + + + +static void +createDecompTreeNext(xmlrpc_env * const envP, + const char ** const formatP, + va_listx * const argsP, + struct decompTreeNode ** const decompNodePP) { +/*---------------------------------------------------------------------------- + Create a branch of a decomposition tree that applies to the first + value described by '*formatP', and advance *formatP past the description + of that first value. E.g.: + + - If *formatP is "isb", we create a branch consisting of one + node -- for an integer. We advance *formatP by one character, so + it points to the "s". + + - If *formatP is "(isb)s", we create a branch that represents the + array (isb) and advance *formatP past the closing parenthesis to + point to the final "s". We return as *decompNodePP a pointer to + a node for the array, and that array in turn points to nodes for + each of the 3 array items: one for an integer, one for a string, + and one for a boolean. + + The locations at which the components of that value are to be + stored (which is the main contents of the branch we create) are + given by 'argsP'. + + Return as *decompNodeP a pointer to the root node of the branch we + generate. +-----------------------------------------------------------------------------*/ + struct decompTreeNode * decompNodeP; + + MALLOCVAR(decompNodeP); + + if (decompNodeP == NULL) + xmlrpc_faultf(envP, "Could not allocate space for a decomposition " + "tree node"); + else { + decompNodeP->formatSpecChar = *(*formatP)++; + + switch (decompNodeP->formatSpecChar) { + case '-': + /* There's nothing to store */ + break; + case 'i': + decompNodeP->store.Tinteger.valueP = + (xmlrpc_int32*) va_arg(argsP->v, xmlrpc_int32*); + break; + + case 'b': + decompNodeP->store.Tbool.valueP = + (xmlrpc_bool*) va_arg(argsP->v, xmlrpc_bool*); + break; + + case 'd': + decompNodeP->store.Tdouble.valueP = + (double*) va_arg(argsP->v, double*); + break; + + case 't': + decompNodeP->store.TdatetimeT.valueP = + va_arg(argsP->v, time_t*); + break; + + case '8': + decompNodeP->store.Tdatetime8.valueP = + (const char**) va_arg(argsP->v, char**); + break; + + case 's': + decompNodeP->store.Tstring.valueP = + (const char**) va_arg(argsP->v, char**); + if (**formatP == '#') { + decompNodeP->store.Tstring.sizeP = + (size_t*) va_arg(argsP->v, size_t**); + ++*formatP; + } else + decompNodeP->store.Tstring.sizeP = NULL; + break; + + case 'w': + buildWideStringNode(envP, formatP, argsP, decompNodeP); + break; + + case '6': + decompNodeP->store.TbitString.valueP = + (const unsigned char**) va_arg(argsP->v, unsigned char**); + decompNodeP->store.TbitString.sizeP = + (size_t*) va_arg(argsP->v, size_t**); + break; + + case 'n': + /* There's no value to store */ + break; + + case 'I': + decompNodeP->store.Ti8.valueP = + (xmlrpc_int64 *) va_arg(argsP->v, xmlrpc_int64 *); + break; + + case 'p': + decompNodeP->store.Tcptr.valueP = + (void**) va_arg(argsP->v, void**); + break; + + case 'V': + decompNodeP->store.Tvalue.valueP = + (xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**); + break; + + case 'A': + decompNodeP->store.TarrayVal.valueP = + (xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**); + break; + + case 'S': + decompNodeP->store.TstructVal.valueP = + (xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**); + break; + + case '(': + buildArrayDecompBranch(envP, formatP, ')', argsP, decompNodeP); + ++(*formatP); /* skip past closing ')' */ + break; + + case '{': + buildStructDecompBranch(envP, formatP, '}', argsP, decompNodeP); + ++(*formatP); /* skip past closing '}' */ + break; + + default: + xmlrpc_faultf(envP, "Invalid format character '%c'", + decompNodeP->formatSpecChar); + } + if (envP->fault_occurred) + free(decompNodeP); + else + *decompNodePP = decompNodeP; + } +} + + + +static void +createDecompTree(xmlrpc_env * const envP, + const char * const format, + va_listx const args, + struct decompTreeNode ** const decompRootPP) { + + const char * formatCursor; + struct decompTreeNode * decompRootP; + va_listx currentArgs; + + currentArgs = args; + formatCursor = &format[0]; + createDecompTreeNext(envP, &formatCursor, ¤tArgs, &decompRootP); + if (!envP->fault_occurred) { + if (*formatCursor != '\0') + xmlrpc_faultf(envP, "format string '%s' has garbage at the end: " + "'%s'. It should be a specifier of a single value " + "(but that might be a complex value, such as an " + "array)", format, formatCursor); + + if (envP->fault_occurred) + destroyDecompTree(decompRootP); + else + *decompRootPP = decompRootP; + } +} + + + +static void +decomposeValue(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + bool const oldstyleMemMgmt, + const char * const format, + va_listx const args) { + + struct decompTreeNode * decompRootP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(valueP); + XMLRPC_ASSERT(format != NULL); + + createDecompTree(envP, format, args, &decompRootP); + + if (!envP->fault_occurred) { + decomposeValueWithTree(envP, valueP, oldstyleMemMgmt, decompRootP); + + destroyDecompTree(decompRootP); + } +} + + + +void +xmlrpc_decompose_value_va(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const char * const format, + va_list const args) { + + bool const oldstyleMemMgtFalse = false; + va_listx argsx; + + init_va_listx(&argsx, args); + + decomposeValue(envP, valueP, oldstyleMemMgtFalse, format, argsx); +} + + + +void +xmlrpc_decompose_value(xmlrpc_env * const envP, + xmlrpc_value * const value, + const char * const format, + ...) { + + va_list args; + + va_start(args, format); + xmlrpc_decompose_value_va(envP, value, format, args); + va_end(args); +} + + + +void +xmlrpc_parse_value_va(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const char * const format, + va_list const args) { + + bool const oldstyleMemMgmtTrue = true; + va_listx argsx; + + init_va_listx(&argsx, args); + + decomposeValue(envP, valueP, oldstyleMemMgmtTrue, format, argsx); +} + + + +void +xmlrpc_parse_value(xmlrpc_env * const envP, + xmlrpc_value * const value, + const char * const format, + ...) { + + va_list args; + + va_start(args, format); + xmlrpc_parse_value_va(envP, value, format, args); + va_end(args); +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_expat.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_expat.c new file mode 100644 index 0000000..9e6c37e --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_expat.c @@ -0,0 +1,487 @@ +/* Copyright information is at end of file */ + +#include "xmlrpc_config.h" + +#include +#include +#include + +#include /* Expat */ + +#include "bool.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/xmlparser.h" + +/* Define the contents of our internal structure. */ +struct _xml_element { + struct _xml_element *_parent; + char *_name; + xmlrpc_mem_block _cdata; /* char */ + xmlrpc_mem_block _children; /* xml_element* */ +}; + +/* Check that we're using expat in UTF-8 mode, not wchar_t mode. +** If you need to use expat in wchar_t mode, write a subroutine to +** copy a wchar_t string to a char string & return an error for +** any non-ASCII characters. Then call this subroutine on all +** XML_Char strings passed to our event handlers before using the +** data. */ +/* #if sizeof(char) != sizeof(XML_Char) +** #error expat must define XML_Char to be a regular char. +** #endif +*/ + +#define XMLRPC_ASSERT_ELEM_OK(elem) \ + XMLRPC_ASSERT((elem) != NULL && (elem)->_name != XMLRPC_BAD_POINTER) + + +/*========================================================================= +** xml_element_new +**========================================================================= +** Create a new xml_element. This routine isn't exported, because the +** arguments are implementation-dependent. +*/ + +static xml_element * +xml_element_new (xmlrpc_env * const env, + const char * const name) { + + xml_element *retval; + int name_valid, cdata_valid, children_valid; + + XMLRPC_ASSERT_ENV_OK(env); + XMLRPC_ASSERT(name != NULL); + + /* Set up our error-handling preconditions. */ + retval = NULL; + name_valid = cdata_valid = children_valid = 0; + + /* Allocate our xml_element structure. */ + retval = (xml_element*) malloc(sizeof(xml_element)); + XMLRPC_FAIL_IF_NULL(retval, env, XMLRPC_INTERNAL_ERROR, + "Couldn't allocate memory for XML element"); + + /* Set our parent field to NULL. */ + retval->_parent = NULL; + + /* Copy over the element name. */ + retval->_name = (char*) malloc(strlen(name) + 1); + XMLRPC_FAIL_IF_NULL(retval->_name, env, XMLRPC_INTERNAL_ERROR, + "Couldn't allocate memory for XML element"); + name_valid = 1; + strcpy(retval->_name, name); + + /* Initialize a block to hold our CDATA. */ + XMLRPC_TYPED_MEM_BLOCK_INIT(char, env, &retval->_cdata, 0); + XMLRPC_FAIL_IF_FAULT(env); + cdata_valid = 1; + + /* Initialize a block to hold our child elements. */ + XMLRPC_TYPED_MEM_BLOCK_INIT(xml_element*, env, &retval->_children, 0); + XMLRPC_FAIL_IF_FAULT(env); + children_valid = 1; + + cleanup: + if (env->fault_occurred) { + if (retval) { + if (name_valid) + free(retval->_name); + if (cdata_valid) + xmlrpc_mem_block_clean(&retval->_cdata); + if (children_valid) + xmlrpc_mem_block_clean(&retval->_children); + free(retval); + } + return NULL; + } else { + return retval; + } +} + + +/*========================================================================= +** xml_element_free +**========================================================================= +** Blow away an existing element & all of its child elements. +*/ +void +xml_element_free(xml_element * const elem) { + + xmlrpc_mem_block *children; + int size, i; + xml_element **contents; + + XMLRPC_ASSERT_ELEM_OK(elem); + + free(elem->_name); + elem->_name = XMLRPC_BAD_POINTER; + xmlrpc_mem_block_clean(&elem->_cdata); + + /* Deallocate all of our children recursively. */ + children = &elem->_children; + contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, children); + size = XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, children); + for (i = 0; i < size; i++) + xml_element_free(contents[i]); + + xmlrpc_mem_block_clean(&elem->_children); + free(elem); +} + + +/*========================================================================= +** Miscellaneous Accessors +**========================================================================= +** Return the fields of the xml_element. See the header for more +** documentation on each function works. +*/ + + + +const char * +xml_element_name(const xml_element * const elemP) { + + XMLRPC_ASSERT_ELEM_OK(elemP); + return elemP->_name; +} + + + +/* The result of this function is NOT VALID until the end_element handler +** has been called! */ +size_t xml_element_cdata_size (xml_element *elem) +{ + XMLRPC_ASSERT_ELEM_OK(elem); + return XMLRPC_TYPED_MEM_BLOCK_SIZE(char, &elem->_cdata) - 1; +} + +char *xml_element_cdata (xml_element *elem) +{ + XMLRPC_ASSERT_ELEM_OK(elem); + return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &elem->_cdata); +} + + + +size_t +xml_element_children_size(const xml_element * const elemP) { + XMLRPC_ASSERT_ELEM_OK(elemP); + return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element *, &elemP->_children); +} + + + +xml_element ** +xml_element_children(const xml_element * const elemP) { + XMLRPC_ASSERT_ELEM_OK(elemP); + return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element *, &elemP->_children); +} + + + +/*========================================================================= +** Internal xml_element Utility Functions +**========================================================================= +*/ + +static void xml_element_append_cdata (xmlrpc_env *env, + xml_element *elem, + char *cdata, + size_t size) +{ + XMLRPC_ASSERT_ENV_OK(env); + XMLRPC_ASSERT_ELEM_OK(elem); + + XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, &elem->_cdata, cdata, size); +} + +/* Whether or not this function succeeds, it takes ownership of the 'child' +** argument. +** WARNING - This is the exact opposite of the usual memory ownership +** rules for xmlrpc_value! So please pay attention. */ +static void xml_element_append_child (xmlrpc_env *env, + xml_element *elem, + xml_element *child) +{ + XMLRPC_ASSERT_ENV_OK(env); + XMLRPC_ASSERT_ELEM_OK(elem); + XMLRPC_ASSERT_ELEM_OK(child); + XMLRPC_ASSERT(child->_parent == NULL); + + XMLRPC_TYPED_MEM_BLOCK_APPEND(xml_element*, env, &elem->_children, + &child, 1); + if (!env->fault_occurred) + child->_parent = elem; + else + xml_element_free(child); +} + + +/*========================================================================= +** Our parse context. We pass this around as expat user data. +**========================================================================= +*/ + +typedef struct { + xmlrpc_env env; + xml_element * rootP; + xml_element * currentP; +} parseContext; + + +/*========================================================================= +** Expat Event Handler Functions +**========================================================================= +*/ + +static void +startElement(void * const userData, + XML_Char * const name, + XML_Char ** const atts ATTR_UNUSED) { + + parseContext * const contextP = userData; + + XMLRPC_ASSERT(contextP != NULL); + XMLRPC_ASSERT(name != NULL); + + if (!contextP->env.fault_occurred) { + xml_element * elemP; + + elemP = xml_element_new(&contextP->env, name); + if (!contextP->env.fault_occurred) { + XMLRPC_ASSERT(elemP != NULL); + + /* Insert the new element in the appropriate place. */ + if (!contextP->rootP) { + /* No root yet, so this element must be the root. */ + contextP->rootP = elemP; + contextP->currentP = elemP; + } else { + XMLRPC_ASSERT(contextP->currentP != NULL); + + /* (We need to watch our error handling invariants + very carefully here. Read the docs for + xml_element_append_child. + */ + xml_element_append_child(&contextP->env, contextP->currentP, + elemP); + if (!contextP->env.fault_occurred) + contextP->currentP = elemP; + } + if (contextP->env.fault_occurred) + xml_element_free(elemP); + } + if (contextP->env.fault_occurred) { + /* Having changed *contextP to reflect failure, we are responsible + for undoing everything that has been done so far in this + context. + */ + if (contextP->rootP) + xml_element_free(contextP->rootP); + } + } +} + + + +static void +endElement(void * const userData, + XML_Char * const name ATTR_UNUSED) { + + parseContext * const contextP = userData; + + XMLRPC_ASSERT(contextP != NULL); + XMLRPC_ASSERT(name != NULL); + + if (!contextP->env.fault_occurred) { + /* I think Expat enforces these facts: */ + XMLRPC_ASSERT(xmlrpc_streq(name, contextP->currentP->_name)); + XMLRPC_ASSERT(contextP->currentP->_parent != NULL || + contextP->currentP == contextP->rootP); + + /* Add a trailing NUL to our cdata. */ + xml_element_append_cdata(&contextP->env, contextP->currentP, "\0", 1); + if (!contextP->env.fault_occurred) + /* Pop our "stack" of elements. */ + contextP->currentP = contextP->currentP->_parent; + + if (contextP->env.fault_occurred) { + /* Having changed *contextP to reflect failure, we are responsible + for undoing everything that has been done so far in this + context. + */ + if (contextP->rootP) + xml_element_free(contextP->rootP); + } + } +} + + + +static void +characterData(void * const userData, + XML_Char * const s, + int const len) { +/*---------------------------------------------------------------------------- + This is an Expat character data (cdata) handler. When an Expat + parser comes across cdata, he calls one of these with the cdata as + argument. He can call it multiple times for consecutive cdata. + + We simply append the cdata to the cdata buffer for whatever XML + element the parser is presently parsing. +-----------------------------------------------------------------------------*/ + parseContext * const contextP = userData; + + XMLRPC_ASSERT(contextP != NULL); + XMLRPC_ASSERT(s != NULL); + XMLRPC_ASSERT(len >= 0); + + if (!contextP->env.fault_occurred) { + XMLRPC_ASSERT(contextP->currentP != NULL); + + xml_element_append_cdata(&contextP->env, contextP->currentP, s, len); + } +} + + + +static void +createParser(xmlrpc_env * const envP, + parseContext * const contextP, + XML_Parser * const parserP) { +/*---------------------------------------------------------------------------- + Create an Expat parser to parse our XML. +-----------------------------------------------------------------------------*/ + XML_Parser parser; + + parser = xmlrpc_XML_ParserCreate(NULL); + if (parser == NULL) + xmlrpc_faultf(envP, "Could not create expat parser"); + else { + /* Initialize our parse context. */ + xmlrpc_env_init(&contextP->env); + contextP->rootP = NULL; + contextP->currentP = NULL; + + xmlrpc_XML_SetUserData(parser, contextP); + xmlrpc_XML_SetElementHandler( + parser, + (XML_StartElementHandler) startElement, + (XML_EndElementHandler) endElement); + xmlrpc_XML_SetCharacterDataHandler( + parser, + (XML_CharacterDataHandler) characterData); + + *parserP = parser; + } +} + + + +static void +destroyParser(XML_Parser const parser, + parseContext * const contextP) { + + xmlrpc_env_clean(&contextP->env); + + xmlrpc_XML_ParserFree(parser); +} + + + +void +xml_parse(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen, + xml_element ** const resultPP) { +/*---------------------------------------------------------------------------- + Parse the XML text 'xmlData', of length 'xmlDataLen'. Return the + description of the element that the XML text contains as *resultPP. +-----------------------------------------------------------------------------*/ + /* + This is an Expat driver. + + We set up event-based parser handlers for Expat and set Expat loose + on the XML. Expat walks through the XML, calling our handlers along + the way. Our handlers build up the element description in our + 'context' variable, so that when Expat is finished, our results are + in 'context' and we just have to pluck them out. + + We should allow the user to specify the encoding in 'xmlData', but + we don't. + */ + XML_Parser parser; + parseContext context; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(xmlData != NULL); + + createParser(envP, &context, &parser); + + if (!envP->fault_occurred) { + bool ok; + + ok = xmlrpc_XML_Parse(parser, xmlData, xmlDataLen, 1); + /* sets 'context', *envP */ + if (!ok) { + /* Expat failed on its own to parse it -- this is not an error + that our handlers detected. + */ + xmlrpc_env_set_fault( + envP, XMLRPC_PARSE_ERROR, + xmlrpc_XML_GetErrorString(parser)); + if (!context.env.fault_occurred) { + /* Have to clean up what our handlers built before Expat + barfed. + */ + if (context.rootP) + xml_element_free(context.rootP); + } + } else { + /* Expat got through the XML OK, but when it called our handlers, + they might have detected a problem. They would have noted + such a problem in *contextP. + */ + if (context.env.fault_occurred) + xmlrpc_env_set_fault_formatted( + envP, context.env.fault_code, + "XML doesn't parse. %s", context.env.fault_string); + else { + XMLRPC_ASSERT(context.rootP != NULL); + XMLRPC_ASSERT(context.currentP == NULL); + + *resultPP = context.rootP; + } + } + destroyParser(parser, &context); + } +} + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_libxml2.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_libxml2.c new file mode 100644 index 0000000..da767a3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_libxml2.c @@ -0,0 +1,432 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** Copyright (C) 2002 Ximian, Inc. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#include "xmlrpc_config.h" + +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/xmlparser.h" + +/* Define the contents of our internal structure. */ +struct _xml_element { + struct _xml_element *_parent; + char *_name; + xmlrpc_mem_block _cdata; /* char */ + xmlrpc_mem_block _children; /* xml_element* */ +}; + +#define XMLRPC_ASSERT_ELEM_OK(elem) \ + XMLRPC_ASSERT((elem) != NULL && (elem)->_name != XMLRPC_BAD_POINTER) + + +/*========================================================================= +** xml_element_new +**========================================================================= +** Create a new xml_element. This routine isn't exported, because the +** arguments are implementation-dependent. +*/ + +static xml_element *xml_element_new (xmlrpc_env *env, char *name) +{ + xml_element *retval; + int name_valid, cdata_valid, children_valid; + + XMLRPC_ASSERT_ENV_OK(env); + XMLRPC_ASSERT(name != NULL); + + /* Set up our error-handling preconditions. */ + retval = NULL; + name_valid = cdata_valid = children_valid = 0; + + /* Allocate our xml_element structure. */ + retval = (xml_element*) malloc(sizeof(xml_element)); + XMLRPC_FAIL_IF_NULL(retval, env, XMLRPC_INTERNAL_ERROR, + "Couldn't allocate memory for XML element"); + + /* Set our parent field to NULL. */ + retval->_parent = NULL; + + /* Copy over the element name. */ + retval->_name = (char*) malloc(strlen(name) + 1); + XMLRPC_FAIL_IF_NULL(retval->_name, env, XMLRPC_INTERNAL_ERROR, + "Couldn't allocate memory for XML element"); + name_valid = 1; + strcpy(retval->_name, name); + + /* Initialize a block to hold our CDATA. */ + XMLRPC_TYPED_MEM_BLOCK_INIT(char, env, &retval->_cdata, 0); + XMLRPC_FAIL_IF_FAULT(env); + cdata_valid = 1; + + /* Initialize a block to hold our child elements. */ + XMLRPC_TYPED_MEM_BLOCK_INIT(xml_element*, env, &retval->_children, 0); + XMLRPC_FAIL_IF_FAULT(env); + children_valid = 1; + + cleanup: + if (env->fault_occurred) { + if (retval) { + if (name_valid) + free(retval->_name); + if (cdata_valid) + xmlrpc_mem_block_clean(&retval->_cdata); + if (children_valid) + xmlrpc_mem_block_clean(&retval->_children); + free(retval); + } + return NULL; + } else { + return retval; + } +} + + +/*========================================================================= +** xml_element_free +**========================================================================= +** Blow away an existing element & all of its child elements. +*/ + +void xml_element_free (xml_element *elem) +{ + xmlrpc_mem_block *children; + int size, i; + xml_element **contents; + + XMLRPC_ASSERT_ELEM_OK(elem); + + free(elem->_name); + elem->_name = XMLRPC_BAD_POINTER; + xmlrpc_mem_block_clean(&elem->_cdata); + + /* Deallocate all of our children recursively. */ + children = &elem->_children; + contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, children); + size = XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, children); + for (i = 0; i < size; i++) + xml_element_free(contents[i]); + + xmlrpc_mem_block_clean(&elem->_children); + free(elem); +} + + +/*========================================================================= +** Miscellaneous Accessors +**========================================================================= +** Return the fields of the xml_element. See the header for more +** documentation on each function works. +*/ + +const char *xml_element_name (const xml_element * const elem) +{ + XMLRPC_ASSERT_ELEM_OK(elem); + return elem->_name; +} + +/* The result of this function is NOT VALID until the end_element handler +** has been called! */ +size_t xml_element_cdata_size (xml_element *elem) +{ + XMLRPC_ASSERT_ELEM_OK(elem); + return XMLRPC_TYPED_MEM_BLOCK_SIZE(char, &elem->_cdata) - 1; +} + +char *xml_element_cdata (xml_element *elem) +{ + XMLRPC_ASSERT_ELEM_OK(elem); + return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &elem->_cdata); +} + +size_t xml_element_children_size (const xml_element *const elem) +{ + XMLRPC_ASSERT_ELEM_OK(elem); + return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, &elem->_children); +} + +xml_element **xml_element_children (const xml_element *const elem) +{ + XMLRPC_ASSERT_ELEM_OK(elem); + return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, &elem->_children); +} + + +/*========================================================================= +** Internal xml_element Utility Functions +**========================================================================= +*/ + +static void xml_element_append_cdata (xmlrpc_env *env, + xml_element *elem, + char *cdata, + size_t size) +{ + XMLRPC_ASSERT_ENV_OK(env); + XMLRPC_ASSERT_ELEM_OK(elem); + + XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, &elem->_cdata, cdata, size); +} + +/* Whether or not this function succeeds, it takes ownership of the 'child' +** argument. +** WARNING - This is the exact opposite of the usual memory ownership +** rules for xmlrpc_value! So please pay attention. */ +static void xml_element_append_child (xmlrpc_env *env, + xml_element *elem, + xml_element *child) +{ + XMLRPC_ASSERT_ENV_OK(env); + XMLRPC_ASSERT_ELEM_OK(elem); + XMLRPC_ASSERT_ELEM_OK(child); + XMLRPC_ASSERT(child->_parent == NULL); + + XMLRPC_TYPED_MEM_BLOCK_APPEND(xml_element*, env, &elem->_children, + &child, 1); + if (!env->fault_occurred) + child->_parent = elem; + else + xml_element_free(child); +} + + +/*========================================================================= +** Our parse context. We pass this around as libxml user data. +**========================================================================= +*/ + +typedef struct { + xmlrpc_env *env; + xml_element *root; + xml_element *current; +} parse_context; + + +/*========================================================================= +** LibXML Event Handler Functions +**========================================================================= +*/ + +static void +start_element(void * const user_data, + const xmlChar * const name, + const xmlChar ** const attrs ATTR_UNUSED) { + + parse_context *context; + xml_element *elem, *new_current; + + XMLRPC_ASSERT(user_data != NULL && name != NULL); + + /* Get our context and see if an error has already occured. */ + context = (parse_context*) user_data; + if (!context->env->fault_occurred) { + + /* Set up our error-handling preconditions. */ + elem = NULL; + + /* Build a new element. */ + elem = xml_element_new(context->env, (char *) name); + XMLRPC_FAIL_IF_FAULT(context->env); + + /* Insert it in the appropriate place. */ + if (!context->root) { + context->root = elem; + context->current = elem; + elem = NULL; + } else { + XMLRPC_ASSERT(context->current != NULL); + + /* (We need to watch our error handling invariants very carefully + ** here. Read the docs for xml_element_append_child. */ + new_current = elem; + xml_element_append_child(context->env, context->current, elem); + elem = NULL; + XMLRPC_FAIL_IF_FAULT(context->env); + context->current = new_current; + } + + cleanup: + if (elem) + xml_element_free(elem); + } +} + + + +static void +end_element(void * const user_data, + const xmlChar * const name ATTR_UNUSED) { + + parse_context *context; + + XMLRPC_ASSERT(user_data != NULL && name != NULL); + + /* Get our context and see if an error has already occured. */ + context = (parse_context*) user_data; + if (!context->env->fault_occurred) { + + /* XXX - I think expat enforces these facts, but I want to be sure. + ** If one of these assertion ever fails, it should be replaced by a + ** non-assertion runtime error check. */ + XMLRPC_ASSERT(strcmp(name, context->current->_name) == 0); + XMLRPC_ASSERT(context->current->_parent != NULL || + context->current == context->root); + + /* Add a trailing '\0' to our cdata. */ + xml_element_append_cdata(context->env, context->current, "\0", 1); + XMLRPC_FAIL_IF_FAULT(context->env); + + /* Pop our "stack" of elements. */ + context->current = context->current->_parent; + + cleanup: + return; + } +} + +static void character_data (void *user_data, const xmlChar *s, int len) +{ + parse_context *context; + + XMLRPC_ASSERT(user_data != NULL && s != NULL && len >= 0); + + /* Get our context and see if an error has already occured. */ + context = (parse_context*) user_data; + if (!context->env->fault_occurred) { + + XMLRPC_ASSERT(context->current != NULL); + + xml_element_append_cdata(context->env, context->current, (char *) s, len); + XMLRPC_FAIL_IF_FAULT(context->env); + + cleanup: + return; + } +} + + +/*========================================================================= +** LibXML Driver +**========================================================================= +** XXX - We should allow the user to specify the encoding of our xml_data. +*/ + +static xmlSAXHandler sax_handler = { + NULL, /* internalSubset */ + NULL, /* isStandalone */ + NULL, /* hasInternalSubset */ + NULL, /* hasExternalSubset */ + NULL, /* resolveEntity */ + NULL, /* getEntity */ + NULL, /* entityDecl */ + NULL, /* notationDecl */ + NULL, /* attributeDecl */ + NULL, /* elementDecl */ + NULL, /* unparsedEntityDecl */ + NULL, /* setDocumentLocator */ + NULL, /* startDocument */ + NULL, /* endDocument */ + start_element, /* startElement */ + end_element, /* endElement */ + NULL, /* reference */ + character_data, /* characters */ + NULL, /* ignorableWhitespace */ + NULL, /* processingInstruction */ + NULL, /* comment */ + NULL, /* warning */ + NULL, /* error */ + NULL, /* fatalError */ + NULL, /* getParameterEntity */ + NULL, /* cdataBlock */ + NULL, /* externalSubset */ + 1 /* initialized */ + + /* Following are SAX2 fields. Any ifdef here? */ + + ,NULL, /* _private */ + NULL, /* startElementNs */ + NULL, /* endElementNs */ + NULL /* serror */ +}; + + + +void +xml_parse(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen, + xml_element ** const resultPP) { + + parse_context context; + xmlParserCtxt *parser; + int err; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(xmlData != NULL && xmlDataLen >= 0); + + /* Set up our error-handling preconditions. */ + parser = NULL; + context.root = NULL; + + /* Set up the rest of our parse context. */ + context.env = envP; + context.current = NULL; + + /* Set up our XML parser. */ + parser = xmlCreatePushParserCtxt(&sax_handler, &context, NULL, 0, NULL); + XMLRPC_FAIL_IF_NULL(parser, envP, XMLRPC_INTERNAL_ERROR, + "Could not create expat parser"); + + /* Parse our data. */ + err = xmlParseChunk(parser, xmlData, xmlDataLen, 1); + if (err) + XMLRPC_FAIL(envP, XMLRPC_PARSE_ERROR, "XML parsing failed"); + XMLRPC_FAIL_IF_FAULT(envP); + + /* Perform some sanity checks. */ + XMLRPC_ASSERT(context.root != NULL); + XMLRPC_ASSERT(context.current == NULL); + + *resultPP = context.root; + + cleanup: + if (parser) + xmlFreeParserCtxt(parser); + + if (envP->fault_occurred) { + if (context.root) + xml_element_free(context.root); + } +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_parse.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_parse.c new file mode 100644 index 0000000..43d9d54 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_parse.c @@ -0,0 +1,633 @@ +/* Copyright information is at end of file. */ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include +#include +#include + +#include "bool.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/xmlparser.h" +#include "parse_value.h" + + +/* Notes about XML-RPC XML documents: + + Contain CDATA: methodName, i4, int, boolean, string, double, + dateTime.iso8601, base64, name + + We attempt to validate the structure of the XML document carefully. + We also try *very* hard to handle malicious data gracefully, and without + leaking memory. + + The CHECK_NAME and CHECK_CHILD_COUNT macros examine an XML element, and + invoke XMLRPC_FAIL if something looks wrong. +*/ + +#define CHECK_NAME(env,elem,name) \ + do \ + if (!xmlrpc_streq((name), xml_element_name(elem))) \ + XMLRPC_FAIL2(env, XMLRPC_PARSE_ERROR, \ + "Expected element of type <%s>, found <%s>", \ + (name), xml_element_name(elem)); \ + while (0) + +#define CHECK_CHILD_COUNT(env,elem,count) \ + do \ + if (xml_element_children_size(elem) != (count)) \ + XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR, \ + "Expected <%s> to have %d children, found %d", \ + xml_element_name(elem), (count), \ + xml_element_children_size(elem)); \ + while (0) + +static xml_element * +get_child_by_name (xmlrpc_env *env, xml_element *parent, char *name) +{ + size_t child_count, i; + xml_element **children; + + children = xml_element_children(parent); + child_count = xml_element_children_size(parent); + for (i = 0; i < child_count; i++) { + if (xmlrpc_streq(xml_element_name(children[i]), name)) + return children[i]; + } + + xmlrpc_env_set_fault_formatted(env, XMLRPC_PARSE_ERROR, + "Expected <%s> to have child <%s>", + xml_element_name(parent), name); + return NULL; +} + + + +static void +setParseFault(xmlrpc_env * const envP, + const char * const format, + ...) { + + va_list args; + va_start(args, format); + xmlrpc_set_fault_formatted_v(envP, XMLRPC_PARSE_ERROR, format, args); + va_end(args); +} + + + +/*========================================================================= +** convert_params +**========================================================================= +** Convert an XML element representing a list of params into an +** xmlrpc_value (of type array). +*/ + +static xmlrpc_value * +convert_params(xmlrpc_env * const envP, + const xml_element * const elemP) { +/*---------------------------------------------------------------------------- + Convert an XML element representing a list of parameters (i.e. a + element) to an xmlrpc_value of type array. Note that an + array is normally represented in XML by a element. We use + type xmlrpc_value to represent the parameter list just for convenience. +-----------------------------------------------------------------------------*/ + xmlrpc_value *array, *item; + int size, i; + xml_element **params, *param, *value; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(elemP != NULL); + + /* Set up our error-handling preconditions. */ + array = item = NULL; + + /* Allocate an array to hold our parameters. */ + array = xmlrpc_build_value(envP, "()"); + XMLRPC_FAIL_IF_FAULT(envP); + + /* We're responsible for checking our own element name. */ + CHECK_NAME(envP, elemP, "params"); + + /* Iterate over our children. */ + size = xml_element_children_size(elemP); + params = xml_element_children(elemP); + for (i = 0; i < size; ++i) { + unsigned int const maxNest = xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID); + + param = params[i]; + CHECK_NAME(envP, param, "param"); + CHECK_CHILD_COUNT(envP, param, 1); + + value = xml_element_children(param)[0]; + + CHECK_NAME(envP, value, "value"); + + xmlrpc_parseValue(envP, maxNest, value, &item); + XMLRPC_FAIL_IF_FAULT(envP); + + xmlrpc_array_append_item(envP, array, item); + xmlrpc_DECREF(item); + item = NULL; + XMLRPC_FAIL_IF_FAULT(envP); + } + + cleanup: + if (envP->fault_occurred) { + if (array) + xmlrpc_DECREF(array); + if (item) + xmlrpc_DECREF(item); + return NULL; + } + return array; +} + + + +static void +parseCallXml(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlLen, + xml_element ** const callElemPP) { +/*---------------------------------------------------------------------------- + Parse the XML of an XML-RPC call. +-----------------------------------------------------------------------------*/ + xml_element * callElemP; + xmlrpc_env env; + + xmlrpc_env_init(&env); + xml_parse(&env, xmlData, xmlLen, &callElemP); + if (env.fault_occurred) + xmlrpc_env_set_fault_formatted( + envP, env.fault_code, "Call is not valid XML. %s", + env.fault_string); + else { + if (!xmlrpc_streq(xml_element_name(callElemP), "methodCall")) + setParseFault(envP, + "XML-RPC call should be a element. " + "Instead, we have a <%s> element.", + xml_element_name(callElemP)); + + if (!envP->fault_occurred) + *callElemPP = callElemP; + + if (envP->fault_occurred) + xml_element_free(callElemP); + } + xmlrpc_env_clean(&env); +} + + + +static void +parseMethodNameElement(xmlrpc_env * const envP, + xml_element * const nameElemP, + const char ** const methodNameP) { + + XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(nameElemP), "methodName")); + + if (xml_element_children_size(nameElemP) > 0) + setParseFault(envP, "A element should not have " + "children. This one has %u of them.", + xml_element_children_size(nameElemP)); + else { + const char * const cdata = xml_element_cdata(nameElemP); + + xmlrpc_validate_utf8(envP, cdata, strlen(cdata)); + + if (!envP->fault_occurred) { + *methodNameP = strdup(cdata); + if (*methodNameP == NULL) + xmlrpc_faultf(envP, + "Could not allocate memory for method name"); + } + } +} + + + +static void +parseCallChildren(xmlrpc_env * const envP, + xml_element * const callElemP, + const char ** const methodNameP, + xmlrpc_value ** const paramArrayPP ) { +/*---------------------------------------------------------------------------- + Parse the children of a XML element *callElemP. They should + be and . +-----------------------------------------------------------------------------*/ + size_t const callChildCount = xml_element_children_size(callElemP); + + xml_element * nameElemP; + + XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(callElemP), "methodCall")); + + nameElemP = get_child_by_name(envP, callElemP, "methodName"); + + if (!envP->fault_occurred) { + parseMethodNameElement(envP, nameElemP, methodNameP); + + if (!envP->fault_occurred) { + /* Convert our parameters. */ + if (callChildCount > 1) { + xml_element * paramsElemP; + + paramsElemP = get_child_by_name(envP, callElemP, "params"); + + if (!envP->fault_occurred) + *paramArrayPP = convert_params(envP, paramsElemP); + } else { + /* Workaround for Ruby XML-RPC and old versions of + xmlrpc-epi. Future improvement: Instead of looking + at child count, we should just check for existence + of . + */ + *paramArrayPP = xmlrpc_array_new(envP); + } + if (!envP->fault_occurred) { + if (callChildCount > 2) + setParseFault(envP, " has extraneous " + "children, other than and " + ". Total child count = %u", + callChildCount); + + if (envP->fault_occurred) + xmlrpc_DECREF(*paramArrayPP); + } + if (envP->fault_occurred) + xmlrpc_strfree(*methodNameP); + } + } +} + + + +void +xmlrpc_parse_call(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlLen, + const char ** const methodNameP, + xmlrpc_value ** const paramArrayPP) { +/*---------------------------------------------------------------------------- + Given some XML text, attempt to parse it as an XML-RPC call. + Return as *methodNameP the name of the method identified in the call + and as *paramArrayPP the parameter list as an XML-RPC array. + Caller must free() and xmlrpc_DECREF() these, respectively). +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(xmlData != NULL); + XMLRPC_ASSERT(methodNameP != NULL && paramArrayPP != NULL); + + /* SECURITY: Last-ditch attempt to make sure our content length is + legal. XXX - This check occurs too late to prevent an attacker + from creating an enormous memory block, so you should try to + enforce it *before* reading any data off the network. + */ + if (xmlLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_LIMIT_EXCEEDED_ERROR, + "XML-RPC request too large. Max allowed is %u bytes", + xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)); + else { + xml_element * callElemP; + parseCallXml(envP, xmlData, xmlLen, &callElemP); + if (!envP->fault_occurred) { + parseCallChildren(envP, callElemP, methodNameP, paramArrayPP); + + xml_element_free(callElemP); + } + } + if (envP->fault_occurred) { + /* Should not be necessary, but for backward compatibility: */ + *methodNameP = NULL; + *paramArrayPP = NULL; + } +} + + + +static void +interpretFaultCode(xmlrpc_env * const envP, + xmlrpc_value * const faultCodeVP, + int * const faultCodeP) { + + xmlrpc_env fcEnv; + xmlrpc_env_init(&fcEnv); + + xmlrpc_read_int(&fcEnv, faultCodeVP, faultCodeP); + if (fcEnv.fault_occurred) + xmlrpc_faultf(envP, "Invalid value for 'faultCode' member. %s", + fcEnv.fault_string); + + xmlrpc_env_clean(&fcEnv); +} + + + +static void +interpretFaultString(xmlrpc_env * const envP, + xmlrpc_value * const faultStringVP, + const char ** const faultStringP) { + + xmlrpc_env fsEnv; + xmlrpc_env_init(&fsEnv); + + xmlrpc_read_string(&fsEnv, faultStringVP, faultStringP); + + if (fsEnv.fault_occurred) + xmlrpc_faultf(envP, "Invalid value for 'faultString' member. %s", + fsEnv.fault_string); + + xmlrpc_env_clean(&fsEnv); +} + + + +static void +interpretFaultValue(xmlrpc_env * const envP, + xmlrpc_value * const faultVP, + int * const faultCodeP, + const char ** const faultStringP) { + + if (faultVP->_type != XMLRPC_TYPE_STRUCT) + setParseFault(envP, + " element of response is not " + "of structure type"); + else { + xmlrpc_value * faultCodeVP; + xmlrpc_env fvEnv; + + xmlrpc_env_init(&fvEnv); + + xmlrpc_struct_read_value(&fvEnv, faultVP, "faultCode", &faultCodeVP); + if (!fvEnv.fault_occurred) { + interpretFaultCode(&fvEnv, faultCodeVP, faultCodeP); + + if (!fvEnv.fault_occurred) { + xmlrpc_value * faultStringVP; + + xmlrpc_struct_read_value(&fvEnv, faultVP, "faultString", + &faultStringVP); + if (!fvEnv.fault_occurred) { + interpretFaultString(&fvEnv, faultStringVP, faultStringP); + + xmlrpc_DECREF(faultStringVP); + } + } + xmlrpc_DECREF(faultCodeVP); + } + if (fvEnv.fault_occurred) + setParseFault(envP, "Invalid struct for value. %s", + fvEnv.fault_string); + + xmlrpc_env_clean(&fvEnv); + } +} + + + +static void +parseFaultElement(xmlrpc_env * const envP, + const xml_element * const faultElement, + int * const faultCodeP, + const char ** const faultStringP) { + + unsigned int const maxRecursion = + xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID); + + XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(faultElement), "fault")); + + if (xml_element_children_size(faultElement) != 1) + setParseFault(envP, " element should have 1 child, " + "but it has %u.", + xml_element_children_size(faultElement)); + else { + xml_element * const faultValueP = + xml_element_children(faultElement)[0]; + const char * const elemName = xml_element_name(faultValueP); + + if (!xmlrpc_streq(elemName, "value")) + setParseFault(envP, + " contains a <%s> element. " + "Only makes sense.", + elemName); + else { + xmlrpc_value * faultVP; + + xmlrpc_parseValue(envP, maxRecursion, faultValueP, &faultVP); + + if (!envP->fault_occurred) { + interpretFaultValue(envP, faultVP, faultCodeP, faultStringP); + + xmlrpc_DECREF(faultVP); + } + } + } +} + + + +static void +parseParamsElement(xmlrpc_env * const envP, + const xml_element * const paramsElementP, + xmlrpc_value ** const resultPP) { + + xmlrpc_value * paramsVP; + xmlrpc_env env; + + xmlrpc_env_init(&env); + + XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(paramsElementP), "params")); + + paramsVP = convert_params(envP, paramsElementP); + + if (!envP->fault_occurred) { + int arraySize; + xmlrpc_env sizeEnv; + + XMLRPC_ASSERT_ARRAY_OK(paramsVP); + + xmlrpc_env_init(&sizeEnv); + + arraySize = xmlrpc_array_size(&sizeEnv, paramsVP); + /* Since it's a valid array, as asserted above, can't fail */ + XMLRPC_ASSERT(!sizeEnv.fault_occurred); + + if (arraySize != 1) + setParseFault(envP, "Contains %d items. It should have 1.", + arraySize); + else { + xmlrpc_array_read_item(envP, paramsVP, 0, resultPP); + } + xmlrpc_DECREF(paramsVP); + xmlrpc_env_clean(&sizeEnv); + } + if (env.fault_occurred) + xmlrpc_env_set_fault_formatted( + envP, env.fault_code, + "Invalid element. %s", env.fault_string); + + xmlrpc_env_clean(&env); +} + + + +static void +parseMethodResponseElt(xmlrpc_env * const envP, + const xml_element * const methodResponseEltP, + xmlrpc_value ** const resultPP, + int * const faultCodeP, + const char ** const faultStringP) { + + XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(methodResponseEltP), + "methodResponse")); + + if (xml_element_children_size(methodResponseEltP) == 1) { + xml_element * const child = + xml_element_children(methodResponseEltP)[0]; + + if (xmlrpc_streq(xml_element_name(child), "params")) { + /* It's a successful response */ + parseParamsElement(envP, child, resultPP); + *faultStringP = NULL; + } else if (xmlrpc_streq(xml_element_name(child), "fault")) { + /* It's a failure response */ + parseFaultElement(envP, child, faultCodeP, faultStringP); + } else + setParseFault(envP, + " must contain or , " + "but contains <%s>.", xml_element_name(child)); + } else + setParseFault(envP, + " has %u children, should have 1.", + xml_element_children_size(methodResponseEltP)); +} + + + +void +xmlrpc_parse_response2(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen, + xmlrpc_value ** const resultPP, + int * const faultCodeP, + const char ** const faultStringP) { +/*---------------------------------------------------------------------------- + Given some XML text, attempt to parse it as an XML-RPC response. + + If the response is a regular, valid response, return a new reference + to the appropriate value as *resultP and return NULL as + *faultStringP and nothing as *faultCodeP. + + If the response is valid, but indicates a failure of the RPC, return the + fault string in newly malloc'ed space as *faultStringP and the fault + code as *faultCodeP and nothing as *resultP. + + If the XML text is not a valid response or something prevents us from + parsing it, return a description of the error as *envP and nothing else. +-----------------------------------------------------------------------------*/ + xml_element * response; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(xmlData != NULL); + + /* SECURITY: Last-ditch attempt to make sure our content length is legal. + ** XXX - This check occurs too late to prevent an attacker from creating + ** an enormous memory block, so you should try to enforce it + ** *before* reading any data off the network. */ + if (xmlDataLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_LIMIT_EXCEEDED_ERROR, + "XML-RPC response too large. Our limit is %u characters. " + "We got %u characters", + xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID), xmlDataLen); + else { + xmlrpc_env env; + xmlrpc_env_init(&env); + + xml_parse(&env, xmlData, xmlDataLen, &response); + + if (env.fault_occurred) + setParseFault(envP, "Not valid XML. %s", env.fault_string); + else { + /* Pick apart and verify our structure. */ + if (xmlrpc_streq(xml_element_name(response), "methodResponse")) { + parseMethodResponseElt(envP, response, + resultPP, faultCodeP, faultStringP); + } else + setParseFault(envP, "XML-RPC response must consist of a " + " element. " + "This has a <%s> instead.", + xml_element_name(response)); + + xml_element_free(response); + } + xmlrpc_env_clean(&env); + } +} + + + +xmlrpc_value * +xmlrpc_parse_response(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen) { +/*---------------------------------------------------------------------------- + This exists for backward compatibility. It is like + xmlrpc_parse_response2(), except that it merges the concepts of a + failed RPC and an error in executing the RPC. +-----------------------------------------------------------------------------*/ + xmlrpc_value * retval; + xmlrpc_value * result; + const char * faultString; + int faultCode; + + xmlrpc_parse_response2(envP, xmlData, xmlDataLen, + &result, &faultCode, &faultString); + + if (envP->fault_occurred) + retval = NULL; + else { + if (faultString) { + xmlrpc_env_set_fault(envP, faultCode, faultString); + xmlrpc_strfree(faultString); + retval = NULL; + } else + retval = result; /* transfer reference */ + } + return retval; +} + + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_serialize.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_serialize.c new file mode 100644 index 0000000..74fb904 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_serialize.c @@ -0,0 +1,720 @@ +/* Copyright information is at end of file */ + +/* Implementation note: + + The printf format specifiers we use appear to be entirely standard, + except for the "long long" one, which is %I64 on Windows and %lld + everywhere else. So for that, we use the C99 standard macro PRId64, + which is defined by inttypes.h. Ironically, Windows doesn't have + inttypes.h either, but we have int.h instead. +*/ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "int.h" +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" +#include "double.h" + +#define CRLF "\015\012" +#define SMALL_BUFFER_SZ (128) +#define XML_PROLOGUE ""CRLF +#define APACHE_URL "http://ws.apache.org/xmlrpc/namespaces/extensions" +#define XMLNS_APACHE "xmlns:ex=\"" APACHE_URL "\"" + + +static void +addString(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const char * const string) { + + XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, string, strlen(string)); +} + + + +static void +formatOut(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const char * const formatString, + ...) { +/*---------------------------------------------------------------------------- + A lightweight print routine for use with various serialization + functions. + + Use this routine only for printing small objects -- it uses a + fixed-size internal buffer and returns an error on overflow. In + particular, do NOT use this routine to print XML-RPC string values! +-----------------------------------------------------------------------------*/ + va_list args; + char buffer[SMALL_BUFFER_SZ]; + int count; + + XMLRPC_ASSERT_ENV_OK(envP); + + va_start(args, formatString); + + count = XMLRPC_VSNPRINTF(buffer, SMALL_BUFFER_SZ, formatString, args); + + /* Old C libraries return -1 if vsnprintf overflows its buffer. + ** New C libraries return the number of characters which *would* have + ** been printed if the error did not occur. This is impressively vile. + ** Thank the C99 committee for this bright idea. But wait! We also + ** need to keep track of the trailing NUL. */ + + if (count < 0 || count >= (SMALL_BUFFER_SZ - 1)) + xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); + else + XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, count); + + va_end(args); +} + + + +static void +assertValidUtf8(const char * const str ATTR_UNUSED, + size_t const len ATTR_UNUSED) { +/*---------------------------------------------------------------------------- + Assert that the string 'str' of length 'len' is valid UTF-8. +-----------------------------------------------------------------------------*/ +#if !defined NDEBUG + /* Check the assertion; if it's false, issue a message to + Standard Error, but otherwise ignore it. + */ + xmlrpc_env env; + + xmlrpc_env_init(&env); + xmlrpc_validate_utf8(&env, str, len); + if (env.fault_occurred) + fprintf(stderr, "*** xmlrpc-c WARNING ***: %s (%s)\n", + "Xmlrpc-c sending corrupted UTF-8 data to network", + env.fault_string); + xmlrpc_env_clean(&env); +#endif +} + + + +static size_t +escapedSize(const char * const chars, + size_t const len) { + + size_t size; + size_t i; + + size = 0; + for (i = 0; i < len; ++i) { + if (chars[i] == '<') + size += 4; /* < */ + else if (chars[i] == '>') + size += 4; /* > */ + else if (chars[i] == '&') + size += 5; /* & */ + else if (chars[i] == '\r') + size += 6; /* */ + else + size += 1; + } + return size; +} + + + +static void +escapeForXml(xmlrpc_env * const envP, + const char * const chars, + size_t const len, + xmlrpc_mem_block ** const outputPP) { +/*---------------------------------------------------------------------------- + Escape & and < in a UTF-8 string so as to make it suitable for the + content of an XML element. I.e. turn them into entity references + & and <. + + Also change > to >, even though not required for XML, for + symmetry. + + < etc. are known in XML as "entity references." + + Also Escape CR as . While raw CR _is_ allowed in the content + of an XML element, it has a special meaning -- it means line ending. + Our input uses LF for for line endings. Since it also means line ending + in XML, we just pass it through to our output like it were a regular + character. + + is known in XML as a "character reference." + + We assume chars[] is is ASCII. That isn't right -- we should + handle all valid UTF-8. Someday, we must do something more complex + and copy over multibyte characters verbatim. (The code here could + erroneously find that e.g. the 2nd byte of a UTF-8 character is a + CR). +-----------------------------------------------------------------------------*/ + xmlrpc_mem_block * outputP; + size_t outputSize; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(chars != NULL); + + assertValidUtf8(chars, len); + + /* Note that in UTF-8, any byte that has high bit of zero is a + character all by itself (every byte of a multi-byte UTF-8 character + has the high bit set). Also, the Unicode code points < 128 are + identical to the ASCII ones. + */ + + outputSize = escapedSize(chars, len); + + outputP = XMLRPC_MEMBLOCK_NEW(char, envP, outputSize); + if (!envP->fault_occurred) { + char * p; + size_t i; + p = XMLRPC_MEMBLOCK_CONTENTS(char, outputP); /* Start at beginning */ + + for (i = 0; i < len; i++) { + if (chars[i] == '<') { + memcpy(p, "<", 4); + p += 4; + } else if (chars[i] == '>') { + memcpy(p, ">", 4); + p += 4; + } else if (chars[i] == '&') { + memcpy(p, "&", 5); + p += 5; + } else if (chars[i] == '\r') { + memcpy(p, " ", 6); + p += 6; + } else { + /* Either a plain character or a LF line delimiter */ + *p = chars[i]; + p += 1; + } + } + *outputPP = outputP; + assert(p == XMLRPC_MEMBLOCK_CONTENTS(char, outputP) + outputSize); + + if (envP->fault_occurred) + XMLRPC_MEMBLOCK_FREE(char, outputP); + } +} + + + +static void +serializeUtf8MemBlock(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_mem_block * const inputP) { +/*---------------------------------------------------------------------------- + Append the characters in *inputP to the XML stream in *outputP. + + *inputP contains Unicode characters in UTF-8. + + We assume *inputP ends with a NUL character that marks end of + string, and we ignore that. (There might also be NUL characters + inside the string, though). +-----------------------------------------------------------------------------*/ + xmlrpc_mem_block * escapedP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(outputP != NULL); + XMLRPC_ASSERT(inputP != NULL); + + escapeForXml(envP, + XMLRPC_MEMBLOCK_CONTENTS(const char, inputP), + XMLRPC_MEMBLOCK_SIZE(const char, inputP) - 1, + /* -1 is for the terminating NUL */ + &escapedP); + if (!envP->fault_occurred) { + const char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(const char, escapedP); + size_t const size = XMLRPC_MEMBLOCK_SIZE(char, escapedP); + + XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, contents, size); + + XMLRPC_MEMBLOCK_FREE(const char, escapedP); + } +} + + + +static void +xmlrpc_serialize_base64_data(xmlrpc_env * const envP, + xmlrpc_mem_block * const output, + unsigned char * const data, + size_t const len) { +/*---------------------------------------------------------------------------- + Encode the 'len' bytes at 'data' in base64 ASCII and append the result to + 'output'. +-----------------------------------------------------------------------------*/ + xmlrpc_mem_block * encoded; + + encoded = xmlrpc_base64_encode(envP, data, len); + if (!envP->fault_occurred) { + unsigned char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(unsigned char, encoded); + size_t const size = + XMLRPC_MEMBLOCK_SIZE(unsigned char, encoded); + + XMLRPC_MEMBLOCK_APPEND(char, envP, output, contents, size); + + XMLRPC_MEMBLOCK_FREE(char, encoded); + } +} + + + +static void +serializeStruct(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const structP, + xmlrpc_dialect const dialect) { +/*---------------------------------------------------------------------------- + Add to *outputP the content of a element to represent + the structure value *valueP. I.e. " ... ". +-----------------------------------------------------------------------------*/ + size_t size; + size_t i; + xmlrpc_value * memberKeyP; + xmlrpc_value * memberValueP; + + addString(envP, outputP, ""CRLF); + XMLRPC_FAIL_IF_FAULT(envP); + + size = xmlrpc_struct_size(envP, structP); + XMLRPC_FAIL_IF_FAULT(envP); + for (i = 0; i < size; ++i) { + xmlrpc_struct_get_key_and_value(envP, structP, i, + &memberKeyP, &memberValueP); + XMLRPC_FAIL_IF_FAULT(envP); + addString(envP, outputP, ""); + XMLRPC_FAIL_IF_FAULT(envP); + serializeUtf8MemBlock(envP, outputP, &memberKeyP->_block); + XMLRPC_FAIL_IF_FAULT(envP); + addString(envP, outputP, ""CRLF); + XMLRPC_FAIL_IF_FAULT(envP); + xmlrpc_serialize_value2(envP, outputP, memberValueP, dialect); + XMLRPC_FAIL_IF_FAULT(envP); + addString(envP, outputP, ""CRLF); + XMLRPC_FAIL_IF_FAULT(envP); + } + + addString(envP, outputP, ""); + XMLRPC_FAIL_IF_FAULT(envP); + +cleanup: + return; +} + + + +static void +serializeArray(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP, + xmlrpc_dialect const dialect) { +/*---------------------------------------------------------------------------- + Add to *outputP the content of a element to represent + the array value *valueP. I.e. " ... ". +-----------------------------------------------------------------------------*/ + int const size = xmlrpc_array_size(envP, valueP); + + if (!envP->fault_occurred) { + addString(envP, outputP, ""CRLF); + if (!envP->fault_occurred) { + int i; + /* Serialize each item. */ + for (i = 0; i < size && !envP->fault_occurred; ++i) { + xmlrpc_value * const itemP = + xmlrpc_array_get_item(envP, valueP, i); + if (!envP->fault_occurred) { + xmlrpc_serialize_value2(envP, outputP, itemP, dialect); + if (!envP->fault_occurred) + addString(envP, outputP, CRLF); + } + } + } + } + if (!envP->fault_occurred) + addString(envP, outputP, ""); +} + + + +static void +formatValueContent(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP, + xmlrpc_dialect const dialect) { +/*---------------------------------------------------------------------------- + Add to *outputP the content of a element to represent + value *valueP. E.g. "42" +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + + switch (valueP->_type) { + case XMLRPC_TYPE_INT: + formatOut(envP, outputP, "%d", valueP->_value.i); + break; + + case XMLRPC_TYPE_I8: { + const char * const elemName = + dialect == xmlrpc_dialect_apache ? "ex:i8" : "i8"; + formatOut(envP, outputP, "<%s>%" PRId64 "", + elemName, valueP->_value.i8, elemName); + } break; + + case XMLRPC_TYPE_BOOL: + formatOut(envP, outputP, "%s", + valueP->_value.b ? "1" : "0"); + break; + + case XMLRPC_TYPE_DOUBLE: { + const char * serializedValue; + xmlrpc_formatFloat(envP, valueP->_value.d, &serializedValue); + if (!envP->fault_occurred) { + addString(envP, outputP, ""); + if (!envP->fault_occurred) { + addString(envP, outputP, serializedValue); + if (!envP->fault_occurred) + addString(envP, outputP, ""); + } + xmlrpc_strfree(serializedValue); + } + } break; + + case XMLRPC_TYPE_DATETIME: + addString(envP, outputP, ""); + if (!envP->fault_occurred) { + serializeUtf8MemBlock(envP, outputP, &valueP->_block); + if (!envP->fault_occurred) { + addString(envP, outputP, ""); + } + } + break; + + case XMLRPC_TYPE_STRING: + addString(envP, outputP, ""); + if (!envP->fault_occurred) { + serializeUtf8MemBlock(envP, outputP, &valueP->_block); + if (!envP->fault_occurred) + addString(envP, outputP, ""); + } + break; + + case XMLRPC_TYPE_BASE64: { + unsigned char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(unsigned char, &valueP->_block); + size_t const size = + XMLRPC_MEMBLOCK_SIZE(unsigned char, &valueP->_block); + addString(envP, outputP, ""CRLF); + if (!envP->fault_occurred) { + xmlrpc_serialize_base64_data(envP, outputP, contents, size); + if (!envP->fault_occurred) + addString(envP, outputP, ""); + } + } break; + + case XMLRPC_TYPE_ARRAY: + serializeArray(envP, outputP, valueP, dialect); + break; + + case XMLRPC_TYPE_STRUCT: + serializeStruct(envP, outputP, valueP, dialect); + break; + + case XMLRPC_TYPE_C_PTR: + xmlrpc_faultf(envP, "Tried to serialize a C pointer value."); + break; + + case XMLRPC_TYPE_NIL: { + const char * const elemName = + dialect == xmlrpc_dialect_apache ? "ex:nil" : "nil"; + formatOut(envP, outputP, "<%s/>", elemName); + } break; + + case XMLRPC_TYPE_DEAD: + xmlrpc_faultf(envP, "Tried to serialize a dead value."); + break; + + default: + xmlrpc_faultf(envP, "Invalid xmlrpc_value type: %d", valueP->_type); + } +} + + + +void +xmlrpc_serialize_value2(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP, + xmlrpc_dialect const dialect) { +/*---------------------------------------------------------------------------- + Generate the XML to represent XML-RPC value 'valueP' in XML-RPC. + + Add it to *outputP. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(outputP != NULL); + XMLRPC_ASSERT_VALUE_OK(valueP); + + addString(envP, outputP, ""); + + if (!envP->fault_occurred) { + formatValueContent(envP, outputP, valueP, dialect); + + if (!envP->fault_occurred) + addString(envP, outputP, ""); + } +} + + + +void +xmlrpc_serialize_value(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP) { + + xmlrpc_serialize_value2(envP, outputP, valueP, xmlrpc_dialect_i8); +} + + + +void +xmlrpc_serialize_params2(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const paramArrayP, + xmlrpc_dialect const dialect) { +/*---------------------------------------------------------------------------- + Serialize the parameter list of an XML-RPC call. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(outputP != NULL); + XMLRPC_ASSERT_VALUE_OK(paramArrayP); + + addString(envP, outputP, ""CRLF); + if (!envP->fault_occurred) { + /* Serialize each parameter. */ + size_t const paramCount = xmlrpc_array_size(envP, paramArrayP); + if (!envP->fault_occurred) { + size_t paramSeq; + for (paramSeq = 0; + paramSeq < paramCount && !envP->fault_occurred; + ++paramSeq) { + + addString(envP, outputP, ""); + if (!envP->fault_occurred) { + xmlrpc_value * const itemP = + xmlrpc_array_get_item(envP, paramArrayP, paramSeq); + if (!envP->fault_occurred) { + xmlrpc_serialize_value2(envP, outputP, itemP, dialect); + if (!envP->fault_occurred) + addString(envP, outputP, ""CRLF); + } + } + } + } + } + + if (!envP->fault_occurred) + addString(envP, outputP, ""CRLF); +} + + + +void +xmlrpc_serialize_params(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const paramArrayP) { +/*---------------------------------------------------------------------------- + Serialize the parameter list of an XML-RPC call in the original + "i8" dialect. +-----------------------------------------------------------------------------*/ + xmlrpc_serialize_params2(envP, outputP, paramArrayP, xmlrpc_dialect_i8); +} + + + +/*========================================================================= +** xmlrpc_serialize_call +**========================================================================= +** Serialize an XML-RPC call. +*/ + +void +xmlrpc_serialize_call2(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_dialect const dialect) { +/*---------------------------------------------------------------------------- + Serialize an XML-RPC call of method named 'methodName' with parameter + list *paramArrayP. Use XML-RPC dialect 'dialect'. + + Append the call XML ot *outputP. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(outputP != NULL); + XMLRPC_ASSERT(methodName != NULL); + XMLRPC_ASSERT_VALUE_OK(paramArrayP); + + addString(envP, outputP, XML_PROLOGUE); + if (!envP->fault_occurred) { + const char * const xmlns = + dialect == xmlrpc_dialect_apache ? " " XMLNS_APACHE : ""; + formatOut(envP, outputP, ""CRLF"", xmlns); + if (!envP->fault_occurred) { + xmlrpc_mem_block * encodedP; + escapeForXml(envP, methodName, strlen(methodName), &encodedP); + if (!envP->fault_occurred) { + const char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(char, encodedP); + size_t const size = XMLRPC_MEMBLOCK_SIZE(char, encodedP); + XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, contents, size); + if (!envP->fault_occurred) { + addString(envP, outputP, ""CRLF); + if (!envP->fault_occurred) { + xmlrpc_serialize_params2(envP, outputP, paramArrayP, + dialect); + if (!envP->fault_occurred) + addString(envP, outputP, ""CRLF); + } + } + XMLRPC_MEMBLOCK_FREE(char, encodedP); + } + } + } +} + + + +void +xmlrpc_serialize_call(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const char * const methodName, + xmlrpc_value * const paramArrayP) { + + xmlrpc_serialize_call2(envP, outputP, methodName, paramArrayP, + xmlrpc_dialect_i8); +} + + + +void +xmlrpc_serialize_response2(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP, + xmlrpc_dialect const dialect) { +/*---------------------------------------------------------------------------- + Serialize a result response to an XML-RPC call. + + The result is 'valueP'. + + Add the response XML to *outputP. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(outputP != NULL); + XMLRPC_ASSERT_VALUE_OK(valueP); + + addString(envP, outputP, XML_PROLOGUE); + if (!envP->fault_occurred) { + const char * const xmlns = + dialect == xmlrpc_dialect_apache ? " " XMLNS_APACHE : ""; + formatOut(envP, outputP, + ""CRLF""CRLF"", xmlns); + if (!envP->fault_occurred) { + xmlrpc_serialize_value2(envP, outputP, valueP, dialect); + if (!envP->fault_occurred) { + addString(envP, outputP, + ""CRLF""CRLF + ""CRLF); + } + } + } +} + + + +void +xmlrpc_serialize_response(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP) { + + xmlrpc_serialize_response2(envP, outputP, valueP, xmlrpc_dialect_i8); +} + + + +void +xmlrpc_serialize_fault(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const xmlrpc_env * const faultP) { +/*---------------------------------------------------------------------------- + Serialize a fault response to an XML-RPC call. + + 'faultP' is the fault. + + Add the response XML to *outputP. +-----------------------------------------------------------------------------*/ + xmlrpc_value * faultStructP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(outputP != NULL); + XMLRPC_ASSERT(faultP != NULL); + XMLRPC_ASSERT(faultP->fault_occurred); + + faultStructP = xmlrpc_build_value(envP, "{s:i,s:s}", + "faultCode", + (xmlrpc_int32) faultP->fault_code, + "faultString", faultP->fault_string); + if (!envP->fault_occurred) { + addString(envP, outputP, XML_PROLOGUE); + if (!envP->fault_occurred) { + addString(envP, outputP, ""CRLF""CRLF); + if (!envP->fault_occurred) { + xmlrpc_serialize_value(envP, outputP, faultStructP); + if (!envP->fault_occurred) { + addString(envP, outputP, + CRLF""CRLF""CRLF); + } + } + } + xmlrpc_DECREF(faultStructP); + } +} + + + +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_cgi.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_cgi.c new file mode 100644 index 0000000..2f6fe73 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_cgi.c @@ -0,0 +1,323 @@ +/* Copyright (C) 2001 by Eric Kidd. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + + +#include "xmlrpc_config.h" + +#include +#include +#include + +/* Windows NT stdout binary mode fix. */ +#ifdef _WIN32 +#include +#include +#endif + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/server.h" +#include "xmlrpc-c/server_cgi.h" + + +/*========================================================================= +** Output Routines +**========================================================================= +** These routines send various kinds of responses to the server. +*/ + +static void +send_xml(const char * const xml_data, + size_t const xml_len) { +#ifdef _WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif + /* Send our CGI headers back to the server. + ** XXX - Coercing 'size_t' to 'unsigned long' might be unsafe under + ** really weird circumstances. */ + fprintf(stdout, "Status: 200 OK\n"); + /* Handle authentication cookie being sent back. */ + if (getenv("HTTP_COOKIE_AUTH") != NULL) + fprintf(stdout, "Set-Cookie: auth=%s\n", getenv("HTTP_COOKIE_AUTH")); + fprintf(stdout, "Content-type: text/xml; charset=\"utf-8\"\n"); + fprintf(stdout, "Content-length: %ld\n\n", (unsigned long) xml_len); + + /* Blast out our data. */ + fwrite(xml_data, sizeof(char), xml_len, stdout); +} + + + +static void +send_error(int const code, + const char * const message, + xmlrpc_env * const env) { + +#ifdef _WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif + /* Send an error header. */ + fprintf(stdout, "Status: %d %s\n", code, message); + fprintf(stdout, "Content-type: text/html\n\n"); + + /* Send an error message. */ + fprintf(stdout, "%d %s\n", code, message); + fprintf(stdout, "

%d %s

\n", code, message); + fprintf(stdout, "

An error occurred processing your request.

\n"); + + /* Print out the XML-RPC fault, if present. */ + if (env && env->fault_occurred) + fprintf(stdout, "

XML-RPC Fault #%d: %s

\n", + env->fault_code, env->fault_string); +} + + +/*========================================================================= +** die_if_fault_occurred +**========================================================================= +** Certain kinds of errors aren't worth the trouble of generating +** an XML-RPC fault. For these, we just send status 500 to our web server +** and log the fault to our server log. +*/ + +static void +die_if_fault_occurred(xmlrpc_env * const env) { + if (env->fault_occurred) { + fprintf(stderr, "Unexpected XML-RPC fault: %s (%d)\n", + env->fault_string, env->fault_code); + send_error(500, "Internal Server Error", env); + exit(1); + } +} + + +/*========================================================================= +** Initialization, Cleanup & Method Registry +**========================================================================= +** These are all related, so we group them together. +*/ + +static xmlrpc_registry * globalRegistryP; + +/*========================================================================= +** get_body +**========================================================================= +** Slurp the body of the request into an xmlrpc_mem_block. +*/ + +static xmlrpc_mem_block * +get_body(xmlrpc_env * const env, + size_t const length) { + + xmlrpc_mem_block *result; + char *contents; + size_t count; + + XMLRPC_ASSERT_ENV_OK(env); + + /* Error-handling preconditions. */ + result = NULL; + +#ifdef _WIN32 + /* Fix from Jeff Stewart: NT opens stdin and stdout in text mode + by default, badly confusing our length calculations. So we need + to set the file handle to binary. + */ + _setmode(_fileno(stdin), _O_BINARY); +#endif + /* XXX - Puke if length is too big. */ + + /* Allocate our memory block. */ + result = xmlrpc_mem_block_new(env, length); + XMLRPC_FAIL_IF_FAULT(env); + contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, result); + + /* Get our data off the network. + ** XXX - Coercing 'size_t' to 'unsigned long' might be unsafe under + ** really weird circumstances. */ + count = fread(contents, sizeof(char), length, stdin); + if (count < length) + XMLRPC_FAIL2(env, XMLRPC_INTERNAL_ERROR, + "Expected %ld bytes, received %ld", + (unsigned long) length, (unsigned long) count); + + cleanup: + if (env->fault_occurred) { + if (result) + xmlrpc_mem_block_free(result); + return NULL; + } + return result; +} + + + +void +xmlrpc_server_cgi_process_call(xmlrpc_registry * const registryP) { +/*---------------------------------------------------------------------------- + Get the XML-RPC call from Standard Input and environment variables, + parse it, find the right method, call it, prepare an XML-RPC + response with the result, and write it to Standard Output. +-----------------------------------------------------------------------------*/ + xmlrpc_env env; + char *method, *type, *length_str; + int length; + xmlrpc_mem_block *input, *output; + char *input_data, *output_data; + size_t input_size, output_size; + int code; + char *message; + + /* Error-handling preconditions. */ + xmlrpc_env_init(&env); + input = output = NULL; + + /* Set up a default error message. */ + code = 500; message = "Internal Server Error"; + + /* Get our HTTP information from the environment. */ + method = getenv("REQUEST_METHOD"); + type = getenv("CONTENT_TYPE"); + length_str = getenv("CONTENT_LENGTH"); + + /* Perform some sanity checks. */ + if (!method || 0 != strcmp(method, "POST")) { + code = 405; message = "Method Not Allowed"; + XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Expected HTTP method POST"); + } + if (!type || 0 != strcmp(type, "text/xml")) { + code = 400; message = "Bad Request"; + XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Expected text/xml content"); + } + if (!length_str) { + code = 411; message = "Length Required"; + XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Content-length required"); + } + + /* Get our content length. */ + length = atoi(length_str); + if (length <= 0) { + code = 400; message = "Bad Request"; + XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Content-length must be > 0"); + } + + /* SECURITY: Make sure our content length is legal. + ** XXX - We can cast 'input_len' because we know it's >= 0, yes? */ + if ((size_t) length > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) { + code = 400; message = "Bad Request"; + XMLRPC_FAIL(&env, XMLRPC_LIMIT_EXCEEDED_ERROR, + "XML-RPC request too large"); + } + + /* Get our body. */ + input = get_body(&env, length); + XMLRPC_FAIL_IF_FAULT(&env); + input_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, input); + input_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input); + + /* Process our call. */ + xmlrpc_registry_process_call2(&env, registryP, + input_data, input_size, NULL, &output); + XMLRPC_FAIL_IF_FAULT(&env); + output_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output); + output_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output); + + /* Send our data. */ + send_xml(output_data, output_size); + + cleanup: + if (input) + xmlrpc_mem_block_free(input); + if (output) + xmlrpc_mem_block_free(output); + + if (env.fault_occurred) + send_error(code, message, &env); + + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_cgi_init(int const flags ATTR_UNUSED) { + xmlrpc_env env; + + xmlrpc_env_init(&env); + globalRegistryP = xmlrpc_registry_new(&env); + die_if_fault_occurred(&env); + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_cgi_cleanup(void) { + xmlrpc_registry_free(globalRegistryP); +} + + + +xmlrpc_registry * +xmlrpc_cgi_registry(void) { + return globalRegistryP; +} + + + +void +xmlrpc_cgi_add_method(const char * const method_name, + xmlrpc_method const method, + void * const user_data) { + xmlrpc_env env; + xmlrpc_env_init(&env); + xmlrpc_registry_add_method(&env, globalRegistryP, NULL, method_name, + method, user_data); + die_if_fault_occurred(&env); + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_cgi_add_method_w_doc(const char * const method_name, + xmlrpc_method const method, + void * const user_data, + const char * const signature, + const char * const help) { + xmlrpc_env env; + xmlrpc_env_init(&env); + xmlrpc_registry_add_method_w_doc(&env, globalRegistryP, NULL, method_name, + method, user_data, signature, help); + die_if_fault_occurred(&env); + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_cgi_process_call(void) { + + xmlrpc_server_cgi_process_call(globalRegistryP); +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_info.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_info.c new file mode 100644 index 0000000..5cf44c3 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_info.c @@ -0,0 +1,343 @@ +/*============================================================================= + xmlrpc_server_info +=============================================================================== + The xmlrpc_server_info class. + + By Bryan Henderson, San Jose CA 2007.10.17. + + Contributed to the public domain by its author + + The xmlrpc_server_info class was originally just supposed to be + information about an HTTP server, hence the name. But we think of it + now as a generic carriage parameter, as in the C++ library. In + the future, it should be a union or maybe contain an opaque pointer + to the carriage parameter for a particular kind of transport. That + way, the client XML transports can be more than just HTTP XML + transports. +=============================================================================*/ + +#include "bool.h" +#include "mallocvar.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/client.h" +#include "xmlrpc-c/client_int.h" + + + +xmlrpc_server_info * +xmlrpc_server_info_new(xmlrpc_env * const envP, + const char * const serverUrl) { + + xmlrpc_server_info * serverInfoP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(serverUrl); + + MALLOCVAR(serverInfoP); + if (serverInfoP == NULL) + xmlrpc_faultf(envP, "Couldn't allocate memory for xmlrpc_server_info"); + else { + serverInfoP->serverUrl = strdup(serverUrl); + if (serverInfoP->serverUrl == NULL) + xmlrpc_faultf(envP, "Couldn't allocate memory for server URL"); + else { + serverInfoP->allowedAuth.basic = false; + serverInfoP->allowedAuth.digest = false; + serverInfoP->allowedAuth.gssnegotiate = false; + serverInfoP->allowedAuth.ntlm = false; + serverInfoP->userNamePw = NULL; + serverInfoP->basicAuthHdrValue = NULL; + if (envP->fault_occurred) + xmlrpc_strfree(serverInfoP->serverUrl); + } + if (envP->fault_occurred) + free(serverInfoP); + } + return serverInfoP; +} + + + +static void +copyUserNamePw(xmlrpc_env * const envP, + const char * const src, + const char ** const dstP) { + + if (src == NULL) + *dstP = NULL; + else { + *dstP = strdup(src); + if (*dstP == NULL) + xmlrpc_faultf(envP, "Couldn't allocate memory for user name/pw"); + } +} + + + +static void +freeIfNonNull(const char * const arg) { + + if (arg) + xmlrpc_strfree(arg); +} + + + +static void +copyBasicAuthHdrValue(xmlrpc_env * const envP, + const char * const src, + const char ** const dstP) { + + if (src == NULL) + *dstP = NULL; + else { + *dstP = strdup(src); + if (*dstP == NULL) + xmlrpc_faultf(envP, "Couldn't allocate memory " + "for authentication header value"); + } +} + + + +static void +copyServerInfoContent(xmlrpc_env * const envP, + xmlrpc_server_info * const dstP, + const xmlrpc_server_info * const srcP) { + + dstP->serverUrl = strdup(srcP->serverUrl); + if (dstP->serverUrl == NULL) + xmlrpc_faultf(envP, "Couldn't allocate memory for server URL"); + else { + copyUserNamePw(envP, srcP->userNamePw, &dstP->userNamePw); + + if (!envP->fault_occurred) { + copyBasicAuthHdrValue(envP, srcP->basicAuthHdrValue, + &dstP->basicAuthHdrValue); + + if (!envP->fault_occurred) { + dstP->allowedAuth.basic = + srcP->allowedAuth.basic; + dstP->allowedAuth.digest = + srcP->allowedAuth.digest; + dstP->allowedAuth.gssnegotiate = + srcP->allowedAuth.gssnegotiate; + dstP->allowedAuth.ntlm = + srcP->allowedAuth.ntlm; + + if (envP->fault_occurred) + freeIfNonNull(dstP->basicAuthHdrValue); + } + if (envP->fault_occurred) + freeIfNonNull(dstP->userNamePw); + } + if (envP->fault_occurred) + xmlrpc_strfree(dstP->serverUrl); + } +} + + + +xmlrpc_server_info * +xmlrpc_server_info_copy(xmlrpc_env * const envP, + xmlrpc_server_info * const srcP) { + + xmlrpc_server_info * serverInfoP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(srcP); + + MALLOCVAR(serverInfoP); + if (serverInfoP == NULL) + xmlrpc_faultf(envP, + "Couldn't allocate memory for xmlrpc_server_info"); + else { + copyServerInfoContent(envP, serverInfoP, srcP); + + if (envP->fault_occurred) + free(serverInfoP); + } + return serverInfoP; +} + + + +void +xmlrpc_server_info_free(xmlrpc_server_info * const serverInfoP) { + + XMLRPC_ASSERT_PTR_OK(serverInfoP); + XMLRPC_ASSERT(serverInfoP->serverUrl != XMLRPC_BAD_POINTER); + + if (serverInfoP->userNamePw) + xmlrpc_strfree(serverInfoP->userNamePw); + serverInfoP->userNamePw = XMLRPC_BAD_POINTER; + + if (serverInfoP->basicAuthHdrValue) + xmlrpc_strfree(serverInfoP->basicAuthHdrValue); + serverInfoP->basicAuthHdrValue = XMLRPC_BAD_POINTER; + + xmlrpc_strfree(serverInfoP->serverUrl); + serverInfoP->serverUrl = XMLRPC_BAD_POINTER; + + free(serverInfoP); +} + + + +void +xmlrpc_server_info_set_user(xmlrpc_env * const envP, + xmlrpc_server_info * const serverInfoP, + const char * const username, + const char * const password) { + + const char * userNamePw; + xmlrpc_mem_block * userNamePw64; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(serverInfoP); + XMLRPC_ASSERT_PTR_OK(username); + XMLRPC_ASSERT_PTR_OK(password); + + xmlrpc_asprintf(&userNamePw, "%s:%s", username, password); + + userNamePw64 = + xmlrpc_base64_encode_without_newlines(envP, + (unsigned char*) userNamePw, + strlen(userNamePw)); + if (!envP->fault_occurred) { + const char * const data = XMLRPC_MEMBLOCK_CONTENTS(char, userNamePw64); + size_t const len = XMLRPC_MEMBLOCK_SIZE(char, userNamePw64); + const char * const authType = "Basic "; + + char * hdrValue; + + hdrValue = malloc(strlen(authType) + len + 1); + if (hdrValue == NULL) + xmlrpc_faultf(envP, "Could not allocate memory to store " + "authorization header value."); + else { + strcpy(hdrValue, authType); + strncat(hdrValue, data, len); + + if (serverInfoP->basicAuthHdrValue) + xmlrpc_strfree(serverInfoP->basicAuthHdrValue); + + serverInfoP->basicAuthHdrValue = hdrValue; + } + XMLRPC_MEMBLOCK_FREE(char, userNamePw64); + } + serverInfoP->userNamePw = userNamePw; +} + + + +void +xmlrpc_server_info_set_basic_auth(xmlrpc_env * const envP, + xmlrpc_server_info * const serverInfoP, + const char * const username, + const char * const password) { + + xmlrpc_server_info_set_user(envP, serverInfoP, username, password); + + if (!envP->fault_occurred) { + serverInfoP->allowedAuth.basic = true; + serverInfoP->allowedAuth.digest = false; + serverInfoP->allowedAuth.gssnegotiate = false; + serverInfoP->allowedAuth.ntlm = false; + } +} + + + +void +xmlrpc_server_info_allow_auth_basic(xmlrpc_env * const envP, + xmlrpc_server_info * const sP) { + + if (sP->userNamePw == NULL) + xmlrpc_faultf(envP, "You must set username/password with " + "xmlrpc_server_info_set_user()"); + else + sP->allowedAuth.basic = true; +} + + + +void +xmlrpc_server_info_disallow_auth_basic( + xmlrpc_env * const envP ATTR_UNUSED, + xmlrpc_server_info * const sP) { + + sP->allowedAuth.basic = false; +} + + + +void +xmlrpc_server_info_allow_auth_digest(xmlrpc_env * const envP, + xmlrpc_server_info * const sP) { + + if (sP->userNamePw == NULL) + xmlrpc_faultf(envP, "You must set username/password with " + "xmlrpc_server_info_set_user()"); + else + sP->allowedAuth.digest = true; +} + + + +void +xmlrpc_server_info_disallow_auth_digest( + xmlrpc_env * const envP ATTR_UNUSED, + xmlrpc_server_info * const sP) { + + sP->allowedAuth.digest = false; +} + + + +void +xmlrpc_server_info_allow_auth_negotiate(xmlrpc_env * const envP, + xmlrpc_server_info * const sP) { + + if (sP->userNamePw == NULL) + xmlrpc_faultf(envP, "You must set username/password with " + "xmlrpc_server_info_set_user()"); + else + sP->allowedAuth.gssnegotiate = true; +} + + + +void +xmlrpc_server_info_disallow_auth_negotiate( + xmlrpc_env * const envP ATTR_UNUSED, + xmlrpc_server_info * const sP) { + + sP->allowedAuth.gssnegotiate = false; +} + + + +void +xmlrpc_server_info_allow_auth_ntlm(xmlrpc_env * const envP, + xmlrpc_server_info * const sP) { + + if (sP->userNamePw == NULL) + xmlrpc_faultf(envP, "You must set username/password with " + "xmlrpc_server_info_set_user()"); + else + sP->allowedAuth.ntlm = true; +} + + + +void +xmlrpc_server_info_disallow_auth_ntlm( + xmlrpc_env * const envP ATTR_UNUSED, + xmlrpc_server_info * const sP) { + + sP->allowedAuth.ntlm = true; +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_w32httpsys.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_w32httpsys.c new file mode 100644 index 0000000..cf0dad8 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_server_w32httpsys.c @@ -0,0 +1,1001 @@ +/* Copyright information is at end of file. */ +/* COMPILATION NOTE: + Note that the Platform SDK headers and + link libraries for Windows XP SP2 or newer are required to compile + xmlrpc-c for this module. If you are not using this server, it is + safe to exclude the xmlrpc_server_w32httpsys.c file from the xmlrpc + project and these dependencies will not be required. You can get the + latest platform SDK at + http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ + Be sure after installation to choose the program to "register the PSDK + directories with Visual Studio" so the newer headers are found. +*/ + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef _UNICODE +#define _UNICODE +#endif + +/* See compilation note above if this header is not found! */ +#include +#include + +#include "xmlrpc_config.h" +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/server.h" +#include "xmlrpc-c/server_w32httpsys.h" +#include "version.h" + +#pragma comment( lib, "httpapi" ) +#pragma message( "Compiling HTTPS server ..." ) + +/* XXX - This variable is *not* currently threadsafe. Once the server has +** been started, it must be treated as read-only. */ +static xmlrpc_registry *global_registryP; + +//set TRUE if you want a log +static BOOL g_bDebug; +//set log filename +static char g_fLogFile[MAX_PATH]; +//do you want OutputDebugString() to be called? +static BOOL g_bDebugString; + +// +// Macros. +// +#define INITIALIZE_HTTP_RESPONSE( resp, status, reason ) \ + do \ + { \ + RtlZeroMemory( (resp), sizeof(*(resp)) ); \ + (resp)->StatusCode = (status); \ + (resp)->pReason = (reason); \ + (resp)->ReasonLength = (USHORT) strlen(reason); \ + } while (FALSE) + + +#define ADD_KNOWN_HEADER(Response, HeaderId, RawValue) \ + do \ + { \ + (Response).Headers.KnownHeaders[(HeaderId)].pRawValue = (RawValue); \ + (Response).Headers.KnownHeaders[(HeaderId)].RawValueLength = \ + (USHORT) strlen(RawValue); \ + } while(FALSE) + +#define ALLOC_MEM(cb) HeapAlloc(GetProcessHeap(), 0, (cb)) +#define FREE_MEM(ptr) HeapFree(GetProcessHeap(), 0, (ptr)) + +// +// Prototypes for Internal Functions. +// +DWORD +DoReceiveRequests( + HANDLE hReqQueue, + const xmlrpc_server_httpsys_parms * const parmsP + ); + +DWORD +SendHttpResponse( + IN HANDLE hReqQueue, + IN PHTTP_REQUEST pRequest, + IN USHORT StatusCode, + IN PSTR pReason, + IN PSTR pEntity + ); + +DWORD +SendHttpResponseAuthRequired( + IN HANDLE hReqQueue, + IN PHTTP_REQUEST pRequest + ); + +void +processRPCCall( + xmlrpc_env * const envP, + IN HANDLE hReqQueue, + IN PHTTP_REQUEST pRequest + ); + +__inline void TraceA(const char *format, ...); +__inline void TraceW(const wchar_t *format, ...); + + +// +// External Function Implementation. +// + +void +xmlrpc_server_httpsys( + xmlrpc_env * const envP, + const xmlrpc_server_httpsys_parms * const parmsP, + unsigned int const parm_size + ) +{ + ULONG retCode; + HANDLE hReqQueue = NULL; + HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_1; + WCHAR wszURL[35]; + + XMLRPC_ASSERT_ENV_OK(envP); + + if (parm_size < XMLRPC_HSSIZE(authfn)) + { + xmlrpc_faultf(envP, + "You must specify members at least up through " + "'authfn' in the server parameters argument. " + "That would mean the parameter size would be >= %u " + "but you specified a size of %u", + XMLRPC_HSSIZE(authfn), parm_size); + return; + } + + //Set logging options + if (parmsP->logLevel>0) + g_bDebug=TRUE; + else + g_bDebug=FALSE; + + if (parmsP->logLevel>1) + g_bDebugString=TRUE; + else + g_bDebugString=FALSE; + + if (!parmsP->logFile) + g_bDebug=FALSE; + else + StringCchPrintfA(g_fLogFile,MAX_PATH,parmsP->logFile); + + //construct the URL we are listening on + if (parmsP->useSSL!=0) + StringCchPrintf(wszURL,35,L"https://+:%u/RPC2",parmsP->portNum); + else + StringCchPrintf(wszURL,35,L"http://+:%u/RPC2",parmsP->portNum); + + global_registryP = parmsP->registryP; + + // Initialize HTTP APIs. + retCode = HttpInitialize(HttpApiVersion, + HTTP_INITIALIZE_SERVER, // Flags + NULL // Reserved + ); + if (retCode != NO_ERROR) + { + xmlrpc_faultf(envP, "HttpInitialize failed with %lu", + retCode); + return; + } + + // Create a Request Queue Handle + retCode = HttpCreateHttpHandle(&hReqQueue, // Req Queue + 0 // Reserved + ); + if (retCode != NO_ERROR) + { + xmlrpc_faultf(envP, "HttpCreateHttpHandle failed with %lu", retCode); + goto CleanUp; + } + + retCode = HttpAddUrl(hReqQueue, // Req Queue + wszURL, // Fully qualified URL + NULL // Reserved + ); + + if (retCode != NO_ERROR) + { + xmlrpc_faultf(envP, "HttpAddUrl failed with %lu", retCode); + goto CleanUp; + } + + TraceW(L"we are listening for requests on the following url: %ws", + wszURL); + + // Loop while receiving requests + for(;;) + { + TraceW(L"Calling DoReceiveRequests()"); + retCode = DoReceiveRequests(hReqQueue, parmsP); + if(NO_ERROR == retCode) + { + TraceW(L"DoReceiveRequests() returned NO_ERROR, breaking"); + break; + } + } + +CleanUp: + + TraceW(L"Tearing down the server.", wszURL); + + // Call HttpRemoveUrl for the URL that we added. + HttpRemoveUrl( hReqQueue, wszURL ); + + // Close the Request Queue handle. + if(hReqQueue) + CloseHandle(hReqQueue); + + // Call HttpTerminate. + HttpTerminate(HTTP_INITIALIZE_SERVER, NULL); + return; +} + +// +// Internal Function Implementations. +// + +__inline void TraceA(const char *format, ...) +{ + if(g_bDebug) + { + if (format) + { + va_list arglist; + char str[4096]; + + va_start(arglist, format); + StringCchVPrintfA(str, sizeof(str), format, arglist); + StringCbCatA(str, sizeof(str), "\n"); + if (g_fLogFile) + { + FILE *fout = fopen(g_fLogFile, "a+t"); + if (fout) + { + fprintf(fout, str); + fclose(fout); + } + } + + printf(str); + + if (g_bDebugString) + { + + OutputDebugStringA(str); + } + + va_end(arglist); + } + } +} + +__inline void TraceW(const wchar_t *format, ...) +{ + if(g_bDebug) + { + if (format) + { + va_list arglist; + wchar_t str[4096]; + + va_start(arglist, format); + StringCchVPrintfW(str, 4096, format, arglist); + StringCbCatW(str, sizeof(str), L"\n"); + if (g_fLogFile) + { + FILE *fout = fopen(g_fLogFile, "a+t"); + if (fout) + { + fwprintf(fout, str); + fclose(fout); + } + } + + wprintf(str); + + if (g_bDebugString) + { + OutputDebugStringW(str); + } + + va_end(arglist); + } + } +} + +/* + * This is a blocking function that merely sits on the request queue + * for our URI and processes them one at a time. Once a request comes + * in, we check it for content-type, content-length, and verb. As long + * as the initial validations are done, we pass the request to the + * processRPCCall() function, which collects the body of the request + * and processes it. If we get an error back other than network type, + * we are responsible for notifing the client. + */ +DWORD +DoReceiveRequests( + IN HANDLE hReqQueue, + const xmlrpc_server_httpsys_parms * const parmsP + ) +{ + ULONG result; + HTTP_REQUEST_ID requestId; + DWORD bytesRead; + PHTTP_REQUEST pRequest; + PCHAR pRequestBuffer; + ULONG RequestBufferLength; + xmlrpc_env env; + char szHeaderBuf[255]; + long lContentLength; + + // Allocate a 2K buffer. Should be good for most requests, we'll grow + // this if required. We also need space for a HTTP_REQUEST structure. + RequestBufferLength = sizeof(HTTP_REQUEST) + 2048; + pRequestBuffer = (PCHAR) ALLOC_MEM( RequestBufferLength ); + if (pRequestBuffer == NULL) + { + return ERROR_NOT_ENOUGH_MEMORY; + } + + pRequest = (PHTTP_REQUEST)pRequestBuffer; + + // Wait for a new request -- This is indicated by a NULL request ID. + HTTP_SET_NULL_ID( &requestId ); + for(;;) + { + RtlZeroMemory(pRequest, RequestBufferLength); + + result = HttpReceiveHttpRequest( + hReqQueue, // Req Queue + requestId, // Req ID + 0, // Flags + pRequest, // HTTP request buffer + RequestBufferLength,// req buffer length + &bytesRead, // bytes received + NULL // LPOVERLAPPED + ); + + if(NO_ERROR == result) + { + // Got a request with a filled buffer. + switch(pRequest->Verb) + { + case HttpVerbPOST: + + TraceW(L"Got a POST request for %ws", + pRequest->CookedUrl.pFullUrl); + + //Check if we need use authorization. + if(parmsP->authfn) + { + xmlrpc_env_init(&env); + if(pRequest->Headers.KnownHeaders[ + HttpHeaderAuthorization].RawValueLength + < 6) + { + xmlrpc_env_set_fault( + &env, XMLRPC_REQUEST_REFUSED_ERROR, + "Authorization header too short."); + } + else + { + //unencode the headers + if(_strnicmp( + "basic", + pRequest->Headers.KnownHeaders[ + HttpHeaderAuthorization].pRawValue,5) + !=0) + { +#ifndef NDEBUG + PCHAR pTmp = (PCHAR) + ALLOC_MEM(pRequest->Headers.KnownHeaders[ + HttpHeaderAuthorization + ].RawValueLength + 1 ); + if( pTmp ) { + strncpy(pTmp, + pRequest->Headers.KnownHeaders[ + HttpHeaderAuthorization + ].pRawValue, + pRequest->Headers.KnownHeaders[ + HttpHeaderAuthorization + ].RawValueLength ); + pTmp[pRequest->Headers.KnownHeaders[ + HttpHeaderAuthorization + ].RawValueLength] = 0; + TraceA("Got HEADER [%s]",pTmp); + FREE_MEM(pTmp); + } +#endif /* #ifndef NDEBUG */ + xmlrpc_env_set_fault( + &env, XMLRPC_REQUEST_REFUSED_ERROR, + "Authorization header does not start " + "with type 'basic'!"); + } + else + { + xmlrpc_mem_block * decoded; + + decoded = + xmlrpc_base64_decode( + &env, + pRequest->Headers.KnownHeaders[ + HttpHeaderAuthorization + ].pRawValue+6, + pRequest->Headers.KnownHeaders[ + HttpHeaderAuthorization + ].RawValueLength-6); + if(!env.fault_occurred) + { + char *pDecodedStr; + char *pUser; + char *pPass; + char *pColon; + + pDecodedStr = (char*) + malloc(decoded->_size+1); + memcpy(pDecodedStr, + decoded->_block, + decoded->_size); + pDecodedStr[decoded->_size]='\0'; + pUser = pPass = pDecodedStr; + pColon=strchr(pDecodedStr,':'); + if(pColon) + { + *pColon='\0'; + pPass=pColon+1; + //The authfn should set env to + //fail if auth is denied. + parmsP->authfn(&env,pUser,pPass); + } + else + { + xmlrpc_env_set_fault( + &env, + XMLRPC_REQUEST_REFUSED_ERROR, + "Decoded auth not of the correct " + "format."); + } + free(pDecodedStr); + } + if(decoded) + XMLRPC_MEMBLOCK_FREE(char, decoded); + } + } + if(env.fault_occurred) + { + //request basic authorization, as the user + //did not provide it. + xmlrpc_env_clean(&env); + TraceW(L"POST request did not provide valid " + L"authorization header."); + result = + SendHttpResponseAuthRequired( hReqQueue, + pRequest); + break; + } + xmlrpc_env_clean(&env); + } + + //Check content type to make sure it is text/xml. + memcpy(szHeaderBuf, + pRequest->Headers.KnownHeaders[ + HttpHeaderContentType + ].pRawValue, + pRequest->Headers.KnownHeaders[ + HttpHeaderContentType + ].RawValueLength); + szHeaderBuf[pRequest->Headers.KnownHeaders[ + HttpHeaderContentType + ].RawValueLength] = '\0'; + if (_stricmp(szHeaderBuf,"text/xml")!=0) + { + //We handle only text/xml data. Anything else + //is not valid. + TraceW(L"POST request had an unrecognized " + L"content-type: %s", szHeaderBuf); + result = SendHttpResponse( + hReqQueue, + pRequest, + 400, + "Bad Request", + NULL + ); + break; + } + + //Check content length to make sure it exists and + //is not too big. + memcpy(szHeaderBuf, + pRequest->Headers.KnownHeaders[ + HttpHeaderContentLength + ].pRawValue, + pRequest->Headers.KnownHeaders[ + HttpHeaderContentLength + ].RawValueLength); + szHeaderBuf[pRequest->Headers.KnownHeaders[ + HttpHeaderContentLength + ].RawValueLength]='\0'; + lContentLength = atol(szHeaderBuf); + if (lContentLength<=0) + { + //Make sure a content length was supplied. + TraceW(L"POST request did not include a " + L"content-length", szHeaderBuf); + result = SendHttpResponse( + hReqQueue, + pRequest, + 411, + "Length Required", + NULL + ); + break; + } + if((size_t) lContentLength > + xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) + { + //Content-length is too big for us to handle + TraceW(L"POST request content-length is too big " + L"for us to handle: %d bytes", + lContentLength); + result = SendHttpResponse( + hReqQueue, + pRequest, + 500, + "content-length too large", + NULL + ); + break; + } + + //our initial validations of POST, content-type, + //and content-length all check out. Collect and + //pass the complete buffer to the XMLRPC-C library + + xmlrpc_env_init(&env); + processRPCCall(&env,hReqQueue, pRequest); + if (env.fault_occurred) + { + //if we fail and it is anything other than a + //network error, we should return a failure + //response to the client. + if (env.fault_code != XMLRPC_NETWORK_ERROR) + { + if (env.fault_string) + result = SendHttpResponse( + hReqQueue, + pRequest, + 500, + env.fault_string, + NULL + ); + else + result = SendHttpResponse( + hReqQueue, + pRequest, + 500, + "Unknown Error", + NULL + ); + } + } + + xmlrpc_env_clean(&env); + break; + + default: + //We handle only POST data. Anything else is not valid. + TraceW(L"Got an unrecognized Verb request for URI %ws", + pRequest->CookedUrl.pFullUrl); + + result = SendHttpResponse( + hReqQueue, + pRequest, + 405, + "Method Not Allowed", + NULL + ); + break; + } + if(result != NO_ERROR) + { + break; + } + + // Reset the Request ID so that we pick up the next request. + HTTP_SET_NULL_ID( &requestId ); + } + else if(result == ERROR_MORE_DATA) + { + // The input buffer was too small to hold the request headers + // We have to allocate more buffer & call the API again. + // + // When we call the API again, we want to pick up the request + // that just failed. This is done by passing a RequestID. + // This RequestID is picked from the old buffer. + requestId = pRequest->RequestId; + + // Free the old buffer and allocate a new one. + RequestBufferLength = bytesRead; + FREE_MEM( pRequestBuffer ); + pRequestBuffer = (PCHAR) ALLOC_MEM( RequestBufferLength ); + + if (pRequestBuffer == NULL) + { + result = ERROR_NOT_ENOUGH_MEMORY; + break; + } + + pRequest = (PHTTP_REQUEST)pRequestBuffer; + + } + else if(ERROR_CONNECTION_INVALID == result && + !HTTP_IS_NULL_ID(&requestId)) + { + // The TCP connection got torn down by the peer when we were + // trying to pick up a request with more buffer. We'll just move + // onto the next request. + HTTP_SET_NULL_ID( &requestId ); + } + else + { + break; + } + + } // for(;;) + + if(pRequestBuffer) + { + FREE_MEM( pRequestBuffer ); + } + + return result; +} + +/* + * SendHttpResponse sends a text/html content type back with + * the user specified status code and reason. Used for returning + * errors to clients. + */ +DWORD +SendHttpResponse( + IN HANDLE hReqQueue, + IN PHTTP_REQUEST pRequest, + IN USHORT StatusCode, + IN PSTR pReason, + IN PSTR pEntityString + ) +{ + HTTP_RESPONSE response; + HTTP_DATA_CHUNK dataChunk; + DWORD result; + DWORD bytesSent; + CHAR szServerHeader[20]; + + // Initialize the HTTP response structure. + INITIALIZE_HTTP_RESPONSE(&response, StatusCode, pReason); + + ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html"); + + StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION); + ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader); + + if(pEntityString) + { + // Add an entity chunk + dataChunk.DataChunkType = HttpDataChunkFromMemory; + dataChunk.FromMemory.pBuffer = pEntityString; + dataChunk.FromMemory.BufferLength = (ULONG) strlen(pEntityString); + + response.EntityChunkCount = 1; + response.pEntityChunks = &dataChunk; + } + + // Since we are sending all the entity body in one call, we don't have + // to specify the Content-Length. + result = HttpSendHttpResponse( + hReqQueue, // ReqQueueHandle + pRequest->RequestId, // Request ID + 0, // Flags + &response, // HTTP response + NULL, // pReserved1 + &bytesSent, // bytes sent (OPTIONAL) + NULL, // pReserved2 (must be NULL) + 0, // Reserved3 (must be 0) + NULL, // LPOVERLAPPED (OPTIONAL) + NULL // pReserved4 (must be NULL) + ); + + if(result != NO_ERROR) + { + TraceW(L"HttpSendHttpResponse failed with %lu", result); + } + + return result; +} + +/* SendHttpResponseAuthRequired sends a 401 status code requesting + * authorization + */ + +DWORD +SendHttpResponseAuthRequired( + IN HANDLE hReqQueue, + IN PHTTP_REQUEST pRequest + ) +{ + HTTP_RESPONSE response; + DWORD result; + DWORD bytesSent; + CHAR szServerHeader[20]; + + // Initialize the HTTP response structure. + INITIALIZE_HTTP_RESPONSE(&response, 401, "Authentication Required"); + + // Add the WWW_Authenticate header. + ADD_KNOWN_HEADER(response, HttpHeaderWwwAuthenticate, + "Basic realm=\"xmlrpc\""); + + StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION); + ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader); + + // Since we are sending all the entity body in one call, we don't have + // to specify the Content-Length. + result = HttpSendHttpResponse( + hReqQueue, // ReqQueueHandle + pRequest->RequestId, // Request ID + 0, // Flags + &response, // HTTP response + NULL, // pReserved1 + &bytesSent, // bytes sent (OPTIONAL) + NULL, // pReserved2 (must be NULL) + 0, // Reserved3 (must be 0) + NULL, // LPOVERLAPPED (OPTIONAL) + NULL // pReserved4 (must be NULL) + ); + + if(result != NO_ERROR) + { + TraceW(L"SendHttpResponseAuthRequired failed with %lu", result); + } + + return result; +} + +/* + * processRPCCall() is called after some validations. The assumption is that + * the request is an HTTP post of content-type text/xml with a content-length + * that is less than the maximum the library can handle. + * + * The caller should check the error status, and if the error was other than + * a network type, respond back to the client to let them know the call failed. + */ +void +processRPCCall( + xmlrpc_env * const envP, + IN HANDLE hReqQueue, + IN PHTTP_REQUEST pRequest + ) +{ + HTTP_RESPONSE response; + DWORD result; + DWORD bytesSent; + PUCHAR pEntityBuffer; + ULONG EntityBufferLength; + ULONG BytesRead; +#define MAX_ULONG_STR ((ULONG) sizeof("4294967295")) + CHAR szContentLength[MAX_ULONG_STR]; + CHAR szServerHeader[20]; + HTTP_DATA_CHUNK dataChunk; + ULONG TotalBytesRead = 0; + xmlrpc_mem_block * body; + xmlrpc_mem_block * output; + + BytesRead = 0; + body = NULL; + output = NULL; + + // Allocate some space for an entity buffer. + EntityBufferLength = 2048; + pEntityBuffer = (PUCHAR) ALLOC_MEM( EntityBufferLength ); + if (pEntityBuffer == NULL) + { + xmlrpc_faultf(envP, "Out of Memory"); + goto Done; + } + + // NOTE: If we had passed the HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY + // flag with HttpReceiveHttpRequest(), the entity would have + // been a part of HTTP_REQUEST (using the pEntityChunks field). + // Since we have not passed that flag, we can be assured that + // there are no entity bodies in HTTP_REQUEST. + if(pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS) + { + //Allocate some space for an XMLRPC memory block. + body = xmlrpc_mem_block_new(envP, 0); + if (envP->fault_occurred) + goto Done; + + // The entity body can be sent over multiple calls. Let's collect all + // of these in a buffer and send the buffer to the xmlrpc-c library + do + { + // Read the entity chunk from the request. + BytesRead = 0; + result = HttpReceiveRequestEntityBody( + hReqQueue, + pRequest->RequestId, + 0, + pEntityBuffer, + EntityBufferLength, + &BytesRead, + NULL + ); + switch(result) + { + case NO_ERROR: + if(BytesRead != 0) + { + XMLRPC_MEMBLOCK_APPEND(char, envP, body, + pEntityBuffer, BytesRead); + if(envP->fault_occurred) + goto Done; + } + break; + + case ERROR_HANDLE_EOF: + // We have read the last request entity body. We can now + // process the suppossed XMLRPC data. + if(BytesRead != 0) + { + XMLRPC_MEMBLOCK_APPEND(char, envP, body, + pEntityBuffer, BytesRead); + if(envP->fault_occurred) + goto Done; + } + + // We will send the response over multiple calls. + // This is achieved by passing the + // HTTP_SEND_RESPONSE_FLAG_MORE_DATA flag. + + // NOTE: Since we are accumulating the TotalBytesRead in + // a ULONG, this will not work for entity bodies that + // are larger than 4 GB. To work with large entity + // bodies, we would have to use a ULONGLONG. + TraceA("xmlrpc_server RPC2 handler processing " + "RPC request."); + + // Process the RPC. + xmlrpc_registry_process_call2( + envP, global_registryP, + XMLRPC_MEMBLOCK_CONTENTS(char, body), + XMLRPC_MEMBLOCK_SIZE(char, body), + NULL, + &output); + if (envP->fault_occurred) + goto Done; + + // Initialize the HTTP response structure. + INITIALIZE_HTTP_RESPONSE(&response, 200, "OK"); + + //Add the content-length + StringCchPrintfA(szContentLength,MAX_ULONG_STR, "%lu", + XMLRPC_MEMBLOCK_SIZE(char, output)); + ADD_KNOWN_HEADER( + response, + HttpHeaderContentLength, + szContentLength ); + + //Add the content-type + ADD_KNOWN_HEADER(response, HttpHeaderContentType, + "text/xml"); + + StringCchPrintfA(szServerHeader,20, + "xmlrpc-c %s",XMLRPC_C_VERSION); + ADD_KNOWN_HEADER(response, HttpHeaderServer, + szServerHeader); + + //send the response + result = HttpSendHttpResponse( + hReqQueue, // ReqQueueHandle + pRequest->RequestId, // Request ID + HTTP_SEND_RESPONSE_FLAG_MORE_DATA, + &response, // HTTP response + NULL, // pReserved1 + &bytesSent, // bytes sent (optional) + NULL, // pReserved2 + 0, // Reserved3 + NULL, // LPOVERLAPPED + NULL // pReserved4 + ); + if(result != NO_ERROR) + { + TraceW(L"HttpSendHttpResponse failed with %lu", + result); + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_NETWORK_ERROR, + "HttpSendHttpResponse failed with %lu", result); + goto Done; + } + + // Send entity body from a memory chunk. + dataChunk.DataChunkType = HttpDataChunkFromMemory; + dataChunk.FromMemory.BufferLength = + (ULONG)XMLRPC_MEMBLOCK_SIZE(char, output); + dataChunk.FromMemory.pBuffer = + XMLRPC_MEMBLOCK_CONTENTS(char, output); + + result = HttpSendResponseEntityBody( + hReqQueue, + pRequest->RequestId, + 0, // This is the last send. + 1, // Entity Chunk Count. + &dataChunk, + NULL, + NULL, + 0, + NULL, + NULL + ); + if(result != NO_ERROR) + { + TraceW(L"HttpSendResponseEntityBody failed " + L"with %lu", result); + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_NETWORK_ERROR, + "HttpSendResponseEntityBody failed with %lu", + result); + goto Done; + } + goto Done; + break; + default: + TraceW(L"HttpReceiveRequestEntityBody failed with %lu", + result); + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_NETWORK_ERROR, + "HttpReceiveRequestEntityBody failed " + "with %lu", result); + goto Done; + } + } while(TRUE); + } + else + { + // This request does not have an entity body. + TraceA("Received a bad request (no body in HTTP post)."); + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Bad POST request (no body)"); + goto Done; + } + +Done: + + if(pEntityBuffer) + FREE_MEM(pEntityBuffer); + + if(output) + XMLRPC_MEMBLOCK_FREE(char, output); + + if(body) + XMLRPC_MEMBLOCK_FREE(char, body); + + return; +} + + + +/* Copyright (C) 2005 by Steven A. Bone, sbone@pobox.com. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_string.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_string.c new file mode 100644 index 0000000..8bf299d --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_string.c @@ -0,0 +1,864 @@ +/*============================================================================= + xmlrpc_string +=============================================================================== + Routines for the "string" type of xmlrpc_value. + + By Bryan Henderson. + + Contributed to the public domain by its author. +=============================================================================*/ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include + +#include "bool.h" +#include "mallocvar.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" + + + +void +xmlrpc_destroyString(xmlrpc_value * const valueP) { + + if (valueP->_wcs_block) + xmlrpc_mem_block_free(valueP->_wcs_block); + + xmlrpc_mem_block_clean(&valueP->_block); +} + + + +static void +verifyNoNulls(xmlrpc_env * const envP, + const char * const contents, + unsigned int const len) { +/*---------------------------------------------------------------------------- + Verify that the character array 'contents', which is 'len' bytes long, + does not contain any NUL characters, which means it can be made into + a passable ASCIIZ string just by adding a terminating NUL. + + Fail if the array contains a NUL. +-----------------------------------------------------------------------------*/ + unsigned int i; + + for (i = 0; i < len && !envP->fault_occurred; ++i) + if (contents[i] == '\0') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, + "String must not contain NUL characters"); +} + + + +#if HAVE_UNICODE_WCHAR + +static void +verifyNoNullsW(xmlrpc_env * const envP, + const wchar_t * const contents, + unsigned int const len) { +/*---------------------------------------------------------------------------- + Same as verifyNoNulls(), but for wide characters. +-----------------------------------------------------------------------------*/ + unsigned int i; + + for (i = 0; i < len && !envP->fault_occurred; i++) + if (contents[i] == '\0') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, + "String must not contain NUL characters"); +} +#endif + + + +static void +validateStringType(xmlrpc_env * const envP, + const xmlrpc_value * const valueP) { + + if (valueP->_type != XMLRPC_TYPE_STRING) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where " + "string type was expected.", + xmlrpc_type_name(valueP->_type)); + } +} + + + +static void +accessStringValue(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const char ** const contentsP) { + + validateStringType(envP, valueP); + if (!envP->fault_occurred) { + unsigned int const size = + XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); + const char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + unsigned int const len = size - 1; + /* The memblock has a null character added to the end */ + + verifyNoNulls(envP, contents, len); + + *lengthP = len; + *contentsP = contents; + } +} + + + +void +xmlrpc_read_string(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP) { +/*---------------------------------------------------------------------------- + Read the value of an XML-RPC string as an ASCIIZ string, with + LF for line delimiters. + + Return the string in newly malloc'ed storage that Caller must free. + + Fail if the string contains null characters (which means it wasn't + really a string, but XML-RPC doesn't seem to understand what a string + is, and such values are possible). +-----------------------------------------------------------------------------*/ + size_t length; + const char * contents; + + accessStringValue(envP, valueP, &length, &contents); + + if (!envP->fault_occurred) { + char * stringValue; + + MALLOCARRAY(stringValue, length + 1); + if (stringValue == NULL) + xmlrpc_faultf(envP, "Unable to allocate space " + "for %u-character string", length); + else { + memcpy(stringValue, contents, length); + stringValue[length] = '\0'; + + *stringValueP = stringValue; + } + } +} + + + +static unsigned int +lineDelimCount(const char * const start, + const char * const end) { + + unsigned int count; + const char * p; + + for (p = start, count = 0; p < end; ) { + const char * const nlPos = memchr(p, '\n', end-p); + if (nlPos) { + ++count; + p = nlPos + 1; + } else + p = end; + } + + return count; +} + + + +static void +copyAndConvertLfToCrlf(xmlrpc_env * const envP, + size_t const srcLen, + const char * const src, + size_t * const dstLenP, + const char ** const dstP) { + + const char * const srcEnd = src + srcLen; + unsigned int const nLineDelim = lineDelimCount(src, srcEnd); + size_t const dstLen = srcLen + nLineDelim; + char * dst; + + MALLOCARRAY(dst, dstLen + 1); + if (dst == NULL) + xmlrpc_faultf(envP, "Unable to allocate space " + "for %u-character string", dstLen + 1); + else { + const char * p; /* source pointer */ + char * q; /* destination pointer */ + + for (p = &src[0], q = &dst[0]; p < srcEnd; ++p) { + if (*p == '\n') + *q++ = '\r'; + + *q++ = *p; + } + XMLRPC_ASSERT(q == dst + dstLen); + + *q = '\0'; + + *dstP = dst; + *dstLenP = dstLen; + } +} + + + +void +xmlrpc_read_string_crlf(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP) { +/*---------------------------------------------------------------------------- + Same as xmlrpc_read_string(), but return CRLF instead of LF for + line delimiters. +-----------------------------------------------------------------------------*/ + size_t length; + const char * contents; + + accessStringValue(envP, valueP, &length, &contents); + + if (!envP->fault_occurred) { + size_t stringLen; + + copyAndConvertLfToCrlf(envP, length, contents, + &stringLen, stringValueP); + } +} + + + +void +xmlrpc_read_string_old(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + const char ** const stringValueP) { + + size_t length; + accessStringValue(envP, valueP, &length, stringValueP); +} + + + +void +xmlrpc_read_string_lp(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const char ** const stringValueP) { + + validateStringType(envP, valueP); + if (!envP->fault_occurred) { + unsigned int const size = + XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); + const char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + + char * stringValue; + + stringValue = malloc(size); + if (stringValue == NULL) + xmlrpc_faultf(envP, "Unable to allocate %u bytes for string.", + size); + else { + memcpy(stringValue, contents, size); + *stringValueP = stringValue; + *lengthP = size - 1; /* Size includes terminating NUL */ + } + } +} + + + +void +xmlrpc_read_string_lp_crlf(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const char ** const stringValueP) { + + validateStringType(envP, valueP); + if (!envP->fault_occurred) { + unsigned int const size = + XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); /* Includes NUL */ + const char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + + copyAndConvertLfToCrlf(envP, size-1, contents, + lengthP, stringValueP); + } +} + + + +void +xmlrpc_read_string_lp_old(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + size_t * const lengthP, + const char ** const stringValueP) { + + validateStringType(envP, valueP); + if (!envP->fault_occurred) { + *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1; + *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + } +} + + + +static __inline__ void +setupWcsBlock(xmlrpc_env * const envP, + xmlrpc_value * const valueP) { +/*---------------------------------------------------------------------------- + Add a wcs block (wchar_t string) to the indicated xmlrpc_value if it + doesn't have one already. +-----------------------------------------------------------------------------*/ + if (!valueP->_wcs_block) { + char * const contents = + XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + size_t const len = + XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1; + valueP->_wcs_block = + xmlrpc_utf8_to_wcs(envP, contents, len + 1); + } +} + + + +#if HAVE_UNICODE_WCHAR + +static void +accessStringValueW(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + size_t * const lengthP, + const wchar_t ** const stringValueP) { + + validateStringType(envP, valueP); + if (!envP->fault_occurred) { + setupWcsBlock(envP, valueP); + + if (!envP->fault_occurred) { + wchar_t * const wcontents = + XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block); + size_t const len = + XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block) - 1; + + verifyNoNullsW(envP, wcontents, len); + + *lengthP = len; + *stringValueP = wcontents; + } + } +} + + + +void +xmlrpc_read_string_w(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const wchar_t ** const stringValueP) { + + size_t length; + const wchar_t * wcontents; + + accessStringValueW(envP, valueP, &length, &wcontents); + + if (!envP->fault_occurred) { + wchar_t * stringValue; + MALLOCARRAY(stringValue, length + 1); + if (stringValue == NULL) + xmlrpc_faultf(envP, "Unable to allocate space for %u-byte string", + length); + else { + memcpy(stringValue, wcontents, length * sizeof(wchar_t)); + stringValue[length] = '\0'; + + *stringValueP = stringValue; + } + } +} + + + +static unsigned int +lineDelimCountW(const wchar_t * const start, + const wchar_t * const end) { + + unsigned int count; + const wchar_t * p; + + count = 0; + p = start; + + while (p && p < end) { + /* We used to use memchr(), but Windows doesn't have it */ + p = wcsstr(p, L"\n"); + if (p && p < end) { + ++count; /* count the newline */ + ++p; /* skip the newline */ + } + } + + return count; +} + + + +static void +wCopyAndConvertLfToCrlf(xmlrpc_env * const envP, + size_t const srcLen, + const wchar_t * const src, + size_t * const dstLenP, + const wchar_t ** const dstP) { + + const wchar_t * const srcEnd = src + srcLen; + unsigned int const nLineDelim = lineDelimCountW(src, srcEnd); + size_t const dstLen = srcLen + nLineDelim; + wchar_t * dst; + + MALLOCARRAY(dst, dstLen + 1); + if (dst == NULL) + xmlrpc_faultf(envP, "Unable to allocate space " + "for %u-character string", dstLen + 1); + else { + const wchar_t * p; /* source pointer */ + wchar_t * q; /* destination pointer */ + + for (p = &src[0], q = &dst[0]; p < srcEnd; ++p) { + if (*p == '\n') + *q++ = '\r'; + + *q++ = *p; + } + XMLRPC_ASSERT(q == dst + dstLen); + + *q = '\0'; + + *dstP = dst; + *dstLenP = dstLen; + } +} + + + +void +xmlrpc_read_string_w_crlf(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const wchar_t ** const stringValueP) { + + size_t size; + const wchar_t * contents; + + accessStringValueW(envP, valueP, &size, &contents); + + if (!envP->fault_occurred) { + size_t stringLen; + + wCopyAndConvertLfToCrlf(envP, size, contents, + &stringLen, stringValueP); + } +} + + + +void +xmlrpc_read_string_w_old(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + const wchar_t ** const stringValueP) { + + size_t length; + + accessStringValueW(envP, valueP, &length, stringValueP); +} + + + +void +xmlrpc_read_string_w_lp(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + size_t * const lengthP, + const wchar_t ** const stringValueP) { + + validateStringType(envP, valueP); + if (!envP->fault_occurred) { + setupWcsBlock(envP, valueP); + + if (!envP->fault_occurred) { + wchar_t * const wcontents = + XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block); + size_t const size = + XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block); + + wchar_t * stringValue; + + MALLOCARRAY(stringValue, size); + if (stringValue == NULL) + xmlrpc_faultf(envP, + "Unable to allocate space for %u-byte string", + (unsigned int)size); + else { + memcpy(stringValue, wcontents, size * sizeof(wchar_t)); + + *lengthP = size - 1; /* size includes terminating NUL */ + *stringValueP = stringValue; + } + } + } +} + + + +void +xmlrpc_read_string_w_lp_crlf(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + size_t * const lengthP, + const wchar_t ** const stringValueP) { + + validateStringType(envP, valueP); + if (!envP->fault_occurred) { + setupWcsBlock(envP, valueP); + + if (!envP->fault_occurred) { + size_t const size = + XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block); + wchar_t * const wcontents = + XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block); + + wCopyAndConvertLfToCrlf(envP, size-1, wcontents, + lengthP, stringValueP); + } + } +} + + + +void +xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP, + xmlrpc_value * const valueP, + size_t * const lengthP, + const wchar_t ** const stringValueP) { + + validateStringType(envP, valueP); + if (!envP->fault_occurred) { + setupWcsBlock(envP, valueP); + + if (!envP->fault_occurred) { + wchar_t * const wcontents = + XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block); + size_t const size = + XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block); + + *lengthP = size - 1; /* size includes terminating NUL */ + *stringValueP = wcontents; + } + } +} +#endif /* HAVE_UNICODE_WCHAR */ + + + +static void +validateUtf(xmlrpc_env * const envP, + const char * const value, + size_t const length) { + +#if HAVE_UNICODE_WCHAR + xmlrpc_validate_utf8(envP, value, length); +#endif +} + + + +static void +copyLines(xmlrpc_env * const envP, + const char * const src, + size_t const srcLen, + xmlrpc_mem_block * const dstP) { +/*---------------------------------------------------------------------------- + Copy the string 'src', 'srcLen' characters long, into 'dst', where + 'dst' is the internal representation of string xmlrpc_value contents, + and 'src' has lines separated by LF, CR, and/or CRLF. + + Note that the source format differs from the destination format in + that in the destination format, lines are separated only by newline + (LF). + + It is tempting to believe that if we just put the user's line + delimiters in the xmlrpc_value here (i.e. where user has CRLF, the + xmlrpc_value also has CRLF), the user's line delimiters would go + all the way across to the XML-RPC partner. But that won't work, + because the XML processor on the other side will, following Section + 2.11 of the XML spec, normalize all line endings to LF anyhow. So + then you might ask, why do we bother to do all the work to convert + them here? Because: besides just being logically cleaner, this way + xmlrpc_read_string() gets the proper value -- the same one the + XML-RPC partner would see. +-----------------------------------------------------------------------------*/ + /* Destination format is sometimes smaller than source (because + CRLF turns into LF), but never smaller. So we allocate + destination space equal to source size (plus one for + terminating NUL), but don't necessarily use it all. + */ + + /* To convert LF, CR, and CRLF to LF, all we have to do is + copy everything up to a CR verbatim, then insert an LF and + skip the CR and any following LF, and repeat. + */ + + XMLRPC_MEMBLOCK_INIT(char, envP, dstP, srcLen + 1); + + if (!envP->fault_occurred) { + const char * const srcEnd = &src[srcLen]; + char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, dstP); + + const char * srcCursor; + char * dstCursor; + + for (srcCursor = &src[0], dstCursor = &contents[0]; + srcCursor < srcEnd;) { + + char * const crPos = memchr(srcCursor, '\r', srcEnd - srcCursor); + + if (crPos) { + size_t const copyLen = crPos - srcCursor; + memcpy(dstCursor, srcCursor, copyLen); + srcCursor += copyLen; + dstCursor += copyLen; + + *(dstCursor++) = '\n'; + + XMLRPC_ASSERT(*srcCursor == '\r'); + ++srcCursor; /* Move past CR */ + if (*srcCursor == '\n') + ++srcCursor; /* Move past LF */ + } else { + size_t const remainingLen = srcEnd - srcCursor; + memcpy(dstCursor, srcCursor, remainingLen); + srcCursor += remainingLen; + dstCursor += remainingLen; + } + } + + *dstCursor++ = '\0'; + + XMLRPC_ASSERT((unsigned)(dstCursor - &contents[0]) <= srcLen + 1); + + XMLRPC_MEMBLOCK_RESIZE(char, envP, dstP, dstCursor - &contents[0]); + } +} + + + +static void +copySimple(xmlrpc_env * const envP, + const char * const src, + size_t const srcLen, + xmlrpc_mem_block * const dstP) { +/*---------------------------------------------------------------------------- + Copy the string 'src', 'srcLen' characters long, into 'dst', where + 'dst' is the internal representation of string xmlrpc_value contents, + and 'src', conveniently enough, is in the exact same format. + + To wit, 'src' has lines separated by LFs only -- no CR or CRLF. +-----------------------------------------------------------------------------*/ + XMLRPC_MEMBLOCK_INIT(char, envP, dstP, srcLen + 1); + if (!envP->fault_occurred) { + char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, dstP); + + memcpy(contents, src, srcLen); + contents[srcLen] = '\0'; + } +} + + + +enum crTreatment { CR_IS_LINEDELIM, CR_IS_CHAR }; + +static xmlrpc_value * +stringNew(xmlrpc_env * const envP, + size_t const length, + const char * const value, + enum crTreatment const crTreatment) { + + xmlrpc_value * valP; + + validateUtf(envP, value, length); + + if (!envP->fault_occurred) { + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_STRING; + valP->_wcs_block = NULL; + + /* Note that copyLines() works for strings with no CRs, but + it's slower. + */ + if (memchr(value, '\r', length) && crTreatment == CR_IS_LINEDELIM) + copyLines(envP, value, length, &valP->_block); + else + copySimple(envP, value, length, &valP->_block); + + if (envP->fault_occurred) + free(valP); + } + } + return valP; +} + + + +xmlrpc_value * +xmlrpc_string_new_lp(xmlrpc_env * const envP, + size_t const length, + const char * const value) { + + return stringNew(envP, length, value, CR_IS_LINEDELIM); +} + + + +xmlrpc_value * +xmlrpc_string_new_lp_cr(xmlrpc_env * const envP, + size_t const length, + const char * const value) { + + return stringNew(envP, length, value, CR_IS_CHAR); +} + + + +xmlrpc_value * +xmlrpc_string_new(xmlrpc_env * const envP, + const char * const value) { + + return stringNew(envP, strlen(value), value, CR_IS_LINEDELIM); +} + + + +xmlrpc_value * +xmlrpc_string_new_cr(xmlrpc_env * const envP, + const char * const value) { + + return stringNew(envP, strlen(value), value, CR_IS_CHAR); +} + + + +xmlrpc_value * +xmlrpc_string_new_va(xmlrpc_env * const envP, + const char * const format, + va_list args) { + + const char * formattedString; + xmlrpc_value * retvalP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(format != NULL); + + xmlrpc_vasprintf(&formattedString, format, args); + + if (formattedString == xmlrpc_strsol) { + xmlrpc_faultf(envP, "Out of memory building formatted string"); + retvalP = NULL; /* defeat compiler warning */ + } else + retvalP = xmlrpc_string_new(envP, formattedString); + + xmlrpc_strfree(formattedString); + + return retvalP; +} + + + +xmlrpc_value * +xmlrpc_string_new_f(xmlrpc_env * const envP, + const char * const format, + ...) { + + va_list args; + xmlrpc_value * retval; + + va_start(args, format); + + retval = xmlrpc_string_new_va(envP, format, args); + + va_end(args); + + return retval; +} + + + +#if HAVE_UNICODE_WCHAR + +static xmlrpc_value * +stringWNew(xmlrpc_env * const envP, + size_t const length, + const wchar_t * const value, + enum crTreatment const crTreatment) { + + xmlrpc_value * valP; + xmlrpc_mem_block * utf8P; + + valP = NULL; /* defeat compiler warning */ + + utf8P = xmlrpc_wcs_to_utf8(envP, value, length); + if (!envP->fault_occurred) { + char * const utf8_value = XMLRPC_MEMBLOCK_CONTENTS(char, utf8P); + size_t const utf8_len = XMLRPC_MEMBLOCK_SIZE(char, utf8P); + + if (!envP->fault_occurred) { + valP = stringNew(envP, utf8_len, utf8_value, crTreatment); + + XMLRPC_MEMBLOCK_FREE(char, utf8P); + } + } + return valP; +} + + + +xmlrpc_value * +xmlrpc_string_w_new_lp(xmlrpc_env * const envP, + size_t const length, + const wchar_t * const value) { + + return stringWNew(envP, length, value, CR_IS_LINEDELIM); +} + + + + +xmlrpc_value * +xmlrpc_string_w_new_lp_cr(xmlrpc_env * const envP, + size_t const length, + const wchar_t * const value) { + + return stringWNew(envP, length, value, CR_IS_CHAR); +} + + + + +xmlrpc_value * +xmlrpc_string_w_new(xmlrpc_env * const envP, + const wchar_t * const value) { + + return stringWNew(envP, wcslen(value), value, CR_IS_LINEDELIM); +} + + + +xmlrpc_value * +xmlrpc_string_w_new_cr(xmlrpc_env * const envP, + const wchar_t * const value) { + + return stringWNew(envP, wcslen(value), value, CR_IS_CHAR); +} + +#endif /* HAVE_UNICODE_WCHAR */ diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_struct.c b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_struct.c new file mode 100644 index 0000000..40c59bb --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/src/xmlrpc_struct.c @@ -0,0 +1,590 @@ +/* Copyright (C) 2001 by First Peer, Inc. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. */ + +#include "xmlrpc_config.h" + +#include +#include +#include + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "int.h" + +#define KEY_ERROR_BUFFER_SZ (32) + + +void +xmlrpc_destroyStruct(xmlrpc_value * const structP) { + + _struct_member * const members = + XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block); + size_t const size = + XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block); + + unsigned int i; + + for (i = 0; i < size; ++i) { + xmlrpc_DECREF(members[i].key); + xmlrpc_DECREF(members[i].value); + } + XMLRPC_MEMBLOCK_CLEAN(_struct_member, &structP->_block); +} + + + +/*========================================================================= +** xmlrpc_struct_new +**========================================================================= +** Create a new value. The corresponding destructor code +** currently lives in xmlrpc_DECREF. +** +** We store the individual members in an array of _struct_member. This +** contains a key, a hash code, and a value. We look up keys by doing +** a linear search of the hash codes. +*/ + +xmlrpc_value * +xmlrpc_struct_new(xmlrpc_env * const envP) { + + xmlrpc_value * valP; + + XMLRPC_ASSERT_ENV_OK(envP); + + xmlrpc_createXmlrpcValue(envP, &valP); + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_STRUCT; + + XMLRPC_MEMBLOCK_INIT(_struct_member, envP, &valP->_block, 0); + + if (envP->fault_occurred) + free(valP); + } + return valP; +} + + + +/*========================================================================= +** xmlrpc_struct_size +**========================================================================= +** Return the number of key-value pairs contained in the struct. If the +** value is not a struct, return -1 and set a fault. +*/ + +int +xmlrpc_struct_size(xmlrpc_env* env, xmlrpc_value* strct) +{ + int retval; + + /* Suppress a compiler warning about uninitialized variables. */ + retval = 0; + + XMLRPC_ASSERT_ENV_OK(env); + XMLRPC_ASSERT_VALUE_OK(strct); + + XMLRPC_TYPE_CHECK(env, strct, XMLRPC_TYPE_STRUCT); + retval = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strct->_block); + + cleanup: + if (env->fault_occurred) + return -1; + return retval; +} + + + +static uint32_t +hashStructKey(const char * const key, + size_t const keyLen) { + + uint32_t hash; + size_t i; + + XMLRPC_ASSERT(key != NULL); + + /* This is the Bernstein hash, optimized for lower case ASCII + keys. Note that the bytes of such a key differ only in their + lower 5 bits. + */ + for (hash = 0, i = 0; i < keyLen; ++i) + hash = hash + key[i] + (hash << 5); + + return hash; +} + + + +/*========================================================================= +** find_member +**========================================================================= +** Get the index of the member with the specified key, or -1 if no such +** member exists. +*/ + +static int +find_member(xmlrpc_value * const strctP, + const char * const key, + size_t const keyLen) { + + size_t size, i; + uint32_t searchHash; + _struct_member * contents; /* array */ + xmlrpc_value * keyvalP; + const char * keystr; + size_t keystrSize; + + XMLRPC_ASSERT_VALUE_OK(strctP); + XMLRPC_ASSERT(key != NULL); + + /* Look for our key. */ + searchHash = hashStructKey(key, keyLen); + size = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strctP->_block); + contents = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block); + for (i = 0; i < size; ++i) { + if (contents[i].keyHash == searchHash) { + keyvalP = contents[i].key; + keystr = XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block); + keystrSize = XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block)-1; + if (keystrSize == keyLen && memcmp(key, keystr, keyLen) == 0) + return i; + } + } + return -1; +} + + + +/*========================================================================= +** xmlrpc_struct_has_key +**========================================================================= +*/ + +int +xmlrpc_struct_has_key(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key) { + + XMLRPC_ASSERT(key != NULL); + return xmlrpc_struct_has_key_n(envP, strctP, key, strlen(key)); +} + + + +int +xmlrpc_struct_has_key_n(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key, + size_t const key_len) { + int index; + + /* Suppress a compiler warning about uninitialized variables. */ + index = 0; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(strctP); + XMLRPC_ASSERT(key != NULL); + + XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT); + index = find_member(strctP, key, key_len); + + cleanup: + if (envP->fault_occurred) + return 0; + return (index >= 0); +} + + + +/*========================================================================= +** xmlrpc_struct_find_value... +**========================================================================= +** These functions look up a specified key value in a specified struct. +** If it exists, they return the value of the struct member. If not, +** they return a NULL to indicate such. +*/ + +/* It would be a nice extension to be able to look up a key that is + not a text string. +*/ + +void +xmlrpc_struct_find_value(xmlrpc_env * const envP, + xmlrpc_value * const structP, + const char * const key, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Given a key, retrieve a value from the struct. If the key is not + present, return NULL as *valuePP. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(structP); + XMLRPC_ASSERT_PTR_OK(key); + + if (structP->_type != XMLRPC_TYPE_STRUCT) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value is not a struct. It is type #%d", + structP->_type); + else { + int index; + + /* Get our member index. */ + index = find_member(structP, key, strlen(key)); + if (index < 0) + *valuePP = NULL; + else { + _struct_member * const members = + XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block); + *valuePP = members[index].value; + + XMLRPC_ASSERT_VALUE_OK(*valuePP); + + xmlrpc_INCREF(*valuePP); + } + } +} + + + +void +xmlrpc_struct_find_value_v(xmlrpc_env * const envP, + xmlrpc_value * const structP, + xmlrpc_value * const keyP, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Given a key, retrieve a value from the struct. If the key is not + present, return NULL as *valuePP. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(structP); + XMLRPC_ASSERT_VALUE_OK(keyP); + + if (structP->_type != XMLRPC_TYPE_STRUCT) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value is not a struct. It is type #%d", + structP->_type); + else { + if (keyP->_type != XMLRPC_TYPE_STRING) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Key value is not a string. " + "It is type #%d", + keyP->_type); + else { + int index; + + /* Get our member index. */ + index = find_member(structP, + XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block), + XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block)-1); + if (index < 0) + *valuePP = NULL; + else { + _struct_member * const members = + XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block); + *valuePP = members[index].value; + + XMLRPC_ASSERT_VALUE_OK(*valuePP); + + xmlrpc_INCREF(*valuePP); + } + } + } +} + + + +/*========================================================================= +** xmlrpc_struct_read_value... +**========================================================================= +** These fail if no member with the specified key exists. +** Otherwise, they are the same as xmlrpc_struct_find_value... +*/ + +void +xmlrpc_struct_read_value_v(xmlrpc_env * const envP, + xmlrpc_value * const structP, + xmlrpc_value * const keyP, + xmlrpc_value ** const valuePP) { + + xmlrpc_struct_find_value_v(envP, structP, keyP, valuePP); + + if (!envP->fault_occurred) { + if (*valuePP == NULL) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%.*s'", + (int)XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block), + XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block)); + } + } +} + + + +void +xmlrpc_struct_read_value(xmlrpc_env * const envP, + xmlrpc_value * const structP, + const char * const key, + xmlrpc_value ** const valuePP) { + + xmlrpc_struct_find_value(envP, structP, key, valuePP); + + if (!envP->fault_occurred) { + if (*valuePP == NULL) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%s'", + key); + /* We should fix the error message to format the key for display */ + } + } +} + + + +/*========================================================================= +** xmlrpc_struct_get_value... +**========================================================================= +** These are for backward compatibility. They used to be the only ones. +** They're deprecated because they don't acquire a reference to the +** value they return. +*/ + +xmlrpc_value * +xmlrpc_struct_get_value_n(xmlrpc_env * const envP, + xmlrpc_value * const structP, + const char * const key, + size_t const keyLen) { + + xmlrpc_value * retval; + xmlrpc_value * keyP; + + keyP = xmlrpc_build_value(envP, "s#", key, keyLen); + if (!envP->fault_occurred) { + xmlrpc_struct_find_value_v(envP, structP, keyP, &retval); + + if (!envP->fault_occurred) { + if (retval == NULL) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, + "No member of struct has key '%.*s'", + (int)keyLen, key); + /* We should fix the error message to format the key + for display */ + } else + /* For backward compatibility. */ + xmlrpc_DECREF(retval); + } + xmlrpc_DECREF(keyP); + } + return retval; +} + + + +xmlrpc_value * +xmlrpc_struct_get_value(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key) { + + XMLRPC_ASSERT(key != NULL); + return xmlrpc_struct_get_value_n(envP, strctP, key, strlen(key)); +} + + + +/*========================================================================= +** xmlrpc_struct_set_value +**========================================================================= +*/ + +void +xmlrpc_struct_set_value(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key, + xmlrpc_value * const valueP) { + + XMLRPC_ASSERT(key != NULL); + xmlrpc_struct_set_value_n(envP, strctP, key, strlen(key), valueP); +} + + + +void +xmlrpc_struct_set_value_n(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + const char * const key, + size_t const keyLen, + xmlrpc_value * const valueP) { + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(key != NULL); + + if (xmlrpc_value_type(strctP) != XMLRPC_TYPE_STRUCT) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, + "Trying to set value in something not a struct. " + "Type is %d; struct is %d", + xmlrpc_value_type(strctP), XMLRPC_TYPE_STRUCT); + else { + xmlrpc_value * keyvalP; + + /* Get the key as an xmlrpc_value */ + keyvalP = xmlrpc_build_value(envP, "s#", key, keyLen); + if (!envP->fault_occurred) + xmlrpc_struct_set_value_v(envP, strctP, keyvalP, valueP); + + xmlrpc_DECREF(keyvalP); + } +} + + + +void +xmlrpc_struct_set_value_v(xmlrpc_env * const envP, + xmlrpc_value * const strctP, + xmlrpc_value * const keyvalP, + xmlrpc_value * const valueP) { + + char *key; + size_t key_len; + int index; + _struct_member *members, *member, new_member; + xmlrpc_value *old_value; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(strctP); + XMLRPC_ASSERT_VALUE_OK(keyvalP); + XMLRPC_ASSERT_VALUE_OK(valueP); + + XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT); + XMLRPC_TYPE_CHECK(envP, keyvalP, XMLRPC_TYPE_STRING); + + key = XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block); + key_len = XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block) - 1; + index = find_member(strctP, key, key_len); + + if (index >= 0) { + /* Change the value of an existing member. (But be careful--the + ** original and new values might be the same object, so watch + ** the order of INCREF and DECREF calls!) */ + members = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block); + member = &members[index]; + + /* Juggle our references. */ + old_value = member->value; + member->value = valueP; + xmlrpc_INCREF(member->value); + xmlrpc_DECREF(old_value); + } else { + /* Add a new member. */ + new_member.keyHash = hashStructKey(key, key_len); + new_member.key = keyvalP; + new_member.value = valueP; + XMLRPC_MEMBLOCK_APPEND(_struct_member, envP, &strctP->_block, + &new_member, 1); + XMLRPC_FAIL_IF_FAULT(envP); + xmlrpc_INCREF(keyvalP); + xmlrpc_INCREF(valueP); + } + +cleanup: + return; +} + + + +/* Note that the order of keys and values is undefined, and may change + when you modify the struct. +*/ + +void +xmlrpc_struct_read_member(xmlrpc_env * const envP, + xmlrpc_value * const structP, + unsigned int const index, + xmlrpc_value ** const keyvalP, + xmlrpc_value ** const valueP) { + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(structP); + XMLRPC_ASSERT_PTR_OK(keyvalP); + XMLRPC_ASSERT_PTR_OK(valueP); + + if (structP->_type != XMLRPC_TYPE_STRUCT) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Attempt to read a struct member " + "of something that is not a struct"); + else { + _struct_member * const members = + XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block); + size_t const size = + XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block); + + if (index >= size) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, "Index %u is beyond the end of " + "the %u-member structure", index, (unsigned int)size); + else { + _struct_member * const memberP = &members[index]; + *keyvalP = memberP->key; + xmlrpc_INCREF(memberP->key); + *valueP = memberP->value; + xmlrpc_INCREF(memberP->value); + } + } +} + + + +void +xmlrpc_struct_get_key_and_value(xmlrpc_env * const envP, + xmlrpc_value * const structP, + int const index, + xmlrpc_value ** const keyvalP, + xmlrpc_value ** const valueP) { +/*---------------------------------------------------------------------------- + Same as xmlrpc_struct_read_member(), except doesn't take a reference + to the returned value. + + This is obsolete. +-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(structP); + XMLRPC_ASSERT_PTR_OK(keyvalP); + XMLRPC_ASSERT_PTR_OK(valueP); + + if (index < 0) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INDEX_ERROR, "Index %d is negative.", index); + else { + xmlrpc_struct_read_member(envP, structP, index, keyvalP, valueP); + if (!envP->fault_occurred) { + xmlrpc_DECREF(*keyvalP); + xmlrpc_DECREF(*valueP); + } + } + if (envP->fault_occurred) { + *keyvalP = NULL; + *valueP = NULL; + } +} diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/transport_config.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/transport_config.h new file mode 100644 index 0000000..1eb23d4 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/transport_config.h @@ -0,0 +1,2 @@ + +#define XMLRPC_DEFAULT_TRANSPORT "curl" diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/version.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/version.h new file mode 100644 index 0000000..60d8fc1 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/version.h @@ -0,0 +1,14 @@ +/* + * In original xmlrpc-c distribution, version.h is generated across multiple directories. + * To avoid that here, everything versioned is placed here + */ + +#define XMLRPC_MAJOR_RELEASE 1 +#define XMLRPC_MINOR_RELEASE 16 +#define XMLRPC_POINT_RELEASE 16 + +#define XMLRPC_VERSION_MAJOR XMLRPC_MAJOR_RELEASE +#define XMLRPC_VERSION_MINOR XMLRPC_MINOR_RELEASE +#define XMLRPC_VERSION_POINT XMLRPC_POINT_RELEASE + +#define XMLRPC_C_VERSION "Xmlrpc-c 1.16.17" diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/xmlrpc_amconfig.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/xmlrpc_amconfig.h new file mode 100644 index 0000000..d82db9d --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/xmlrpc_amconfig.h @@ -0,0 +1,32 @@ +/* xmlrpc_amconfig.h. Generated by configure. */ +/* xmlrpc_amconfig.h is generated by 'configure' from the template + xmlrpc_amconfig.h.in, by virtue of the AM_CONFIG_HEADER() macro in + configure.in. + + In the future, we plan to eliminate this file, because it is a special + tool that requires extra learning. Instead, we will just put logic + directly in configure.in like that for wchar.h, etc. +*/ + +/* The following are related to AC_CHECK_FUNCS macro calls in + configure.in +*/ + +#define HAVE_SETGROUPS 1 +#define HAVE_ASPRINTF 1 +#define HAVE_SETENV 1 +#define HAVE_PSELECT 1 +#define HAVE_WCSNCMP 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_GMTIME_R 1 +#define HAVE_STRCASECMP 1 +/* #undef HAVE_STRICMP */ +/* #undef HAVE__STRICMP */ + + +/* Define if you have the socket library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Name of package */ +#define PACKAGE "xmlrpc-c" diff --git a/ede-bug-tools/ede-bug-report/xmlrpc-c/xmlrpc_config.h b/ede-bug-tools/ede-bug-report/xmlrpc-c/xmlrpc_config.h new file mode 100644 index 0000000..d1dd132 --- /dev/null +++ b/ede-bug-tools/ede-bug-report/xmlrpc-c/xmlrpc_config.h @@ -0,0 +1,156 @@ +/* xmlrpc_config.h is generated from xmlrpc_config.h.in by 'configure'. + + The purpose of this file is to define stuff particular to the build + environment being used to build Xmlrpc-c. Xmlrpc-c source files can + #include this file and have build-environment-independent source code. + + A major goal of this file is to reduce conditional compilation in + the other source files as much as possible. Even more, we want to avoid + having to generate source code particular to a build environment + except in this file. + + This file is NOT meant to be used by any code outside of the + Xmlrpc-c source tree. There is a similar file that gets installed + as that performs the same function for Xmlrpc-c + interface header files that get compiled as part of a user's program. + + This file just uses plain AC_SUBST substitution, the same as + Makefile.config. Wherever you see @XXX@, that gets replaced by the + value of 'configure' variable XXX. + + Logical macros are 0 or 1 instead of the more traditional defined and + undefined. That's so we can distinguish when compiling code between + "false" and some problem with the code. +*/ + +#ifndef XMLRPC_CONFIG_H_INCLUDED +#define XMLRPC_CONFIG_H_INCLUDED + +/* We hope to replace xmlrpc_amconfig.h some day with something that + doesn't require a whole special set of software to build, to make + Xmlrpc-c approachable by dumber developers. +*/ +#include "xmlrpc_amconfig.h" + +#ifndef HAVE_SETGROUPS +#define HAVE_SETGROUPS 0 +#endif +#ifndef HAVE_ASPRINTF +#define HAVE_ASPRINTF 0 +#endif +#ifndef HAVE_SETENV +#define HAVE_SETENV 0 +#endif +#ifndef HAVE_PSELECT +#define HAVE_PSELECT 0 +#endif +#ifndef HAVE_WCSNCMP +#define HAVE_WCSNCMP 1 +#endif +#ifndef HAVE_GETTIMEOFDAY +#define HAVE_GETTIMEOFDAY 0 +#endif +#ifndef HAVE_LOCALTIME_R +#define HAVE_LOCALTIME_R 0 +#endif +#ifndef HAVE_GMTIME_R +#define HAVE_GMTIME_R 0 +#endif +#ifndef HAVE_STRCASECMP +#define HAVE_STRCASECMP 0 +#endif +#ifndef HAVE_STRICMP +#define HAVE_STRICMP 0 +#endif +#ifndef HAVE__STRICMP +#define HAVE__STRICMP 0 +#endif + +#define HAVE_WCHAR_H 1 +#define HAVE_SYS_FILIO_H 0 +#define HAVE_SYS_IOCTL_H 1 + +#define VA_LIST_IS_ARRAY 0 + +#define HAVE_LIBWWW_SSL 0 + +/* Used to mark an unused function parameter */ +#define ATTR_UNUSED __attribute__((__unused__)) + +#define DIRECTORY_SEPARATOR "/" + +#define HAVE_UNICODE_WCHAR HAVE_WCHAR_H + +/* Xmlrpc-c code uses __inline__ to declare functions that should + be compiled as inline code. GNU C recognizes the __inline__ keyword. + Others recognize 'inline' or '__inline' or nothing at all to say + a function should be inlined. + + We could make 'configure' simply do a trial compile to figure out + which one, but for now, this approximation is easier: +*/ +#if (!defined(__GNUC__)) + #if (!defined(__inline__)) + #if (defined(__sgi) || defined(_AIX) || defined(_MSC_VER)) + #define __inline__ __inline + #else + #define __inline__ + #endif + #endif +#endif + +/* MSVCRT means we're using the Microsoft Visual C++ runtime library */ + +#ifdef _MSC_VER +/* The compiler is Microsoft Visual C++. */ + #define MSVCRT _MSC_VER +#else + #define MSVCRT 0 +#endif + +#if MSVCRT + /* The MSVC runtime library _does_ have a 'struct timeval', but it is + part of the Winsock interface (along with select(), which is probably + its intended use), so isn't intended for use for general timekeeping. + */ + #define HAVE_TIMEVAL 0 + #define HAVE_TIMESPEC 0 +#else + #define HAVE_TIMEVAL 1 + /* timespec is Posix.1b. If we need to work on a non-Posix.1b non-Windows + system, we'll have to figure out how to make Configure determine this. + */ + #define HAVE_TIMESPEC 1 +#endif + +#if MSVCRT + #define XMLRPC_VSNPRINTF _vsnprintf +#else + #define XMLRPC_VSNPRINTF vsnprintf +#endif + +#if MSVCRT + #define HAVE_REGEX 0 +#else + #define HAVE_REGEX 1 +#endif + +#if defined(_MSC_VER) +/* Starting with MSVC 8, the runtime library defines various POSIX functions + such as strdup() whose names violate the ISO C standard (the standard + says the strXXX names are reserved for the standard), but warns you of + the standards violation. That warning is 4996, along with other warnings + that tell you you're using a function that Microsoft thinks you + shouldn't. + + Well, POSIX is more important than that element of ISO C, so we disable + that warning. + + FYI, msvcrt also defines _strdup(), etc, which doesn't violate the + naming standard. But since other environments don't define _strdup(), + we can't use it in portable code. +*/ +#pragma warning(disable:4996) +#endif + +#endif